// unit test program for geometry classes: geometry.hh, geometry.cc
// Copyright (C) 2002  Bruce J. Bell

#include "geometry.hh"

#include <stdio.h>
#include <stdlib.h>


// generally used functions
scalar rscal(void) {
  int i=random() % (2*scalar::maxval+1) - scalar::maxval;
  scalar s(i);
  return s;
}


// per-class unittest functions

// point_T1
void point_T1_rand(point_T1& p) {
  p.set_point(rscal(),rscal());
}

void point_T1_checkaffine(const point_T1& p, FILE *f) {
  fprintf(f,"\n  isfront=%d isback=%d isideal=%d fpval=%f fpinv=%f fpangle=%f",
	  p.isfront(),
	  p.isback(),
	  p.isideal(),
	  p.fpval(),
	  p.fpinv(),
	  p.fpangle()
	  );
}

void test_point_T1(FILE *f) {
  bool flag;

  fprintf(f,"\nunit-testing class point_T1:\n");
  srandom(1); // random number seed (should be set once per subtest...)

  point_T1 p1,p2,p3,p4,p5;
  assert(p1.isnull());

  fprintf(f,"\n-----  point_T1():");
  fprintf(f,"\n-----dump(): ");  p1.dump(f);
  fprintf(f,"\n-----analyze(): "); flag= p1.analyze(f);
  fprintf(f,"-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", p1.ok());

  point_T1 p(10,21);
  fprintf(f,"\n-----  point_T1(10,21):");
  fprintf(f,"\n-----dump(): ");  p.dump(f);
  fprintf(f,"\n-----analyze(): "); flag= p.analyze(f);
  fprintf(f,"-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", p.ok());

  point_T1_rand(p1);
  point_T1_rand(p2);
  fprintf(f,"\n-----randomized: p1=");  p1.dump(f);
  fprintf(f,"\n-----randomized: p2=");  p2.dump(f);

  for(int i=0; i<2; i++) {
    fprintf(f,"\n-----p1.get_val(%d)=%d; p1[%d]=%d",
	    i, p1.get_val(i).toint(), i, p1[i].toint() );
  }

  p3.set_point(30,50);
  fprintf(f,"\n-----p3.set_point(30,50) -> "); p3.dump(f);
  p3.set_point(p1);
  fprintf(f,"\n-----p3.set_point(p1) -> "); p3.dump(f);
  p3.set_null();
  fprintf(f,"\n-----p3.set_null() -> "); p3.dump(f);
  p3.set_anti(p1);
  fprintf(f,"\n-----p3.set_anti(p1) -> "); p3.dump(f);

  p4.set_dual_right(p1);
  fprintf(f,"\n-----p4.set_dual_right(p1) -> "); p4.dump(f);
  p3.set_dual_left(p4);
  fprintf(f,"\n-----p3.set_dual_left(p4) -> "); p3.dump(f);
  p3.set_dual_right(p4);
  fprintf(f,"\n-----p3.set_dual_right(p4) -> "); p3.dump(f);
  fprintf(f,"\n-----p1(p4) = %d", p1(p4).toint());
  fprintf(f,"\n-----p4(p1) = %d", p4(p1).toint());

  p5.set_dual_left(p1);
  fprintf(f,"\n-----p5.set_dual_left(p1) -> "); p5.dump(f);
  p3.set_dual_right(p5);
  fprintf(f,"\n-----p3.set_dual_right(p5) -> "); p3.dump(f);
  p3.set_dual_left(p5);
  fprintf(f,"\n-----p3.set_dual_left(p5) -> "); p3.dump(f);
  fprintf(f,"\n-----p1(p5) = %d", p1(p5).toint());
  fprintf(f,"\n-----p5(p1) = %d", p5(p1).toint());

  fprintf(f,"\n-----p4(p5) = %d", p4(p5).toint());
  fprintf(f,"\n-----p5(p4) = %d", p5(p4).toint());

  fprintf(f,"\n");

  fprintf(f,"\n-----p1.dot(p1) = %d", p1.dot(p1).toint());
  fprintf(f,"\n-----p1.det(p1) = %d", p1.det(p1).toint());
  fprintf(f,"\n-----p2.dot(p2) = %d", p2.dot(p2).toint());
  fprintf(f,"\n-----p2.det(p2) = %d", p2.det(p2).toint());
  fprintf(f,"\n");

  fprintf(f,"\n-----p1.dot(p4) = %d", p1.dot(p4).toint());
  fprintf(f,"\n-----p1.det(p4) = %d", p1.det(p4).toint());
  fprintf(f,"\n-----p1.dot(p5) = %d", p1.dot(p5).toint());
  fprintf(f,"\n-----p1.det(p5) = %d", p1.det(p5).toint());
  fprintf(f,"\n-----p4.dot(p5) = %d", p4.dot(p5).toint());
  fprintf(f,"\n-----p4.det(p5) = %d", p4.det(p5).toint());
  fprintf(f,"\n");

  fprintf(f,"\n-----p1.dot(p2) = %d", p1.dot(p2).toint());
  fprintf(f,"\n-----p2.dot(p1) = %d", p2.dot(p1).toint());
  fprintf(f,"\n-----p1.dot(p1) = %d", p1.dot(p1).toint());
  fprintf(f,"\n-----p2.dot(p2) = %d", p2.dot(p2).toint());
  fprintf(f,"\n");
  fprintf(f,"\n-----p1.det(p2) = %d", p1.det(p2).toint());
  fprintf(f,"\n-----p2.det(p1) = %d", p2.det(p1).toint());
  fprintf(f,"\n-----p1.det(p1) = %d", p1.det(p1).toint());
  fprintf(f,"\n-----p2.det(p2) = %d", p2.det(p2).toint());
  fprintf(f,"\n");

  fprintf(f,"\n-----p1.eval_point(p2) = %d", p1.eval_point(p2).toint());
  fprintf(f,"\n-----p1*p2=  %d; p2*p1= %d", (p1*p2).toint(), (p2*p1).toint());
  fprintf(f,"\n-----p1(p2)= %d; p2(p1)= %d", p1(p2).toint(), p2(p1).toint());

  // affine methods
  p3.set_null();
  fprintf(f,"\n-----p3.set_null() -> "); p3.dump(f);
  point_T1_checkaffine(p3,f);
  p3.set_point(0,10);
  fprintf(f,"\n-----p3 -> "); p3.dump(f);
  point_T1_checkaffine(p3,f);
  p3.set_point(34,0);
  fprintf(f,"\n-----p3 -> "); p3.dump(f);
  point_T1_checkaffine(p3,f);
  p3.set_point(0,-28);
  fprintf(f,"\n-----p3 -> "); p3.dump(f);
  point_T1_checkaffine(p3,f);
  p3.set_point(-55,0);
  fprintf(f,"\n-----p3 -> "); p3.dump(f);
  point_T1_checkaffine(p3,f);
  p3.set_point(-80,-90);
  fprintf(f,"\n-----p3 -> "); p3.dump(f);
  point_T1_checkaffine(p3,f);
  p3.set_point(100,111);
  fprintf(f,"\n-----p3 -> "); p3.dump(f);
  point_T1_checkaffine(p3,f);


  fprintf(f,"\nend unit-test for point_T1.\n\n\n");
} // end function test_point_T1


// base_T2
void base_T2_rand(base_T2& b) {
  b.set_base(rscal(),rscal(),rscal());
}

