'[(Multivector, Multivector),

- (Multivector2, Multivector2)]; // FIXME: Fill this out.

+ (Multivector2, Multivector2),

+ (EvenVersor, EvenVersor),

+ (EvenVersor2, EvenVersor2),

+ (Translator, Translator),

+ (Translator2, Translator2)]; // FIXME: Fill this out.

let grade_involution_types =

'[(Multivector, Multivector),

'(EvenVersor, EvenVersor, EvenVersor2),

'(EvenVersor, EvenVersor, Translator),

'(EvenVersor, EvenVersor, Translator2),

+ '(EvenVersor, EvenVersor, Point),

+ '(EvenVersor, EvenVersor, Point2),

'(EvenVersor2, EvenVersor2, EvenVersor2),

'(EvenVersor2, EvenVersor2, Translator2),

let norm_types = zip (repeat ('Scalar)) smv_types;

+let versor_inverse_types =

+ commute ['(Multivector, Multivector),

+ '(Multivector2, Multivector2),

+ '(EvenVersor, EvenVersor),

+ '(EvenVersor2, EvenVersor2),

+ '(Translator, Translator),

+ '(Translator2, Translator2)];

let plus_scalar_types = scalar_arg_types 1 plus_types;

let minus_scalar_types = scalar_arg_types 1 minus_types;

let gp_scalar_types = scalar_arg_types 1 gp_types;

+write_op {"pure" => "lc",

+ "types" => ['(Multivector, Multivector, Multivector)]};

write_op {"pure" => "norm2",

"operation" => (\u -> u*(::reverse u)),

"scalar_result" => true};

+write_op {"pure" => "apply_unit_versor",

+ "fortran" => "apply_unit_versor",

+ "operation" => (\u v -> u * v * ::reverse u),

+ "types" => ['(Multivector, Translator, Multivector),

+ '(Point, Translator, Point)]};

+// Some of the type combinations get too complicated to expand

+// apply_unit_versor with write_op.

+pp "apply_unit_versor u v = u*v*(reverse u);\n";

+pp "apply_versor u v = apply_unit_versor u v % norm2 u;\n";

//-------------------------------------------------------------------------

write_scalar_arg {"pure" => "(::+)",