Parcourir la source

реализовал троичный fib код, добавил тесты

kpmy il y a 10 ans
Parent
commit
aa69ea7fe6
6 fichiers modifiés avec 301 ajouts et 270 suppressions
  1. 4 4
      lib/tri/conv.dart
  2. 162 189
      lib/tri/fib.dart
  3. 65 30
      lib/tri/nons.dart
  4. 67 0
      lib/tri/test.dart
  5. 3 3
      lib/tri/trits.dart
  6. 0 44
      web/main.dart

+ 4 - 4
lib/tri/conv.dart

@@ -1,6 +1,6 @@
 part of tri;
 
-List<tryte>splitInt27(int27 x){
+List<tryte> splitInt27(int27 x) {
   List ret = new List(3);
   ret[0] = short((x << 18) >> 18);
   ret[1] = short((x << 9) >> 18);
@@ -8,7 +8,7 @@ List<tryte>splitInt27(int27 x){
   return ret;
 }
 
-int27 mergeTryteList(List<tryte> x){
-  if(x.length!=3) throw new ArgumentError();
+int27 mergeTryteList(List<tryte> x) {
+  if (x.length != 3) throw new ArgumentError();
   return long(x[0]) + (x[1] << 9) + (x[2] << 18);
-}
+}

+ 162 - 189
lib/tri/fib.dart

@@ -1,191 +1,164 @@
 part of tri;
 
-/*
- * MODULE TRiscTernS;
-  (* Троичная зеркально-симметричная арифметика на основании четных степеней золотого сечения ((1+sqrt(5))/2)^x, где x {.. -4, -2, 0, 2, 4 ...} соответственно разряды {-2, -1, 0, 1, 2} *)
-  
-  IMPORT
-    Math, Log:=StdLog;
-    
-  VAR 
-    cache: ARRAY 81 OF REAL;
-  
-  PROCEDURE Valid(IN s: ARRAY OF BYTE): BOOLEAN;
-    VAR i, len, z: INTEGER; ok: BOOLEAN;
-  BEGIN
-    ASSERT(ODD(LEN(s)), 20);
-    i:=0; len:=LEN(s); z:=len DIV 2; ok:=TRUE;
-    WHILE (i<z) & ok DO 
-      ok:=s[i]=s[len-1-i];
-      INC(i);
-    END;
-  RETURN ok;
-  END Valid;
-  
-  PROCEDURE Print(IN s: ARRAY OF BYTE);
-    VAR i: INTEGER;
-  BEGIN
-    ASSERT(ODD(LEN(s)), 20);
-    i:=0; 
-    WHILE i<LEN(s) DO 
-      IF i=(LEN(s) DIV 2) THEN Log.Char("'") END;
-      CASE s[i] OF
-        1: Log.Char('+') |
-        0: Log.Char('0') |
-        -1: Log.Char('-')
-      ELSE HALT(0) END;
-      IF i=(LEN(s) DIV 2) THEN Log.Char("'") END;
-      INC(i)
-    END;
-  END Print;
-  
-  PROCEDURE Dump*(IN s: ARRAY OF BYTE; OUT vs: ARRAY OF CHAR);
-    VAR i: INTEGER;
-  BEGIN
-    ASSERT(ODD(LEN(s)), 20);
-    i:=0; vs:='';
-    WHILE i<LEN(s) DO 
-      IF i=(LEN(s) DIV 2) THEN vs:=vs+"'"+0X; END;
-      CASE s[i] OF
-        1: vs:=vs+'+'+0X |
-        0: vs:=vs+'0'+0X |
-        -1: vs:=vs+'-'+0X
-      ELSE HALT(0) END;
-      IF i=(LEN(s) DIV 2) THEN vs:=vs+"'"+0X END;
-      INC(i)
-    END;
-  END Dump;
-  
-  PROCEDURE Fn(i: INTEGER): REAL;
-  BEGIN
-  RETURN Math.IntPower((1+Math.Sqrt(5))/2, 2*i);
-  END Fn;
-    
-  PROCEDURE Fi(i: INTEGER): REAL;
-    VAR z: INTEGER; res: REAL;
-  BEGIN
-    z:=LEN(cache) DIV 2;
-    IF ABS(i)<=z THEN res:=cache[z+i] ELSE res:=Fn(i) END;
-  RETURN res
-  END Fi;
-    
-  PROCEDURE Ord(IN s: ARRAY OF BYTE): LONGINT;
-    VAR i, len, z: INTEGER; res: REAL;    
-  BEGIN
-    ASSERT(ODD(LEN(s)), 20);
-    len:=LEN(s); z:=len DIV 2; i:=0;
-    res:=0;
-    WHILE i<len DO
-      res:=res+s[i]*Fi(z-i);
-      INC(i);
-    END;
-  RETURN ENTIER(res)
-  END Ord;
-  
-  PROCEDURE Sum(VAR s: ARRAY OF BYTE; z: INTEGER; x: BYTE);
-  BEGIN
-    ASSERT(ODD(LEN(s)), 20); ASSERT(ABS(x) IN {0, 1}, 21); ASSERT(z<LEN(s), 22);
-    CASE s[z] OF
-      0: s[z]:=x |
-      1: IF x=-1 THEN s[z]:=0 ELSE s[z]:=-1; Sum(s, z+1, 1); Sum(s, z-1, 1) END |
-      -1: IF x=1 THEN s[z]:=0 ELSE s[z]:=1; Sum(s, z+1, -1); Sum(s, z-1, -1) END
-    ELSE HALT(0) END;
-  END Sum;
-  
-  PROCEDURE Mul(VAR s: ARRAY OF BYTE; z: INTEGER; x: BYTE);
-  BEGIN
-    ASSERT(ABS(x) IN {0, 1}, 20); ASSERT(z<LEN(s), 21);
-    s[z]:=SHORT(SHORT(s[z]*x));
-  END Mul;
-  
-  PROCEDURE Inc(VAR s: ARRAY OF BYTE);    
-  BEGIN
-    ASSERT(ODD(LEN(s)), 20);
-    Sum(s, LEN(s) DIV 2, 1);
-  END Inc;
-  
-  PROCEDURE Dec(VAR s: ARRAY OF BYTE);    
-  BEGIN
-    ASSERT(ODD(LEN(s)), 20);
-    Sum(s, LEN(s) DIV 2, -1);
-  END Dec;
-  
-  PROCEDURE Bits*(x: LONGINT; OUT s: ARRAY OF BYTE);
-    VAR i, len, z: INTEGER; r, b1, b0: REAL; sign: BYTE;
-    
-    PROCEDURE IsLesser(a, b: REAL): BOOLEAN;
-      CONST C = 1000000;
-    BEGIN
-    RETURN (ENTIER(a*C)) < (ENTIER(b*C))
-    END IsLesser;
-    
-    PROCEDURE Equal(a, b: REAL): BOOLEAN;
-      CONST C = 1000000;
-    BEGIN
-    RETURN (ENTIER(a*C)) = (ENTIER(b*C))
-    END Equal;
-    
-  BEGIN
-    ASSERT(ODD(LEN(s)), 20);
-    len:=LEN(s); z:=len DIV 2; 
-    i:=0; WHILE i<len DO s[i]:=0; INC(i) END;
-    i:=0; r:=ABS(x); b1:=Fi(z+1);
-    WHILE (i<len) & ~Equal(r, 0) DO
-      b0:=Fi(z-i);
-      IF IsLesser(b1, r+b0) OR Equal(b1, r+b0) THEN 
-        Sum(s, i-1, 1); s[i]:=-1; r:=r-b1+b0;
-      ELSIF IsLesser(b0, r) OR Equal(b0, r) THEN
-        s[i]:=1; r:=r-b0;
-      END;
-      INC(i);
-      b1:=b0;
-    END;
-    sign:=SHORT(SHORT(SHORT(ENTIER(Math.Sign(x)))));
-    i:=0; WHILE i<len DO s[i]:=SHORT(SHORT(sign*s[i])); INC(i) END;
-    ASSERT(Valid(s), 60);
-  END Bits;
-  
-  PROCEDURE Add(IN s, t: ARRAY OF BYTE; OUT res: ARRAY OF BYTE);
-  BEGIN
-    
-  END Add;
-  
-  PROCEDURE Do*;
-    VAR s, t: ARRAY 7 OF BYTE; i, max: LONGINT;
-  BEGIN
-    i:=0; WHILE i<LEN(s) DO s[i]:=1; INC(i) END;
-    max:=Ord(s);
-    i:=-max; Bits(i, s);
-    REPEAT
-      Bits(i, t);
-      Log.Int(i); Log.Tab; Bits(i, t);  Print(t); Log.Ln;
-      IF i<max THEN Inc(s) END; INC(i);
-    UNTIL i>max;
-  END Do;
-  
-  PROCEDURE Do2*;
-    VAR s: POINTER TO ARRAY OF BYTE; i, j: INTEGER;
-  BEGIN
-    i:=1;
-    REPEAT
-      NEW(s, i);
-      FOR j:=0 TO i-1 DO s[j]:=1 END;
-      Log.Int(i); Log.Int(Ord(s)); Print(s); Log.Ln;
-      INC(i, 2);
-    UNTIL i=91; (* дальше LONGINT заканчивается *)
-  END Do2;
-  
-  PROCEDURE Init;
-    VAR i, z, len: INTEGER;
-  BEGIN
-    i:=0; len:=LEN(cache); z:=len DIV 2;
-    WHILE i<len DO 
-      cache[i]:=Fn(i-z); 
-      INC(i)
-    END;
-  END Init;
-  
-BEGIN
-  Init
-END TRiscTernS.
-*/
+double fn(int i) {
+  return pow((1 + sqrt(5)) / 2, 2 * i);
+}
+
+double fi(int i) {
+  int z = cache.length ~/ 2;
+  if (i.abs() <= z) return cache[z + i]; else return fn(i);
+}
+
+List<double> init_fib() {
+  List ret = new List(81);
+  int z = ret.length ~/ 2;
+  for (int i = 0; i < ret.length; i++) {
+    ret[i] = fn(i - z);
+  }
+  return ret;
+}
+
+final List<double> cache = init_fib();
+
+class Fib {
+  List<Tril> _trits;
+
+  void _clear([int n = 15]) {
+    _trits = new List(n);
+    for (int i = 0; i < n; i++) {
+      _trits[i] = NULL;
+    }
+  }
+
+  void _sum(int z, Tril x) {
+    if (z >= _trits.length || z < 0) throw new ArgumentError();
+    if (_trits[z] == NULL) {
+      _trits[z] = x;
+    } else if (_trits[z] == TRUE) {
+      if (x == FALSE) {
+        _trits[z] = NULL;
+      } else {
+        _trits[z] = FALSE;
+        _sum(z + 1, TRUE);
+        _sum(z - 1, TRUE);
+      }
+    } else if (_trits[z] == FALSE) {
+      if (x == TRUE) {
+        _trits[z] = NULL;
+      } else {
+        _trits[z] = TRUE;
+        _sum(z + 1, FALSE);
+        _sum(z - 1, FALSE);
+      }
+    }
+  }
+
+  void _mul(int z, Tril x) {
+    _trits[z] = new Tril.fromInt(_trits[z].toInt * x.toInt);
+  }
+
+  factory Fib(int x) {
+    const c = 1000000;
+
+    Function lesser = (double a, double b) {
+      return (a * c).round() < (b * c).round();
+    };
+
+    Function equal = (double a, double b) {
+      return (a * c).round() == (b * c).round();
+    };
+
+    Fib ret = new Fib._new();
+    ret._clear();
+    int z = ret._trits.length ~/ 2;
+    double r = x.abs().toDouble();
+    double b1 = fi(z + 1);
+    int i = 0;
+    while ((i < ret._trits.length) && !equal(r, .0)) {
+      double b0 = fi(z - i);
+      if (lesser(b1, r + b0) || equal(b1, r + b0)) {
+        ret._sum(i - 1, TRUE);
+        ret._trits[i] = FALSE;
+        r = r - b1 + b0;
+      } else if (lesser(b0, r) || equal(b0, r)) {
+        ret._trits[i] = TRUE;
+        r = r - b0;
+      }
+      i++;
+      b1 = b0;
+    }
+    i = 0;
+    while (i < ret._trits.length) {
+      ret._trits[i] = new Tril.fromInt(x.sign * ret._trits[i].toInt);
+      i++;
+    }
+    return ret;
+  }
+
+  factory Fib.parse(String ls) {
+    if (ls.length == 0) return new Fib(0);
+    if (!ls.length.isOdd) throw new ArgumentError();
+
+    Fib ret = new Fib._new();
+    ret._clear(ls.length);
+    String s = ls.toUpperCase();
+    for (int i = s.length - 1; i >= 0; i--) {
+      switch (s[i]) {
+        case "+":
+          ret._trits[i] = TRUE;
+          break;
+        case "-":
+          ret._trits[i] = FALSE;
+          break;
+        case "0":
+          ret._trits[i] = NULL;
+          break;
+      }
+    }
+    return ret;
+  }
+
+  Fib._new([Fib old]) {
+    if (old != null) {
+      _clear(old._trits.length);
+      for (int i = 0; i < _trits.length; i++) {
+        _trits[i] = old._trits[i];
+      }
+    }
+  }
+
+  @override
+  String toString() {
+    String ret = "";
+    for (int i = 0; i < _trits.length; i++) {
+      //if(i == _trits.length ~/ 2) ret = ret+"'";
+      Tril t = _trits[i];
+      if (t == TRUE) ret = ret + "+"; else if (t == NULL) ret = ret + "0"; else ret = ret + "-";
+      //if(i == _trits.length ~/ 2) ret = ret+"'";
+    }
+    return ret;
+  }
+
+  int toInt() {
+    double ret = .0;
+    int z = _trits.length ~/ 2;
+    int i = 0;
+    _trits.forEach((t) {
+      ret = ret + t.toInt * fi(z - i);
+      i++;
+    });
+    return ret.round();
+  }
+
+  Fib inc() {
+    Fib ret = new Fib._new(this);
+    ret._sum(ret._trits.length ~/ 2, TRUE);
+    return ret;
+  }
+
+  Fib dec() {
+    Fib ret = new Fib._new(this);
+    ret._sum(ret._trits.length ~/ 2, FALSE);
+    return ret;
+  }
+}

+ 65 - 30
lib/tri/nons.dart

@@ -30,48 +30,83 @@ class Nons {
         m[i] = r;
         i++;
       }
-    }  
+    }
     String ret = "";