void test_base_T2(FILE *f) {
  bool flag;

  fprintf(f,"\nunit-testing class base_T2:\n");
  srandom(3); // random number seed for this subtest

  base_T2 b1,b2,b3,b4,b5;
  assert(b1.isnull());

  fprintf(f,"\n-----  base_T2():");
  fprintf(f,"\n-----dump(): "); b1.dump(f);
  fprintf(f,"\n-----analyze(): "); flag= b1.analyze(f);
  fprintf(f,"-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", b1.ok());

  base_T2 b(44,-56,68);
  fprintf(f,"\n-----  base_T2(44,-56,68):");
  fprintf(f,"\n-----dump(): "); b.dump(f);
  fprintf(f,"\n-----analyze(): "); flag= b.analyze(f);
  fprintf(f,"-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", b.ok());

  base_T2_rand(b1);
  base_T2_rand(b2);
  base_T2_rand(b3);
  fprintf(f,"\n-----randomized: b1=");  b1.dump(f);
  fprintf(f,"\n-----randomized: b2=");  b2.dump(f);
  fprintf(f,"\n-----randomized: b3=");  b3.dump(f);

  for(int i=0; i<3; i++) {
    fprintf(f,"\n----- b1.get_val(%d)=%d; b1[%d]=%d",
	    i, b1.get_val(i).toint(), i, b1[i].toint() );
  }

  b4.set_base(20,30,-110);
  fprintf(f,"\n-----b4.set_base(20,30,-110) -> ");  b4.dump(f);
  b4.set_base(b1);
  fprintf(f,"\n-----b4.set_base(b1) -> "); b4.dump(f);
  b4.set_null();
  fprintf(f,"\n-----b4.set_null() -> "); b4.dump(f);
  b4.set_anti(b1);
  fprintf(f,"\n-----b4.set_anti(b1) -> "); b4.dump(f);
  fprintf(f,"\n");

  b4.set_cross(b1,b2);
  fprintf(f,"\n-----b4.set_cross(b1,b2) -> "); b4.dump(f);
  b5.set_cross(b2,b1);
  fprintf(f,"\n-----b5.set_cross(b2,b1) -> "); b5.dump(f);
  fprintf(f,"\n");

  fprintf(f,"\n-----b1.dot(b1) = %d", b1.dot(b1).toint());
  fprintf(f,"\n-----b2.dot(b1) = %d", b2.dot(b1).toint());
  fprintf(f,"\n-----b3.dot(b1) = %d", b3.dot(b1).toint());

  fprintf(f,"\n-----b1.dot(b2) = %d", b1.dot(b2).toint());
  fprintf(f,"\n-----b2.dot(b2) = %d", b2.dot(b2).toint());
  fprintf(f,"\n-----b3.dot(b2) = %d", b3.dot(b2).toint());

  fprintf(f,"\n-----b1.dot(b3) = %d", b1.dot(b3).toint());
  fprintf(f,"\n-----b2.dot(b3) = %d", b2.dot(b3).toint());
  fprintf(f,"\n-----b3.dot(b3) = %d", b3.dot(b3).toint());
  fprintf(f,"\n");

  fprintf(f,"\n-----b4.dot(b1) = %d", b4.dot(b1).toint());
  fprintf(f,"\n-----b4.dot(b2) = %d", b4.dot(b2).toint());
  fprintf(f,"\n-----b4.dot(b3) = %d", b4.dot(b3).toint());

  fprintf(f,"\n-----b5.dot(b1) = %d", b5.dot(b1).toint());
  fprintf(f,"\n-----b5.dot(b2) = %d", b5.dot(b2).toint());
  fprintf(f,"\n-----b5.dot(b3) = %d", b5.dot(b3).toint());

  fprintf(f,"\n-----b4.dot(b4) = %d", b4.dot(b4).toint());
  fprintf(f,"\n-----b5.dot(b5) = %d", b5.dot(b5).toint());
  fprintf(f,"\n-----b5.dot(b4) = %d", b5.dot(b4).toint());
  fprintf(f,"\n");

  fprintf(f,"\n-----b1.det(b2,b3) = %d", b1.det(b2,b3).toint());
  fprintf(f,"\n-----b2.det(b3,b1) = %d", b2.det(b3,b1).toint());
  fprintf(f,"\n-----b3.det(b1,b2) = %d", b3.det(b1,b2).toint());
  fprintf(f,"\n-----b1.det(b3,b2) = %d", b1.det(b3,b2).toint());
  fprintf(f,"\n-----b2.det(b1,b3) = %d", b2.det(b1,b3).toint());
  fprintf(f,"\n-----b3.det(b2,b1) = %d", b3.det(b2,b1).toint());
  fprintf(f,"\n");

  fprintf(f,"\n-----b2.det(b1,b1) = %d", b2.det(b1,b1).toint());
  fprintf(f,"\n-----b1.det(b2,b1) = %d", b1.det(b2,b1).toint());
  fprintf(f,"\n-----b1.det(b1,b2) = %d", b1.det(b1,b2).toint());
  fprintf(f,"\n-----b3.det(b3,b3) = %d", b3.det(b3,b3).toint());
  fprintf(f,"\n");

  fprintf(f,"\nend unit-test for base_T2.\n\n\n");
} // end test_base_T2()


// point_T2, line_T2
void point_T2_rand(point_T2& p) {
  base_T2_rand((base_T2&)p);
}
void line_T2_rand(line_T2& d) {
  base_T2_rand((base_T2&)d);
}

void point_T2_checkaffine(point_T2& p, FILE *f) {
  fprintf(f,"\n  isfront=%d isback=%d isideal=%d",
	  p.isfront(),p.isback(),p.isideal());
  fprintf(f, "\n  fpX=%f fpXinv=%f fpY=%f fpYinv=%f",
	  p.fpX(),p.fpXinv(),p.fpY(),p.fpYinv());
}

void line_T2_checkaffine(line_T2& d, FILE *f) {
  fprintf(f,"\n  isideal=%d", d.isideal());
  point_T2 p;  d.get_dir(p);
  fprintf(f,"\n  get_dir() = "); p.dump(f);
}

