anchor.diff:  import 'dart:async';
   import 'dart:convert';
   import 'dart:math';
  +
  +class Multivector {
  +  static const DIMENSION = 1 << 3;
  +  List<double> _elements;
  +  Multivector.zero() {
  +    _elements = new List<double>(DIMENSION);
  +    for (int i = 0; i < DIMENSION; i++) {
  +      _elements[i] = 0.0;
  +    }
  +  }
  +  Multivector.one() {
  +    _elements = new List<double>(DIMENSION);
  +    for (int i = 0; i < DIMENSION; i++) {
  +      _elements[i] = 0.0;
  +    }
  +    _elements[0] = 1.0;
  +  }
  +  Multivector.basisVector(int i) {
  +    _elements = new List<double>(DIMENSION);
  +    for (int i = 0; i < DIMENSION; i++) {
  +      _elements[i] = 0.0;
  +    }
  +    _elements[1 << i] = 1.0;
  +  }
  +
  +  Multivector(Vector3 v) {
  +    _elements = new List<double>(DIMENSION);
  +    for (int i = 0; i < DIMENSION; i++) {
  +      _elements[i] = 0.0;
  +    }
  +    _elements[1 << 0] = v.x;
  +    _elements[1 << 1] = v.y;
  +    _elements[1 << 2] = v.z;
  +  }
  +
  +  Vector3 get vector {
  +    return new Vector3(_elements[1<<0], _elements[1<<1], _elements[1<<2]);
  +  }
  +
  +  static int _bitCount(int a) {
  +    int c = a;
  +    c = (c & 0x5555555555555555) + ((c >> 1) & 0x5555555555555555);
  +    c = (c & 0x3333333333333333) + ((c >> 2) & 0x3333333333333333);
  +    c = (c & 0x0f0f0f0f0f0f0f0f) + ((c >> 4) & 0x0f0f0f0f0f0f0f0f);
  +    c = (c & 0x00ff00ff00ff00ff) + ((c >> 8) & 0x00ff00ff00ff00ff);
  +    c = (c & 0x0000ffff0000ffff) + ((c >> 16) & 0x0000ffff0000ffff);
  +    c = (c & 0x00000000ffffffff) + ((c >> 32) & 0x00000000ffffffff);
  +    return c;
  +  }
  +  static bool _reorderingSign(int a, int b) {
  +    a = a >> 1;
  +    int sum = 0;
  +    while (a != 0) {
  +      sum = sum + Multivector._bitCount(a & b);
  +      a = a >> 1;
  +    }
  +    return sum & 1 == 1;
  +  }
  +
  +  double normSquare() {
  +    double t = 0.0;
  +    for (int i = 0; i < DIMENSION; i++) {
  +      t += _elements[i] * _elements[i];
  +    }
  +    return t;
  +  }
  +  Multivector reverse() {
  +    Multivector c = new Multivector.zero();
  +    for (int i = 0; i < DIMENSION; i++) {
  +      double t = _elements[i];
  +      c._elements[i] = (Multivector._bitCount(i) & 3) >= 2 ? -t : t;
  +    }
  +    return c;
  +  }
  +  
  +  Multivector inverse() {
  +    Multivector c = new Multivector.zero();
  +    double normsq = normSquare();
  +
  +    for (int i = 0; i < DIMENSION; i++) {
  +      double t = _elements[i] / normsq;
  +      c._elements[i] = (Multivector._bitCount(i) & 3) >= 2 ? -t : t;
  +    }
  +    return c;
  +  }
  +  operator +(Multivector b) {
  +    Multivector c = new Multivector.zero();
  +    for (int i = 0; i < DIMENSION; i++) {
  +      c._elements[i] = _elements[i] + b._elements[i];
  +    }
  +    return c;
  +  }
  +
  +  operator *(Multivector b) {
  +    Multivector c = new Multivector.zero();
  +
  +    for (int i = 0; i < DIMENSION; i++) {
  +      for (int j = 0; j < DIMENSION; j++) {
  +        double t = _elements[i] * b._elements[j];
  +        c._elements[i ^ j] += Multivector._reorderingSign(i, j) ? -t : t;
  +      }
  +    }
  +    return c;
  +  }
  +  operator /(Multivector b) {
  +    return this * b.inverse();
  +  }
  +}
   
   class Renderer {
     Matrix4 _pMatrix;
  
positive.code: 
      startDrag -= new Vector2(0.5, 0.5);
      endDrag -= new Vector2(0.5, 0.5);
      Matrix4 rotation = makeRotation(
          new Vector3(startDrag.x, startDrag.y, -planeDistance),
          new Vector3(endDrag.x, endDrag.y, -planeDistance));
  
  
negative.code: 
      canvas.onMouseMove.listen((MouseEvent e) {
        if (_startDrag != null) {
          Multivector rotation =
              dragRotation(_startDrag, e.client, planeDistance);
          for (int i = 0; i < ROTATION_POWER; i++) {
            _rotation = rotation * _rotation;
          }
  
          _startDrag = e.client;
  