-    if(i==0) ret = "0";
-    else{
+    if (i == 0) ret = "0"; else {
       do {
-            i--;
-            switch(m[i]){
-              case -4: ret = ret+"W"; break;
-              case -3: ret = ret+"X"; break;
-              case -2: ret = ret+"Y"; break;
-              case -1: ret = ret+"Z"; break;
-              case 0: ret = ret+"0"; break;
-              case 1: ret = ret+"1"; break;
-              case 2: ret = ret+"2"; break;
-              case 3: ret = ret+"3"; break;
-              case 4: ret = ret+"4"; break;
-            }
-          } while (i != 0);
+        i--;
+        switch (m[i]) {
+          case -4:
+            ret = ret + "W";
+            break;
+          case -3:
+            ret = ret + "X";
+            break;
+          case -2:
+            ret = ret + "Y";
+            break;
+          case -1:
+            ret = ret + "Z";
+            break;
+          case 0:
+            ret = ret + "0";
+            break;
+          case 1:
+            ret = ret + "1";
+            break;
+          case 2:
+            ret = ret + "2";
+            break;
+          case 3:
+            ret = ret + "3";
+            break;
+          case 4:
+            ret = ret + "4";
+            break;
+        }
+      } while (i != 0);
     }
     return ret;
   }
 
   static int27 parse(String ls) {
-    if(ls.length == 0) return new int27(0);
+    if (ls.length == 0) return new int27(0);
     List<int> m = new List();
     String s = ls.toUpperCase();
-    for(int i = s.length-1; i>=0; i--){
-      switch(s[i]){
-        case "0": m.add(0); break;
-        case "1": m.add(1); break;
-        case "2": m.add(2); break;
-        case "3": m.add(3); break;
-        case "4": m.add(4); break;
-        case "W": m.add(-4); break;
-        case "X": m.add(-3); break;
-        case "Y": m.add(-2); break;
-        case "Z": m.add(-1); break;
+    for (int i = s.length - 1; i >= 0; i--) {
+      switch (s[i]) {
+        case "0":
+          m.add(0);
+          break;
+        case "1":
+          m.add(1);
+          break;
+        case "2":
+          m.add(2);
+          break;
+        case "3":
+          m.add(3);
+          break;
+        case "4":
+          m.add(4);
+          break;
+        case "W":
+          m.add(-4);
+          break;
+        case "X":
+          m.add(-3);
+          break;
+        case "Y":
+          m.add(-2);
+          break;
+        case "Z":
+          m.add(-1);
+          break;
       }
     }
     int ret = m[0];
-    for(int i = 1; i<m.length; i++){
-      ret = ret+(m[i]*pow(9, i));
+    for (int i = 1; i < m.length; i++) {
+      ret = ret + (m[i] * pow(9, i));
     }
     return new int27(ret);
   }

+ 67 - 0
lib/tri/test.dart

@@ -0,0 +1,67 @@
+library tri_test;
+
+import 'package:unittest/unittest.dart';
+import 'package:tri/tri/mathe.dart';
+
+void testTri(){
+  print("$TRUE, $NULL, $FALSE");
+
+    test("basics", () {
+      expect(TRUE, equals(TRUE));
+      expect(FALSE, equals(FALSE));
+      expect(NULL, isNot(equals(TRUE)));
+      expect(~NULL, equals(NULL));
+      expect(~TRUE, equals(FALSE));
+      expect(~FALSE, equals(TRUE));
+      expect(new Tril.fromInt(0), equals(NULL));
+    });
+
+    test("logic", () {
+      expect(TRUE | TRUE, equals(TRUE));
+      expect(FALSE & FALSE, equals(FALSE));
+    });
+
+    print(tryte.min);
+    print(tryte.max);
+    print(int27.min);
+    print(int27.max);
+
+    test("arithmetics", () {
+      expect(new tryte(5) + new tryte.one(), equals(new tryte(6)));
+      expect(short(new int27(40)), equals(new tryte(40)));
+    });
+
+    test("bits", () {
+      expect(new Bits(int27.max).toString(), equals("+++++++++++++++++++++++++++"));
+      expect(new Bits(tryte.max).toString(), equals("000000000000000000+++++++++"));
+      expect(tryte.max, equals(short(new Bits(tryte.max).toInt27())));
+      expect(int27.max, equals(new Bits(int27.max).toInt27()));
+      expect(new Bits(new tryte(1)) << 5, equals((new Bits(new tryte(1)) << 18) >> 13));
+      expect(new int27(1) << 5, equals((new int27(1) << 18) >> 13));
+      expect(new tryte(1) << 5, isNot(equals(short(new tryte(1) << 18) >> 13)));
+      expect(new Bits(new tryte(5))[1], equals(~(new Bits(new tryte(-5))[1])));
+      expect(new Bits(new tryte(0)).incl(5).incl(8).incl(-1).excl(-1), equals(new Bits(new tryte(0)).incl(5).join(new Bits(new tryte(0)).incl(8))));
+    });
+
+    test("conv", () {
+      expect(Nons.intToString(new int27(2342)), equals("32Z2"));
+      expect(Nons.parse("32Z2"), equals(new int27(2342)));
+      expect(mergeTryteList(splitInt27(new int27(4323352435))), equals(new int27(4323352435)));
+      expect(new Fib(-7).toInt(), equals(-7));
+      expect(new Fib(24).toString(), equals("0000++0-0++0000"));
+
+      Function max = (int x) {
+        String ret = "";
+        for (int i = 0; i < x; i++) {
+          ret = ret + "+";
+        }
+        return ret;
+      };
+
+      for (int i = 1; i <= 91; i = i + 2) {
+        expect(new Fib.parse(max(i)), isNotNull);
+        expect(new Fib.parse(max(i)).toInt(), isNotNaN);
+      }
+    });
+
+}

+ 3 - 3
lib/tri/trits.dart

@@ -168,11 +168,11 @@ class Bits {
   Bits.fromInt27(int27 x) {
     _fill(x.toInt(), 27);
   }
-  
-  List<Tril> toList(){
+
+  List<Tril> toList() {
     return _trits.toList();
   }
-  
+
   @override
   String toString() {
     String ret = "";

+ 0 - 44
web/main.dart

@@ -1,49 +1,5 @@
-import 'package:unittest/unittest.dart';
 import 'package:tri/tri/mathe.dart';
 
 void main() {
-  print("$TRUE, $NULL, $FALSE");
 
-  test("basics", () {
-    expect(TRUE, equals(TRUE));
-    expect(FALSE, equals(FALSE));
-    expect(NULL, isNot(equals(TRUE)));
-    expect(~NULL, equals(NULL));
-    expect(~TRUE, equals(FALSE));
-    expect(~FALSE, equals(TRUE));
-    expect(new Tril.fromInt(0), equals(NULL));
-  });
-
-  test("logic", () {
-    expect(TRUE | TRUE, equals(TRUE));
-    expect(FALSE & FALSE, equals(FALSE));
-  });
-
-  print(tryte.min);
-  print(tryte.max);
-  print(int27.min);
-  print(int27.max);
-
-  test("arithmetics", () {
-    expect(new tryte(5) + new tryte.one(), equals(new tryte(6)));
-    expect(short(new int27(40)), equals(new tryte(40)));
-  });
-
-  test("bits", () {
-    expect(new Bits(int27.max).toString(), equals("+++++++++++++++++++++++++++"));
-    expect(new Bits(tryte.max).toString(), equals("000000000000000000+++++++++"));
-    expect(tryte.max, equals(short(new Bits(tryte.max).toInt27())));
-    expect(int27.max, equals(new Bits(int27.max).toInt27()));
-    expect(new Bits(new tryte(1)) << 5, equals((new Bits(new tryte(1)) << 18) >> 13));
-    expect(new int27(1) << 5, equals((new int27(1) << 18) >> 13));
-    expect(new tryte(1) << 5, isNot(equals(short(new tryte(1) << 18) >> 13)));
-    expect(new Bits(new tryte(5))[1], equals(~(new Bits(new tryte(-5))[1])));
-    expect(new Bits(new tryte(0)).incl(5).incl(8).incl(-1).excl(-1), equals(new Bits(new tryte(0)).incl(5).join(new Bits(new tryte(0)).incl(8))));
-  });
-  
-  test("conv", (){
-    expect(Nons.intToString(new int27(2342)), equals("32Z2"));
-    expect(Nons.parse("32Z2"), equals(new int27(2342)));
-    expect(mergeTryteList(splitInt27(new int27(4323352435))), equals(new int27(4323352435)));
-  });
 }