void test_point_line_T2(FILE *f) {
  bool flag;

  fprintf(f,"\nunit-testing classes point_T2 and line_T2:\n");
  srandom(4); // random number seed (should be set once per subtest)

  point_T2 p1,p2,p3,p4,p5;
  line_T2 d1,d2,d3,d4,d5;
  assert(p1.isnull());
  assert(d1.isnull());

  fprintf(f,"\n-----point_T2:");
  fprintf(f,"\n-----dump(): "); p1.dump(f);
  fprintf(f,"\n-----analyze(): "); flag= p1.analyze(f);
  fprintf(f,"-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", p1.ok());

  point_T2 p(-66,6,42);
  fprintf(f,"\n-----point_T2(-66,6,42):");
  fprintf(f,"\n-----dump(): "); p.dump(f);
  fprintf(f,"\n-----analyze(): "); flag= p.analyze(f);
  fprintf(f,"-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", p.ok());

  fprintf(f,"\n-----line_T2:");
  fprintf(f,"\n-----dump(): "); d1.dump(f);
  fprintf(f,"\n-----analyze(): "); flag= d1.analyze(f);
  fprintf(f,"-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", d1.ok());

  line_T2 d(-21,-55,-40);
  fprintf(f,"\n-----line_T2(-21,-55,-40):");
  fprintf(f,"\n-----dump(): "); d.dump(f);
  fprintf(f,"\n-----analyze(): "); flag= d.analyze(f);
  fprintf(f,"-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", d.ok());

  point_T2_rand(p1);
  point_T2_rand(p2);
  point_T2_rand(p3);
  fprintf(f,"\n-----randomized: p1="); p1.dump(f);
  fprintf(f,"\n-----randomized: p2="); p2.dump(f);
  fprintf(f,"\n-----randomized: p3="); p3.dump(f);
  for(int i=0; i<3; i++) {
    fprintf(f,"\n----- p1.get_val(%d)=%d; p1[%d]=%d",
	    i, p1.get_val(i).toint(), i, p1[i].toint() );
  }

  line_T2_rand(d1);
  line_T2_rand(d2);
  line_T2_rand(d3);
  fprintf(f,"\n-----randomized: d1="); d1.dump(f);
  fprintf(f,"\n-----randomized: d2="); d2.dump(f);
  fprintf(f,"\n-----randomized: d3="); d3.dump(f);
  for(int i=0; i<3; i++) {
    fprintf(f,"\n----- d1.get_val(%d)=%d; d1[%d]=%d",
	    i, d1.get_val(i).toint(), i, d1[i].toint() );
  }

  p4.set_point(30,40,50);
  fprintf(f,"\n-----p4.set_point(30,40,50) -> ");  p4.dump(f);
  p4.set_point(p1);
  fprintf(f,"\n-----p4.set_point(p1) -> "); p4.dump(f);
  p4.set_anti(p1);
  fprintf(f,"\n-----p4.set_anti(p1) -> "); p4.dump(f);

  d4.set_line(70,80,90);
  fprintf(f,"\n-----d4.set_line(70,80,90) -> "); d4.dump(f);
  d4.set_line(d1);
  fprintf(f,"\n-----d4.set_line(d1) -> "); d4.dump(f);
  d4.set_anti(d1);
  fprintf(f,"\n-----d4.set_anti(d1) -> "); d4.dump(f);

  fprintf(f,"\n");

  // mixed operations
  p4.set_meet_lines(d1,d2);
  fprintf(f,"\n-----p4.set_meet_lines(d1,d2) -> "); p4.dump(f);
  fprintf(f,"\n-----p4(d1) = %d", p4(d1).toint());
  fprintf(f,"\n-----p4(d2) = %d", p4(d2).toint());
  fprintf(f,"\n-----p4(d3) = %d", p4(d3).toint());

  d4.set_join_points(p1,p2);
  fprintf(f,"\n-----d4.set_join_points(p1,p2) -> "); d4.dump(f);
  fprintf(f,"\n-----d4(p1) = %d", d4(p1).toint());
  fprintf(f,"\n-----d4(p2) = %d", d4(p2).toint());
  fprintf(f,"\n-----d4(p3) = %d", d4(p3).toint());
  fprintf(f,"\n");

  p5.set_dual(d1);
  fprintf(f,"\n-----p5.set_dual(d1) -> "); p5.dump(f);
  d4.set_dual(p5);
  fprintf(f,"\n-----d4.set_dual(p5) -> "); d4.dump(f);
  fprintf(f,"\n-----d1(p5) = %d", d1(p5).toint());
  fprintf(f,"\n-----p5(d1) = %d", p5(d1).toint());

  d5.set_dual(p1);
  fprintf(f,"\n-----d5.set_dual(p1) -> "); d5.dump(f);
  p4.set_dual(d5);
  fprintf(f,"\n-----p4.set_dual(d5) -> "); p4.dump(f);
  fprintf(f,"\n-----p1(d5) = %d", p1(d5).toint());
  fprintf(f,"\n-----d5(p1) = %d", d5(p1).toint());

  fprintf(f,"\n-----p5(d5) = %d", p5(d5).toint());
  fprintf(f,"\n-----d5(p5) = %d", d5(p5).toint());

  fprintf(f,"\n");

  fprintf(f,"\n-----p1.eval_line(d1) = %d", p1.eval_line(d1).toint());
  fprintf(f,"\n-----p1*d1 = %d", (p1*d1).toint());
  fprintf(f,"\n-----p1(d1) = %d", p1(d1).toint());

  fprintf(f,"\n-----d1.eval_point(p1) = %d", d1.eval_point(p1).toint());
  fprintf(f,"\n-----d1*p1 = %d", (d1*p1).toint());
  fprintf(f,"\n-----d1(p1) = %d", d1(p1).toint());
  fprintf(f,"\n");

  // affine methods
  p4.set_null();
  fprintf(f,"\n-----p4.set_null() -> "); p4.dump(f);
  point_T2_checkaffine(p4,f);
  p4.set_point(0,14,22);
  fprintf(f,"\n-----p4 -> "); p4.dump(f);
  point_T2_checkaffine(p4,f);
  p4.set_point(20,60,75);
  fprintf(f,"\n-----p6 -> "); p4.dump(f);
  point_T2_checkaffine(p4,f);
  p4.set_point(-44,97,28);
  fprintf(f,"\n-----p4 -> "); p4.dump(f);
  point_T2_checkaffine(p4,f);
  p4.set_point(0,127,-31);
  fprintf(f,"\n-----p4 -> "); p4.dump(f);
  point_T2_checkaffine(p4,f);
  p4.set_point(1,35,100);
  fprintf(f,"\n-----p4 -> "); p4.dump(f);
  point_T2_checkaffine(p4,f);
  p4.set_point(-1,88,93);
  fprintf(f,"\n-----p4 -> "); p4.dump(f);
  point_T2_checkaffine(p4,f);

  d4.set_line(12,24,48);
  fprintf(f,"\n-----d4 -> "); d4.dump(f);
  line_T2_checkaffine(d4,f);
  d4.set_line(99,0,0);
  fprintf(f,"\n-----d4 -> "); d4.dump(f);
  line_T2_checkaffine(d4,f);
  d4.set_line(1,0,0);
  fprintf(f,"\n-----d4 -> "); d4.dump(f);
  line_T2_checkaffine(d4,f);
  d4.set_line(55,1,-1);
  fprintf(f,"\n-----d6 -> "); d4.dump(f);
  line_T2_checkaffine(d4,f);


  fprintf(f,"\nend unit-test for point_T2 and line_T2.\n\n\n");
} // end test_point_line_T2()


// base_T3
void base_T3_rand(base_T3& b) {
  b.set_base(rscal(),rscal(),rscal(),rscal());
}

void test_base_T3(FILE *f) {
  bool flag;

  fprintf(f,"\nunit-testing class base_T3:\n");
  srandom(10); // random number seed for this subtest

  base_T3 b1,b2,b3,b4,b5;
  assert(b1.isnull());

  fprintf(f,"\n-----  base_T3():");
  fprintf(f,"\n-----dump(): "); b1.dump(f);
  fprintf(f,"\n-----analyze(): "); flag= b1.analyze(f);
  fprintf(f,"-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", b1.ok());

  base_T3 b(42,-62,-82,-102);
  fprintf(f,"\n-----  base_T3(-42,-62,-82,-102):");
  fprintf(f,"\n-----dump(): "); b.dump(f);
  fprintf(f,"\n-----analyze(): "); flag= b.analyze(f);
  fprintf(f,"-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", b.ok());

  base_T3_rand(b1);
  base_T3_rand(b2);
  base_T3_rand(b3);
  base_T3_rand(b4);
  fprintf(f,"\n-----randomized: b1=");  b1.dump(f);
  fprintf(f,"\n-----randomized: b2=");  b2.dump(f);
  fprintf(f,"\n-----randomized: b3=");  b3.dump(f);
  fprintf(f,"\n-----randomized: b4=");  b4.dump(f);

  for(int i=0; i<4; i++) {
    fprintf(f,"\n----- b1.getval(%d)=%d; b1[%d]=%d",
	    i, b1.get_val(i).toint(), i, b1[i].toint() );
  }

  b5.set_base(45,22,110,-86);
  fprintf(f,"\n-----b5.set_base(45,22,110,-86) -> "); b5.dump(f);
  b5.set_base(b1);
  fprintf(f,"\n-----b5.set_base(b1) -> "); b5.dump(f);
  b5.set_null();
  fprintf(f,"\n-----b5.set_null() -> "); b5.dump(f);
  b5.set_anti(b1);
  fprintf(f,"\n-----b5.set_anti(b1) -> "); b5.dump(f);
  fprintf(f,"\n");

  fprintf(f,"\n-----b1.dot(b1) = %d", b1.dot(b1).toint());
  fprintf(f,"\n-----b2.dot(b1) = %d", b2.dot(b1).toint());
  fprintf(f,"\n-----b3.dot(b1) = %d", b3.dot(b1).toint());
  fprintf(f,"\n-----b4.dot(b1) = %d", b4.dot(b1).toint());

  fprintf(f,"\n-----b1.dot(b2) = %d", b1.dot(b2).toint());
  fprintf(f,"\n-----b2.dot(b2) = %d", b2.dot(b2).toint());
  fprintf(f,"\n-----b3.dot(b2) = %d", b3.dot(b2).toint());
  fprintf(f,"\n-----b4.dot(b2) = %d", b4.dot(b2).toint());

  fprintf(f,"\n-----b1.dot(b3) = %d", b1.dot(b3).toint());
  fprintf(f,"\n-----b2.dot(b3) = %d", b2.dot(b3).toint());
  fprintf(f,"\n-----b3.dot(b3) = %d", b3.dot(b3).toint());
  fprintf(f,"\n-----b4.dot(b3) = %d", b4.dot(b3).toint());

  fprintf(f,"\n-----b1.dot(b4) = %d", b1.dot(b4).toint());
  fprintf(f,"\n-----b2.dot(b4) = %d", b2.dot(b4).toint());
  fprintf(f,"\n-----b3.dot(b4) = %d", b3.dot(b4).toint());
  fprintf(f,"\n-----b4.dot(b4) = %d", b4.dot(b4).toint());
  fprintf(f,"\n");

  fprintf(f,"\n-----b1.det(b2,b3,b4) = %d", b1.det(b2,b3,b4).toint());
  fprintf(f,"\n-----b2.det(b3,b4,b1) = %d", b2.det(b3,b4,b1).toint());
  fprintf(f,"\n-----b3.det(b4,b1,b2) = %d", b3.det(b4,b1,b2).toint());
  fprintf(f,"\n-----b4.det(b1,b2,b3) = %d", b4.det(b1,b2,b3).toint());

  fprintf(f,"\n-----b4.det(b3,b2,b1) = %d", b4.det(b3,b2,b1).toint());
  fprintf(f,"\n-----b3.det(b2,b1,b4) = %d", b3.det(b2,b1,b4).toint());
  fprintf(f,"\n-----b2.det(b1,b4,b3) = %d", b2.det(b1,b4,b3).toint());
  fprintf(f,"\n-----b1.det(b4,b3,b2) = %d", b1.det(b4,b3,b2).toint());

  fprintf(f,"\n-----b1.det(b2,b4,b3) = %d", b1.det(b2,b4,b3).toint());
  fprintf(f,"\n-----b2.det(b1,b3,b4) = %d", b2.det(b1,b3,b4).toint());
  fprintf(f,"\n-----b2.det(b1,b4,b3) = %d", b2.det(b1,b4,b3).toint());
  fprintf(f,"\n-----b3.det(b4,b1,b2) = %d", b3.det(b4,b1,b2).toint());
  fprintf(f,"\n");

  fprintf(f,"\n-----b1.det(b2,b3,b1) = %d", b1.det(b2,b3,b1).toint());
  fprintf(f,"\n-----b1.det(b2,b1,b4) = %d", b1.det(b2,b1,b4).toint());
  fprintf(f,"\n-----b1.det(b1,b3,b4) = %d", b1.det(b1,b3,b4).toint());
  fprintf(f,"\n-----b1.det(b2,b2,b4) = %d", b1.det(b2,b2,b4).toint());
  fprintf(f,"\n-----b1.det(b2,b3,b3) = %d", b1.det(b2,b3,b3).toint());
  fprintf(f,"\n");

  fprintf(f,"\nend unit-test for base_T3.\n\n\n");
  } // end test_base_T3()


// base_T5
void base_T5_rand(base_T5& b) {
  b.set_base(rscal(),rscal(),rscal(),rscal(),rscal(),rscal());
}

void test_base_T5(FILE *f) {
  bool flag;

  fprintf(f,"\nunit-testing class base_T5:\n");
  srandom(55); // random number seed for this subtest

  base_T5 b1,b2,b3,b4,b5,b6,b7;
  assert(b1.isnull());

  fprintf(f,"\n-----  base_T5():");
  fprintf(f,"\n-----dump(): "); b1.dump(f);
  fprintf(f,"\n-----analyze(); "); flag= b1.analyze(f);
  fprintf(f,"\n-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", b1.ok());

  base_T5 b(-21,-11,-1,9,19,29);
  fprintf(f,"\n-----  base_T5(-21,-11,-1,9,19,29):");
  fprintf(f,"\n-----dump(): "); b.dump(f);
  fprintf(f,"\n-----analyze(); "); flag= b.analyze(f);
  fprintf(f,"\n-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", b.ok());

  base_T5_rand(b1);
  base_T5_rand(b2);
  base_T5_rand(b3);
  base_T5_rand(b4);
  base_T5_rand(b5);
  base_T5_rand(b6);
  fprintf(f,"\n-----randomized: b1="); b1.dump(f);
  fprintf(f,"\n-----randomized: b2="); b2.dump(f);
  fprintf(f,"\n-----randomized: b3="); b3.dump(f);
  fprintf(f,"\n-----randomized: b4="); b4.dump(f);
  fprintf(f,"\n-----randomized: b5="); b5.dump(f);
  fprintf(f,"\n-----randomized: b6="); b6.dump(f);

  for(int i=0; i<6; i++) {
    fprintf(f,"\n----- b1.getval(%d)=%d; b1[%d]=%d",
	    i, b1.get_val(i).toint(), i, b1[i].toint() );
  }

  b7.set_base(15,25,35,45,55,65);
  fprintf(f,"\n-----b7.set_base(15,25,35,45,55,65) -> "); b7.dump(f);
  b7.set_base(b1);
  fprintf(f,"\n-----b7.set_base(b1) -> "); b7.dump(f);
  b7.set_null();
  fprintf(f,"\n-----b7.set_null() -> "); b7.dump(f);
  b7.set_anti(b1);
  fprintf(f,"\n-----b7.set_anti(b1) -> "); b7.dump(f);

  fprintf(f,"\n-----b1.find_big_elt()=%d", b1.find_big_elt());
  fprintf(f,"\n-----b2.find_big_elt()=%d", b2.find_big_elt());
  fprintf(f,"\n-----b3.find_big_elt()=%d", b3.find_big_elt());
  fprintf(f,"\n-----b4.find_big_elt()=%d", b4.find_big_elt());
  fprintf(f,"\n-----b5.find_big_elt()=%d", b5.find_big_elt());
  fprintf(f,"\n-----b6.find_big_elt()=%d", b6.find_big_elt());
  fprintf(f,"\n");

  fprintf(f,"\n-----b1.dot(b1)= %d", b1.dot(b1).toint());
  fprintf(f,"\n-----b1.dot(b2)= %d", b1.dot(b2).toint());
  fprintf(f,"\n-----b1.dot(b3)= %d", b1.dot(b3).toint());
  fprintf(f,"\n-----b1.dot(b4)= %d", b1.dot(b4).toint());
  fprintf(f,"\n-----b1.dot(b5)= %d", b1.dot(b5).toint());
  fprintf(f,"\n-----b1.dot(b6)= %d", b1.dot(b6).toint());

  fprintf(f,"\n-----b2.dot(b1)= %d", b2.dot(b1).toint());
  fprintf(f,"\n-----b2.dot(b2)= %d", b2.dot(b2).toint());
  fprintf(f,"\n-----b2.dot(b3)= %d", b2.dot(b3).toint());
  fprintf(f,"\n-----b2.dot(b4)= %d", b2.dot(b4).toint());
  fprintf(f,"\n-----b2.dot(b5)= %d", b2.dot(b5).toint());
  fprintf(f,"\n-----b2.dot(b6)= %d", b2.dot(b6).toint());
  fprintf(f,"\n");

  fprintf(f,"\nend unit-test for base_T5.\n\n\n");
}


// point_T3, line_T3, plane_T3
void point_T3_rand(point_T3& p) {
  base_T3_rand((base_T3&)p);
}
void line_T3_rand(line_T3& L) {
  base_T5_rand((base_T5&)L);
}
void plane_T3_rand(plane_T3& d) {
  base_T3_rand((base_T3&)d);
}

void point_T3_checkaffine(point_T3& p, FILE *f) {
  fprintf(f,"\n  isfront=%d isback=%d isideal=%d",
	  p.isfront(),p.isback(),p.isideal());
  fprintf(f,"\n  fpX=%f fpXinv=%f fpY=%f fpYinv=%f fpZ=%f fpZinv= %f",
	  p.fpX(), p.fpXinv(), p.fpY(), p.fpYinv(), p.fpZ(), p.fpZinv());
}
void line_T3_checkaffine(const line_T3& L, FILE *f) {
  fprintf(f,"\n  isideal=%d", L.isideal());
  point_T3 p; L.get_dir(p);
  fprintf(f,"\n  get_dir() -> (ideal point) "); p.dump(f);
}
void plane_T3_checkaffine(const plane_T3& d, FILE *f) {
  fprintf(f,"\n  isideal=%d", d.isideal());
  line_T3 L;  d.get_dir(L);
  fprintf(f,"\n  get_dir() -> (ideal line) "); L.dump(f);
}

void line_T3_checkratio(const line_T3& L, const line_T3& M, FILE *f) {
  fprintf(f,"\n ratio=(%f %f %f %f %f %f)",
	  double(L[0].toint())/double(M[0].toint()),
	  double(L[1].toint())/double(M[1].toint()),
	  double(L[2].toint())/double(M[2].toint()),
	  double(L[3].toint())/double(M[3].toint()),
	  double(L[4].toint())/double(M[4].toint()),
	  double(L[5].toint())/double(M[5].toint())
	  );
}

void line_T3_checkbasis(const line_T3& L, FILE *f) {
  fprintf(f,"\nFor line_T3 "); L.dump(f);
  int big= L.find_big_elt();
  fprintf(f,":  find_big_elt=%d", big); 
  for(int i=0; i<4; i++) {
    fprintf(f,"\n");
    if(line_T3::first_index(big) == i)
      fprintf(f," 1 ");
    if(line_T3::second_index(big) == i)
      fprintf(f," 2 ");
    if(! (line_T3::first_index(big) == i)
       && ! (line_T3::second_index(big) == i))
      fprintf(f," . ");
    base_T3 b; L.get_vect(i,b);
    fprintf(f,"     get_vect(%d) -> ", i); b.dump(f);
  };
  for(int i=0; i<6; i++) {
    fprintf(f,"\n  pivot= %d  ->", i);
    if(i == big)
      fprintf(f," * ");
    else
      fprintf(f,"   ");
    base_T3 b1,b2; L.get_vects(i,b1,b2);
    fprintf(f,"   get_vects(%d) -> ", i);
    b1.dump(f); b2.dump(f);

    line_T3 M; M.set_fix_line(L,i);
    fprintf(f,"\n     set_fix_line(%d) -> ", i); M.dump(f);
    line_T3_checkratio(L,M,f);
  }

  // ... do set_xform_as_* here later...

  fprintf(f,"\n");
}

void test_point_line_plane_T3(FILE *f) {
  bool flag;

  fprintf(f,"\nunit-testing classes point_T3, line_T3, plane_T3:\n");
  srandom(2255); // random number seed (should be set once per subtest)

  point_T3 p1,p2,p3,p4,p5,p6,p7,p9;
  line_T3 L1,L2,L3,L4,L5,L6,L7,L8,L9,L10,L11;
  plane_T3 d1,d2,d3,d4,d5,d6,d7,d9;
  assert(p1.isnull());
  assert(L1.isnull());
  assert(d1.isnull());

  fprintf(f,"\n-----point_T3:");
  fprintf(f,"\n-----dump(): "); p1.dump(f);
  fprintf(f,"\n-----analyze(): "); flag= p1.analyze(f);
  fprintf(f,"\n-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", p1.ok());

  point_T3 p(-1,-2,-3,-4);
  fprintf(f,"\n-----point_T3(-1,-2,-3,-4):");
  fprintf(f,"\n-----dump(): "); p.dump(f);
  fprintf(f,"\n-----analyze(): "); flag= p.analyze(f);
  fprintf(f,"\n-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", p.ok());
  fprintf(f,"\n");

  fprintf(f,"\n-----line_T3:");
  fprintf(f,"\n-----dump(): "); L1.dump(f);
  fprintf(f,"\n-----analyze(): "); flag= L1.analyze(f);
  fprintf(f,"\n-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", L1.ok());

  line_T3 L(-5,-6,-7,-8,-9,-10);
  fprintf(f,"\n-----line_T3(-5,-6,-7,-8,-9,-10):");
  fprintf(f,"\n-----dump(): "); L.dump(f);
  fprintf(f,"\n-----analyze(): "); flag= L.analyze(f);
  fprintf(f,"\n-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", L.ok());
  fprintf(f,"\n");

  fprintf(f,"\n-----plane_T3:");
  fprintf(f,"\n-----dump(): "); d1.dump(f);
  fprintf(f,"\n-----analyze(): "); flag= d1.analyze(f);
  fprintf(f,"\n-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", d1.ok());

  plane_T3 d(-11,-12,-13,-14);
  fprintf(f,"\n-----plane_T3(-11,-12,-13,-14):");
  fprintf(f,"\n-----dump(): "); d.dump(f);
  fprintf(f,"\n-----analyze(): "); flag= d.analyze(f);
  fprintf(f,"\n-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d\n", d.ok());
  fprintf(f,"\n");

  point_T3_rand(p1);
  point_T3_rand(p2);
  point_T3_rand(p3);
  point_T3_rand(p4);
  fprintf(f,"\n-----randomized: p1="); p1.dump(f);
  fprintf(f,"\n-----randomized: p2="); p2.dump(f);
  fprintf(f,"\n-----randomized: p3="); p3.dump(f);
  fprintf(f,"\n-----randomized: p4="); p4.dump(f);
  for(int i=0; i<4; i++) {
    fprintf(f,"\n----- p1.get_val(%d)=%d; p1[%d]=%d",
	    i, p1.get_val(i).toint(), i, p1[i].toint() );
  }

  line_T3_rand(L1);
  line_T3_rand(L2);
  line_T3_rand(L3);
  line_T3_rand(L4);
  line_T3_rand(L5);
  line_T3_rand(L6);
  fprintf(f,"\n-----randomized: L1="); L1.dump(f);
  fprintf(f,"\n-----randomized: L2="); L2.dump(f);
  fprintf(f,"\n-----randomized: L3="); L3.dump(f);
  fprintf(f,"\n-----randomized: L4="); L4.dump(f);
  fprintf(f,"\n-----randomized: L5="); L5.dump(f);
  fprintf(f,"\n-----randomized: L6="); L6.dump(f);
  for(int i=0; i<6; i++) {
    fprintf(f,"\n----- L1.get_val(%d)=%d; L1[%d]=%d",
	    i, L1.get_val(i).toint(), i, L1[i].toint() );
  }

  plane_T3_rand(d1);
  plane_T3_rand(d2);
  plane_T3_rand(d3);
  plane_T3_rand(d4);
  fprintf(f,"\n-----randomized: d1="); d1.dump(f);
  fprintf(f,"\n-----randomized: d2="); d2.dump(f);
  fprintf(f,"\n-----randomized: d3="); d3.dump(f);
  fprintf(f,"\n-----randomized: d4="); d4.dump(f);
  for(int i=0; i<4; i++) {
    fprintf(f,"\n----- d1.get_val(%d)=%d; d1[%d]=%d",
	    i, d1.get_val(i).toint(), i, d1[i].toint() );
  }

  p5.set_point(-15,-5,7,9);
  fprintf(f,"\n-----p5.set_point(-15,-5,7,9) -> "); p5.dump(f);
  p5.set_point(p1);
  fprintf(f,"\n-----p5.set_point(p1) -> "); p5.dump(f);
  p5.set_anti(p1);
  fprintf(f,"\n-----p5.set_anti(p1) -> "); p5.dump(f);

  L7.set_line(-30,-90,-103, 45, 111, 1);
  fprintf(f,"\n-----L7.set_line(-30,-90,-103, 45, 111, 1) -> "); L7.dump(f);
  L7.set_line(L1);
  fprintf(f,"\n-----L7.set_line(L1) -> "); L7.dump(f);
  L7.set_anti(L1);
  fprintf(f,"\n-----L7.set_anti(L1) -> "); L7.dump(f);

  d5.set_plane(24,26,-28,13);
  fprintf(f,"\n-----d5.set_plane(24,26,-28,13) -> "); d5.dump(f);
  d5.set_plane(d1);
  fprintf(f,"\n-----d5.set_plane(d1) -> "); d5.dump(f);
  d5.set_anti(d1);
  fprintf(f,"\n-----d5.set_anti(d1) -> "); d5.dump(f);

  fprintf(f,"\n");

  // mixed operations

  p5.set_dual_right(d1);
  fprintf(f,"\n-----p5.set_dual_right(d1) -> "); p5.dump(f);
  fprintf(f,"\n-----p5(d1) = %d", p5(d1).toint());
  fprintf(f,"\n-----d1(p5) = %d", d1(p5).toint());

  d7.set_dual_left(p5);
  fprintf(f,"\n-----d7.set_dual_left(p5) -> "); d7.dump(f);
  d7.set_dual_right(p5);
  fprintf(f,"\n-----d7.set_dual_right(p5) -> "); d7.dump(f);
  fprintf(f,"\n");

  p6.set_dual_left(d1);
  fprintf(f,"\n-----p6.set_dual_left(d1) -> "); p6.dump(f);
  fprintf(f,"\n-----p6(d1) = %d", p6(d1).toint());
  fprintf(f,"\n-----d1(p6) = %d", d1(p6).toint());

  d7.set_dual_right(p6);
  fprintf(f,"\n-----d7.set_dual_right(p6) -> "); d7.dump(f);
  d7.set_dual_left(p6);
  fprintf(f,"\n-----d7.set_dual_left(p6) -> "); d7.dump(f);
  fprintf(f,"\n");

  d5.set_dual_right(p1);
  fprintf(f,"\n-----d5.set_dual_right(p1) -> "); d5.dump(f);
  fprintf(f,"\n-----d5(p1) = %d", d5(p1).toint());
  fprintf(f,"\n-----p1(d5) = %d", p1(d5).toint());

  p7.set_dual_left(d5);
  fprintf(f,"\n-----p7.set_dual_left(d5) -> "); p7.dump(f);
  p7.set_dual_right(d5);
  fprintf(f,"\n-----p7.set_dual_right(d5) -> "); p7.dump(f);
  fprintf(f,"\n");

  d6.set_dual_left(p1);
  fprintf(f,"\n-----d6.set_dual_left(p1) -> "); d6.dump(f);
  fprintf(f,"\n-----d6(p1) = %d", d6(p1).toint());
  fprintf(f,"\n-----p1(d6) = %d", p1(d6).toint());

  p7.set_dual_right(d6);
  fprintf(f,"\n-----p7.set_dual_right(d6) -> "); p7.dump(f);
  p7.set_dual_left(d6);
  fprintf(f,"\n-----p7.set_dual_left(d6) -> "); p7.dump(f);
  fprintf(f,"\n");

  fprintf(f,"\n-----p5(d5) = %d", p5(d5).toint());
  fprintf(f,"\n-----d5(p5) = %d", d5(p5).toint());

  fprintf(f,"\n-----p5(d6) = %d", p5(d6).toint());
  fprintf(f,"\n-----d6(p5) = %d", d6(p5).toint());

  fprintf(f,"\n-----p6(d5) = %d", p6(d5).toint());
  fprintf(f,"\n-----d5(p6) = %d", d5(p6).toint());

  fprintf(f,"\n-----p6(d6) = %d", p6(d6).toint());
  fprintf(f,"\n-----d6(p6) = %d", d6(p6).toint());

  fprintf(f,"\n");

  fprintf(f,"\n-----p1.eval_plane(d1) = %d", p1.eval_plane(d1).toint());
  fprintf(f,"\n-----p1*d1 = %d", (p1*d1).toint());
  fprintf(f,"\n-----p1(d1) = %d", p1(d1).toint());

  fprintf(f,"\n-----d1.eval_point(p1) = %d", d1.eval_point(p1).toint());
  fprintf(f,"\n-----d1*p1 = %d", (d1*p1).toint());
  fprintf(f,"\n-----d1(p1) = %d", d1(p1).toint());

  fprintf(f,"\n");

  fprintf(f,
    "\nd1(p1)=%d  d1(p2)=%d  d1(p3)=%d  d1(p4)=%d  d1(p5)=%d  d1(p6)=%d",
    d1(p1).toint(), d1(p2).toint(),d1(p3).toint(),d1(p4).toint(),
    d1(p5).toint(),d1(p6).toint()
    );
  fprintf(f,
    "\np1(d1)=%d  p1(d2)=%d  p1(d3)=%d  p1(d4)=%d  p1(d5)=%d  p1(d6)=%d",
    p1(d1).toint(), p1(d2).toint(),p1(d3).toint(),p1(d4).toint(),
    p1(d5).toint(),p1(d6).toint()
    );
  fprintf(f,"\n");

  L7.set_dual(L1);
  fprintf(f,"\n-----L7.set_dual(L1) -> "); L7.dump(f);
  L8.set_dual(L7);
  fprintf(f,"\n-----L8.set_dual(L7) -> "); L8.dump(f);

  fprintf(f,"\n-----L1.dot(L1) = %d", L1.dot(L1).toint());
  fprintf(f,"\n-----L1.dot(L2) = %d", L1.dot(L2).toint());
  fprintf(f,"\n-----L2.dot(L1) = %d", L2.dot(L1).toint());
  fprintf(f,"\n-----L2.dot(L2) = %d", L2.dot(L2).toint());

  fprintf(f,"\n-----L7.dot(L7) = %d", L7.dot(L7).toint());
  fprintf(f,"\n-----L1.dot(L7) = %d", L1.dot(L7).toint());
  fprintf(f,"\n-----L7.dot(L1) = %d", L7.dot(L1).toint());
  fprintf(f,"\n-----L2.dot(L7) = %d", L2.dot(L7).toint());
  fprintf(f,"\n-----L7.dot(L2) = %d", L7.dot(L2).toint());

  fprintf(f,"\n-----L1.orient(L1) = %d", L1.orient(L1).toint());
  fprintf(f,"\n-----L1.orient(L2) = %d", L1.orient(L2).toint());
  fprintf(f,"\n-----L2.orient(L1) = %d", L2.orient(L1).toint());
  fprintf(f,"\n-----L2.orient(L2) = %d", L2.orient(L2).toint());
  
  fprintf(f,"\n-----L7.orient(L7) = %d", L7.orient(L7).toint()); 
  fprintf(f,"\n-----L1.orient(L7) = %d", L1.orient(L7).toint());
  fprintf(f,"\n-----L7.orient(L1) = %d", L7.orient(L1).toint());
  fprintf(f,"\n-----L2.orient(L7) = %d", L2.orient(L7).toint());
  fprintf(f,"\n-----L7.orient(L2) = %d", L7.orient(L2).toint());

  fprintf(f,"\n");

  L9.set_dyad((const base_T3&)p1,(const base_T3&)p2 );
  fprintf(f,"\n-----L9.set_dyad((const base_T3&)p1,(const base_T3&)p2 ) -> ");
  L9.dump(f);
  L9.set_nuller((const base_T3&)p1,(const base_T3&)p2 );
  fprintf(f,"\n-----L9.set_nuller((const base_T3&)p1,(const base_T3&)p2 ) -> ");
  L9.dump(f);

  L9.set_dyad((const base_T3&)p1,(const base_T3&)p1 );
  fprintf(f,"\n-----L9.set_dyad((const base_T3&)p1,(const base_T3&)p1 ) -> ");
  L9.dump(f);
  L9.set_nuller((const base_T3&)p1,(const base_T3&)p1 );
  fprintf(f,"\n-----L9.set_nuller((const base_T3&)p1,(const base_T3&)p1 ) -> ");
  L9.dump(f);

  L9.set_dyad((const base_T3&)d1,(const base_T3&)d2 );
  fprintf(f,"\n-----L9.set_dyad((const base_T3&)d1,(const base_T3&)d2 ) -> ");
  L9.dump(f);
  L9.set_dyad((const base_T3&)d1,(const base_T3&)d2 );
  fprintf(f,"\n-----L9.set_nuller((const base_T3&)d1,(const base_T3&)d2 ) -> ");
  L9.dump(f);

  L9.set_dyad((const base_T3&)d1,(const base_T3&)d1 );
  fprintf(f,"\n-----L9.set_dyad((const base_T3&)d1,(const base_T3&)d1 ) -> ");
  L9.dump(f);
  L9.set_nuller((const base_T3&)d1,(const base_T3&)d1 );
  fprintf(f,"\n-----L9.set_nuller((const base_T3&)d1,(const base_T3&)d1 ) -> ");
  L9.dump(f);

  fprintf(f,"\n");

  // no tests for map_vect -- 
  // it should be exercised in join_point and meet_plane

  // exercise geometric interfaces
  fprintf(f,"\nExercise geometric interfaces:\n");

  fprintf(f,"\n-----p1.eval_plane(d1) = %d",
	  p1.eval_plane(d1).toint());
  fprintf(f,"\n-----(p1*d1) = %d", (p1*d1).toint());
  fprintf(f,"\n-----p1(d1) = %d", p1(d1).toint());
  fprintf(f,"\n-----p1.orient(p2,p3,p4) = %d", p1.orient(p2,p3,p4).toint());

  fprintf(f,"\n-----d1.eval_point(p1) = %d",
	  d1.eval_point(p1).toint());
  fprintf(f,"\n-----(d1*p1) = %d", (d1*p1).toint());
  fprintf(f,"\n-----d1(p1) = %d", d1(p1).toint());
  fprintf(f,"\n-----d1.orient(d2,d3,d4) = %d", d1.orient(d2,d3,d4).toint());

  fprintf(f,"\n-----L1.eval_line(L2) = %d", L1.eval_line(L2).toint());
  fprintf(f,"\n-----L1*L2 = %d", (L1*L2).toint());
  fprintf(f,"\n-----L1(L2) = %d", L1(L2).toint());
  fprintf(f,"\n-----L2.eval_line(L1) = %d", L2.eval_line(L1).toint());
  fprintf(f,"\n-----L2*L1 = %d", (L2*L1).toint());
  fprintf(f,"\n-----L2(L1) = %d", L2(L1).toint());
  fprintf(f,"\n-----basis operations on L1:  "); line_T3_checkbasis(L1,f);
  fprintf(f,"\n-----basis operations on L2:  "); line_T3_checkbasis(L2,f);
  fprintf(f,"\n");

  L10.set_join_points(p1,p2);
  fprintf(f,"\n-----L10.set_join_points(p1,p2) -> "); L10.dump(f);
  L11.set_join_points(p3,p4);
  fprintf(f,"\n-----L11.set_join_points(p3,p4) -> "); L11.dump(f);
  fprintf(f,"\n-----L10(L11) = %d", L10(L11).toint());
  L10.join_point(p1,d5);
  fprintf(f,"\n-----L10.join_point(p1,d5): d5 -> "); d5.dump(f);
  fprintf(f,"\n-----d5(p4)=%d  p4(d5)=%d", d5(p4).toint(), p4(d5).toint());
  fprintf(f,"\n-----basis operations on L10:  "); line_T3_checkbasis(L10,f);
  fprintf(f,"\n-----basis operations on L11:  "); line_T3_checkbasis(L11,f);

  L10.set_join_points(p1,p3);
  fprintf(f,"\n-----L10.set_join_points(p1,p3) -> "); L10.dump(f);
  L11.set_join_points(p2,p4);
  fprintf(f,"\n-----L11.set_join_points(p2,p4) -> "); L11.dump(f);
  fprintf(f,"\n-----L10(L11) = %d", L10(L11).toint());
  L10.join_point(p2,d5);
  fprintf(f,"\n-----L10.join_point(p2,d5): d5 -> "); d5.dump(f);
  fprintf(f,"\n-----d5(p4)=%d  p4(d5)=%d", d5(p4).toint(), p4(d5).toint());

  L10.set_join_points(p1,p4);
  fprintf(f,"\n-----L10.set_join_points(p1,p4) -> "); L10.dump(f);
  L11.set_join_points(p2,p3);
  fprintf(f,"\n-----L11.set_join_points(p2,p3) -> "); L11.dump(f);
  fprintf(f,"\n-----L10(L11) = %d", L10(L11).toint());
  L10.join_point(p2,d5);
  fprintf(f,"\n-----L10.join_point(p2,d5): d5 -> "); d5.dump(f);
  fprintf(f,"\n-----d5(p3)=%d  p3(d5)=%d", d5(p3).toint(), p3(d5).toint());

  L10.set_meet_planes(d1,d2);
  fprintf(f,"\n-----L10.set_meet_planes(d1,d2) -> "); L10.dump(f);
  L11.set_meet_planes(d3,d4);
  fprintf(f,"\n-----L11.set_meet_planes(d3,d4) -> "); L11.dump(f);
  fprintf(f,"\n-----L10(L11)= %d", L10(L11).toint());
  L10.meet_plane(d3,p5);
  fprintf(f,"\n-----L10.meet_plane(d3,p5): p5 -> "); p5.dump(f);
  fprintf(f,"\n-----p5(d4)= %d  d4(p5)= %d", p5(d4).toint(), d4(p5).toint());
  fprintf(f,"\n-----basis operations on L10:  "); line_T3_checkbasis(L10,f);
  fprintf(f,"\n-----basis operations on L11:  "); line_T3_checkbasis(L11,f);

  L10.set_meet_planes(d1,d3);
  fprintf(f,"\n-----L10.set_meet_planes(d1,d3) -> "); L10.dump(f);
  L11.set_meet_planes(d2,d4);
  fprintf(f,"\n-----L11.set_meet_planes(d2,d4) -> "); L11.dump(f);
  fprintf(f,"\n-----L10(L11)= %d", L10(L11).toint());
  L10.meet_plane(d2,p5);
  fprintf(f,"\n-----L10.meet_plane(d2,p5): p5 -> "); p5.dump(f);
  fprintf(f,"\n-----p5(d4)= %d  d4(p5)= %d", p5(d4).toint(), d4(p5).toint());

  L10.set_meet_planes(d1,d4);
  fprintf(f,"\n-----L10.set_meet_planes(d1,d4) -> "); L10.dump(f);
  L11.set_meet_planes(d2,d3);
  fprintf(f,"\n-----L11.set_meet_planes(d2,d3) -> "); L11.dump(f);
  fprintf(f,"\n-----L10(L11)= %d", L10(L11).toint());
  L10.meet_plane(d2,p5);
  fprintf(f,"\n-----L10.meet_plane(d2,p5): p5 -> "); p5.dump(f);
  fprintf(f,"\n-----p5(d3)= %d  d3(p5)= %d", p5(d3).toint(), d4(p5).toint());
  fprintf(f,"\n");


  // affine operations
  p9.set_null();
  fprintf(f,"\n-----p9.set_null() -> "); p9.dump(f);
  point_T3_checkaffine(p9,f);
  p9.set_point(0,15,-20,-99);
  fprintf(f,"\n-----p9 -> "); p9.dump(f);
  point_T3_checkaffine(p9,f);
  p9.set_point(34,55,27,-101);
  fprintf(f,"\n-----p9 -> "); p9.dump(f);
  point_T3_checkaffine(p9,f);
  p9.set_point(-110,3,-1,-10);
  fprintf(f,"\n-----p9 -> "); p9.dump(f);
  point_T3_checkaffine(p9,f);
  p9.set_point(40,0,0,0);
  fprintf(f,"\n-----p9 -> "); p9.dump(f);
  point_T3_checkaffine(p9,f);

  d9.set_null();
  fprintf(f,"\n-----d9.set_null() -> "); d9.dump(f);
  plane_T3_checkaffine(d9,f);
  d9.set_plane(0,15,-20,-99);
  fprintf(f,"\n-----d9 -> "); d9.dump(f);
  plane_T3_checkaffine(d9,f);
  d9.set_plane(34,55,27,-101);
  fprintf(f,"\n-----d9 -> "); d9.dump(f);
  plane_T3_checkaffine(d9,f);
  d9.set_plane(-110,3,-1,-10);
  fprintf(f,"\n-----d9 -> "); d9.dump(f);
  plane_T3_checkaffine(d9,f);
  d9.set_plane(40,0,0,0);
  fprintf(f,"\n-----d9 -> "); d9.dump(f);
  plane_T3_checkaffine(d9,f);

  L9.set_null();
  fprintf(f,"\n-----L9.set_null() -> "); L9.dump(f);
  line_T3_checkaffine(L9,f);
  L9.set_line(25,36,47,0,0,0);
  fprintf(f,"\n-----L9.set_line(25,36,47,0,0,0) -> "); L9.dump(f);
  line_T3_checkaffine(L9,f);
  L9.set_line(0,0,0,-15,80,92);
  fprintf(f,"\n-----L9.set_line(0,0,0,-15,80,92) -> "); L9.dump(f);
  line_T3_checkaffine(L9,f);
  L9.set_line(-98,22,40,100,20,-3);
  fprintf(f,"\n-----L9.set_line(-98,22,40,100,20,-3) -> "); L9.dump(f);
  line_T3_checkaffine(L9,f);
  L9.set_join_points(p1,p4);
  fprintf(f,"\n-----L9.set_join_points(p1,p4) -> "); L9.dump(f);
  line_T3_checkaffine(L9,f);
  fprintf(f,"\n");

  fprintf(f,"\nend unit test for point_T3, line_T3, plane_T3.\n\n\n");
} // end test_point_line_plane_T3()


// matrix_T2
void matrix_T2_rand(matrix_T2& T) {
  base_T2 w,x,y;
  base_T2_rand(w);
  base_T2_rand(x);
  base_T2_rand(y);

  T.set_cols(w,x,y);
}

void test_matrix_T2(FILE *f) {
  bool flag;
  fprintf(f,"\nunit-testing class matrix_T2:\n");
  srandom(141); // random number seed for this subtest

  matrix_T2 T1,T2,T3,T4,T5;

  fprintf(f,"\n-----matrix_T2:");
  fprintf(f,"\n-----dump: "); T1.dump(f);
  fprintf(f,"\n-----analyze(): "); flag= T1.analyze(f);
  fprintf(f,"-----> analyze returned %d", flag);
  fprintf(f,"\n-----ok(): %d", T1.ok());

  fprintf(f,"\n-----isnull() = %d", T1.isnull());
  fprintf(f,"\n");

  matrix_T2_rand(T1);
  matrix_T2_rand(T2);
  matrix_T2_rand(T3);
  fprintf(f,"\n-----randomized: T1 -> "); T1.dump(f);
  fprintf(f,"\n-----randomized: T2 -> "); T2.dump(f);
  fprintf(f,"\n-----randomized: T3 -> "); T3.dump(f);

  fprintf(f,"\n-----T1.isnull() = %d", T1.isnull());
  fprintf(f,"\n");

  for(int i=0; i<3; i++) {
    base_T2 tmp;  T1.get_col(i,tmp);
    fprintf(f,"\n----- T1.get_col(%d) -> ",i); tmp.dump(f);
  }
  for(int i=0; i<3; i++) {
    base_T2 tmp;  T1.get_row(i,tmp);
    fprintf(f,"\n----- T1.get_row(%d) -> ",i); tmp.dump(f);
  }
  for(int i=0; i<3; i++) {
    fprintf(f,"\n  ");
    for(int j=0; j<3; j++) {
      fprintf(f, " T1.get_val(%d,%d)=%d", i,j,T1.get_val(i,j).toint());
    }
  }
  T3.set_null();
  fprintf(f,"\n-----T3.set_null() -> "); T3.dump(f);
  T3.set_unit();
  fprintf(f,"\n-----T3.set_unit() -> "); T3.dump(f);
  T3.set_cols(base_T2(11,12,13),base_T2(14,15,16),base_T2(17,18,19));
  fprintf(f,"\n-----T3.set_cols(base_T2(11,12,13),base_T2(14,15,16),base_T2(17,18,19))\n -> "); T3.dump(f);
  T3.set_rows(base_T2(21,22,23),base_T2(24,25,26),base_T2(27,28,29));
  fprintf(f,"\n-----T3.set_rows(base_T2(21,22,23),base_T2(24,25,26),base_T2(27,28,29))\n -> "); T3.dump(f);
  T3.set_neg(T1);
  fprintf(f,"\n-----T3.set_neg(T1) -> "); T3.dump(f);
  T3.negate();
  fprintf(f,"\n-----T3.negate() -> "); T3.dump(f);
  T3.set_transpose(T1);
  fprintf(f,"\n-----T3.set_transpose(T1) -> "); T3.dump(f);
  T3.transpose();
  fprintf(f,"\n-----T3.transpose() -> "); T3.dump(f);

  fprintf(f,"\n");
  T3.set_product(T1,T2);
  fprintf(f,"\n-----T3.set_product(T1,T2) -> "); T3.dump(f);
  T3.transpose();
  fprintf(f,"\n-----T3.transpose() -> "); T3.dump(f);
  T4.set_transpose(T1);
  fprintf(f,"\n-----T4.set_transpose(T1) -> "); T4.dump(f);
  T5.set_transpose(T2);
  fprintf(f,"\n-----T5.set_transpose(T2) -> "); T5.dump(f);
  T3.set_product(T5,T4);
  fprintf(f,"\n-----T3.set_product(T5,T4) -> "); T3.dump(f);

  fprintf(f,"\n");
  scalar det= T3.set_cofactor(T1);
  fprintf(f,"\n-----T3.set_cofactor(T1)(=%d) -> ",det.toint()); T3.dump(f);
  T3.transpose();
  fprintf(f,"\n-----T3.transpose() -> "); T3.dump(f);
  T4.set_product(T1,T3);
  fprintf(f,"\n-----T4.set_product(T1,T3) -> "); T4.dump(f);
  T4.set_product(T3,T1);
  fprintf(f,"\n-----T4.set_product(T3,T1) -> "); T4.dump(f);

  fprintf(f,"\n");
  fprintf(f,"\n-----T1.det()= %d", T1.det().toint());
  fprintf(f,"\n-----T2.det()= %d", T2.det().toint());
  fprintf(f,"\n-----T3.det()= %d", T3.det().toint());
  fprintf(f,"\n-----T4.det()= %d", T4.det().toint());

  fprintf(f,"\n");
  base_T2 b1,b2,b3;

  base_T2_rand(b1);
  fprintf(f,"\n-----randomized: b1="); b1.dump(f);

  T1.xform_row(b1,b2);
  fprintf(f,"\n-----T1.xform_row(b1,b2): b2 -> "); b2.dump(f);
  T3.xform_row(b2,b3);
  fprintf(f,"\n-----T3.xform_row(b2,b3): b3 -> "); b3.dump(f);
  T3.xform_col(b2,b3);
  fprintf(f,"\n-----T3.xform_col(b2,b3): b3 -> "); b3.dump(f);
  T1.xform_col(b1,b2);
  fprintf(f,"\n-----T1.xform_col(b1,b2): b2 -> "); b2.dump(f);
  T3.xform_row(b2,b3);
  fprintf(f,"\n-----T3.xform_row(b2,b3): b3 -> "); b3.dump(f);
  T3.xform_col(b2,b3);
  fprintf(f,"\n-----T3.xform_col(b2,b3): b3 -> "); b3.dump(f);

  T2.xform_row(b1,b2);
  fprintf(f,"\n-----T2.xform_row(b1,b2): b2 -> "); b2.dump(f);
  T2.xform_col(b1,b2);
  fprintf(f,"\n-----T2.xform_col(b1,b2): b2 -> "); b2.dump(f);

  T3.xform_row(b1,b2);
  fprintf(f,"\n-----T3.xform_row(b1,b2): b2 -> "); b2.dump(f);
  T1.xform_col(b2,b3);
  fprintf(f,"\n-----T1.xform_col(b2,b3): b3 -> "); b3.dump(f);
  T3.xform_col(b1,b2);
  fprintf(f,"\n-----T3.xform_col(b1,b2): b2 -> "); b2.dump(f);
  T1.xform_row(b2,b3);
  fprintf(f,"\n-----T1.xform_row(b2,b3): b3 -> "); b3.dump(f);

  T4.xform_row(b1,b2);
  fprintf(f,"\n-----T4.xform_row(b1,b2): b2 -> "); b2.dump(f);
  T4.xform_col(b1,b2);
  fprintf(f,"\n-----T4.xform_col(b1,b2): b2 -> "); b2.dump(f);
  

  fprintf(f,"\nend unit-test for matrix_T2.\n\n\n");
} // end test_matrix_T2


int main() {

  // basic arithmetic checks
  printf("scalar::maxval=%d\n", scalar::maxval);


  // unittest classes one by one
  test_point_T1(stdout);

  test_base_T2(stdout);
  test_point_line_T2(stdout);

  test_base_T3(stdout);
  test_base_T5(stdout);

  test_point_line_plane_T3(stdout);

  test_matrix_T2(stdout);
  //test_matrix_T3(stdout);
  //test_matrix_T5(stdout);

  //test_gmap_T2(stdout);
  //test_gmap_T3(stdout);
  //test_dmap_T2(stdout);
  //test_dmap_T3(stdout);

  // combination tests
  // ...

  printf("\n***** end of testgeometry.cc *****\n");
  // end of unit test for geometry.hh/geometry.cc
  return 0;
} // end main()
