58 class EGS_LOCAL EGS_PrivateTester {
63 ~EGS_PrivateTester() {
84 FILE *fp_info, *fp_warn, *fp_inside, *fp_hownear, *fp_howfar;
114 int beginTest(
int n,
const EGS_BaseShape *s,
const char *func,
121 p =
new EGS_PrivateTester(
this,i);
133 p->testInsideTime(g);
137 p->testHownear(ntry,g);
141 p->testHownearTime(g);
145 p->testHowfar(g,
false);
149 p->testHowfar(g,
true);
153 fprintf(p->fp_this_test,
"%g %g %g\n",x.
x,x.
y,x.
z);
158 if (!p)
egsFatal(
"EGS_PrivateTester::EGS_PrivateTester:\n"
159 " attempt to construct a tester with a null parent\n");
169 inside_time_shape = 0;
172 hownear_time_shape = 0;
173 howfar_time_shape = 0;
176 check_infinity =
true;
188 setTest(input,
"inside test",n_inside,&inside_shape);
189 fp_inside = fp_this_test;
191 setTest(input,
"inside time test",n_inside_time,&inside_time_shape);
193 setTest(input,
"hownear test",n_hownear,&hownear_shape);
194 fp_hownear = fp_this_test;
196 setTest(input,
"hownear time test",n_hownear_time,&hownear_time_shape);
198 setTest(input,
"howfar test",n_howfar,&howfar_shape);
199 fp_howfar = fp_this_test;
201 setTest(input,
"howfar time test",n_howfar_time,&howfar_time_shape);
205 void EGS_PrivateTester::setTest(
EGS_Input *input,
const char *delim,
int &n,
208 if (!i) fprintf(fp_warn,
"EGS_PrivateTester::EGS_setTest: \n"
209 " no '%s' specification\n",delim);
212 int ierr = i->
getInput(
"bounding shape name",shape_name);
219 if (!ishape) fprintf(fp_warn,
"EGS_PrivateTester::EGS_setTest: \n"
220 " no 'bounding shape' definition for %s\n",delim);
226 if (!shape) fprintf(fp_warn,
"EGS_PrivateTester::EGS_PrivateTester:"
227 "\n got null shape for %s\n",delim);
233 if (err) fprintf(fp_warn,
"EGS_PrivateTester::setTest: \n"
234 " missing/wrong 'ntest' input for %s\n",delim);
236 fp_this_test = stdout;
237 err = i->
getInput(
"file name",fname);
238 if (!err && fname.size() > 0) {
239 fp_this_test = fopen(fname.c_str(),
"w");
241 fprintf(fp_warn,
"EGS_PrivateTester::setTest: \n"
242 " failed to open file %s from writing\n",fname.c_str());
243 fp_this_test = stdout;
247 err = i->
getInput(
"check infinity",ci);
248 if (!err && ci == 0) {
249 check_infinity =
false;
252 string delimeter(delim);
253 if (delimeter ==
"howfar time test") {
256 if (ss ==
"no" || ss ==
"0") {
257 fprintf(fp_info,
"will not store steps in howfar test\n");
267 if (beginTest(n_inside,inside_shape,
"testInside()",
"inside test",g)) {
271 fp_this_test = fp_inside;
272 for (
int j=0; j<n_inside; j++) {
273 EGS_Vector x = inside_shape->getRandomPoint(rndm);
277 parent->printPosition(x);
280 fprintf(fp_info,
"finished inside test. Point inside: %d (%g)\n",
281 n_in,((
double) n_in)/((
double) n_inside));
285 if (beginTest(n_inside_time,inside_time_shape,
"testInsideTime()",
286 "inside time test",g)) {
291 for (
int j=0; j<n_inside_time; j++) {
292 EGS_Vector x = inside_time_shape->getRandomPoint(rndm);
298 EGS_Float cpu = t.
time();
299 fprintf(fp_info,
"finished inside time test.\n");
300 fprintf(fp_info,
" point inside: %d (%g)\n",n_in,
301 ((
double) n_in)/((
double) n_inside_time));
302 fprintf(fp_info,
" cpu time: %g seconds\n",cpu);
307 fprintf(fp_warn,
"EGS_GeometryTester::testHownear(): ntry must be >0\n");
310 if (beginTest(n_hownear,hownear_shape,
"testHownear()",
"hownear test",g)) {
314 for (
int j=0; j<n_hownear; j++) {
315 EGS_Vector x = hownear_shape->getRandomPoint(rndm);
317 EGS_Float tperp = g->
hownear(ireg,x);
318 for (
int i=0; i<ntry; i++) {
319 EGS_Float cost = 2*rndm->getUniform()-1;
320 EGS_Float sint = tperp*sqrt(1-cost*cost);
321 EGS_Float cphi, sphi;
322 rndm->getAzimuth(cphi,sphi);
324 int ireg_i = g->
inside(xi);
325 if (ireg_i != ireg) {
327 fprintf(fp_hownear,
" point (%g,%g,%g) with tperp=%g fails for "
328 "(%g,%g,%g): %d %d\n",x.
x,x.
y,x.
z,tperp,xi.x,xi.y,xi.z,ireg,ireg_i);
332 fprintf(fp_info,
"finished hownear test. number of failed points: %d\n",
337 if (beginTest(n_hownear_time,hownear_time_shape,
"testHownearTime()",
338 "hownear time test",g)) {
341 double sum_tperp = 0;
343 for (
int j=0; j<n_hownear_time; j++) {
344 EGS_Vector x = hownear_time_shape->getRandomPoint(rndm);
346 sum_tperp += g->
hownear(ireg,x);
348 EGS_Float cpu = t.
time();
349 fprintf(fp_info,
"finished hownear time test.\n");
350 fprintf(fp_info,
" average tperp: %g\n",sum_tperp/n_hownear_time);
351 fprintf(fp_info,
" cpu time: %g seconds\n",cpu);
355 #define N_MAX_STEP 200
359 int regions[N_MAX_STEP];
365 ncase = n_howfar_time;
366 btest = beginTest(n_howfar_time,howfar_time_shape,
"testHowfarTime()",
367 "howfar time test",g);
368 hshape = howfar_time_shape;
370 fprintf(fp_info,
"Store steps: %d\n",ss);
374 btest = beginTest(n_howfar,howfar_shape,
"testHowfar()",
"howfar test",g);
375 hshape = howfar_shape;
382 egsWarning(
"has transofrmation: %d\n",(T != 0));
385 fp_this_test = fp_howfar;
387 for (
int j=0; j<ncase; j++) {
389 EGS_Float cost = 2*rndm->getUniform()-1;
390 EGS_Float sint = sqrt(1-cost*cost);
391 EGS_Float cphi, sphi;
392 rndm->getAzimuth(cphi,sphi);
402 int ireg_first = ireg;
403 ireg = g->
howfar(ireg,x,u,t_step);
404 if (ireg < 0 && ireg != ireg_first && !time) {
406 parent->printPosition(tmp);
413 positions[n_step] = x;
414 regions[n_step++] = ireg;
417 parent->printPosition(x);
424 int ireg_new = g->
howfar(ireg,x,u,t_step);
434 if (ireg_new == ireg) {
444 positions[n_step] = x;
445 regions[n_step++] = ireg;
446 if (n_step >= N_MAX_STEP) {
448 egsWarning(
"testHowfar(): number of steps exceeded %d for"
449 " case %d:\n",N_MAX_STEP,j+1);
450 egsWarning(
" direction = (%g,%g,%g)\n",u.x,u.y,u.z);
451 egsWarning(
" initial position = (%g,%g,%g) region = %d\n",
452 Xo.x,Xo.y,Xo.z,ireg_first);
453 for (
int j=0; j<N_MAX_STEP; j++)
454 egsWarning(
"x = (%g,%g,%g) ireg = %d\n",positions[j].x,
455 positions[j].y,positions[j].z,regions[j]);
465 if (check_infinity && x.length2() > 1e10) {
466 egsWarning(
"testHowfar(): x -> infinity for case %d?\n",
468 egsWarning(
" direction = (%g,%g,%g)\n",u.x,u.y,u.z);
469 egsWarning(
" initial position = (%g,%g,%g) region = %d\n",
470 Xo.x,Xo.y,Xo.z,ireg_first);
471 for (
int j=0; j<n_step; j++)
egsWarning(
"x = (%g,%g,%g) "
472 "ireg = %d\n",positions[j].x,positions[j].y,
473 positions[j].z,regions[j]);
478 egsWarning(
"testHowfar(): after howfar step ireg = %d"
479 " but inside() returns %d\n",ireg,itest);
481 egsWarning(
" direction = (%g,%g,%g)\n",u.x,u.y,u.z);
483 "region = %d\n",Xo.x,Xo.y,Xo.z,ireg_first);
484 for (
int j=0; j<n_step; j++)
egsWarning(
"x = (%g,%g,%g) "
485 "ireg = %d\n",positions[j].x,positions[j].y,
486 positions[j].z,regions[j]);
490 parent->printPosition(x);
494 EGS_Float cpu = timer.
time();
496 fprintf(fp_info,
"finished howfar time test, cpu time = %g seconds\n",
498 fprintf(fp_info,
" average number of steps: %g\n",nstep/ncase);
501 fprintf(fp_info,
"finished howfar test.\n");
506 int EGS_PrivateTester::beginTest(
int n,
const EGS_BaseShape *s,
509 fprintf(fp_warn,
"EGS_GeometryTester::%s: no bounding shape defined\n",
514 fprintf(fp_warn,
"EGS_GeometryTester::%s: number of test cases to run "
515 "is less than 1 (%d)\n",func,n);
518 fprintf(fp_info,
"\nEGS_GeometryTester::%s: starting %s\n",func,name);
519 fprintf(fp_info,
" number of cases: %d\n",n);
520 fprintf(fp_info,
" bounding shape: %s\n",s->
getObjectType().c_str());
522 fprintf(fp_info,
" geometry: %s (type %s)\n",g->
getName().c_str(),
538 EGS_Float r = sqrt(x.length2()-z*z);
539 fprintf(p->fp_this_test,
"%g %g\n",z,r);
549 ~EGS_SphereTester() {};
552 EGS_Float r2 = xp.length2();
553 fprintf(p->fp_this_test,
"%g %g\n",xp.z,sqrt(r2-xp.z*xp.z));
563 ~EGS_TransformedTester() {};
566 fprintf(p->fp_this_test,
"%g %g %g\n",xp.x,xp.y,xp.z);
575 egsWarning(
"EGS_GeometryTester::getGeometryTester:\n"
576 " input is null?\n");
579 bool delete_it =
false;
581 if (input->
isA(
"geometry tester")) {
587 egsWarning(
"EGS_GeometryTester::getGeometryTester:\n"
588 " no 'geometry tester' input\n");
601 int err = i->
getInput(
"output type",type);
602 if (err || i->
compare(type,
"normal")) {
605 else if (i->
compare(type,
"cylindrical")) {
606 vector<EGS_Float> axis;
607 int err1 = i->
getInput(
"axis",axis);
608 if (!err1 && axis.size() == 3) {
609 tester =
new EGS_CylTester(
EGS_Vector(axis[0],axis[1],axis[2]),i);
612 egsWarning(
"EGS_GeometryTester::getGeometryTester: no 'axis'"
613 " input for cylindrical output type\n");
617 else if (i->
compare(type,
"spherical")) {
618 vector<EGS_Float> Xo;
619 int err1 = i->
getInput(
"midpoint",Xo);
620 if (!err1 && Xo.size() == 3) {
621 tester =
new EGS_SphereTester(
EGS_Vector(Xo[0],Xo[1],Xo[2]),i);
624 tester =
new EGS_SphereTester(
EGS_Vector(),i);
627 else if (i->
compare(type,
"transformed")) {
630 egsWarning(
"EGS_GeometryTester::getGeometryTester: no "
631 "transformation defined for a transformed tester\n");
635 tester =
new EGS_TransformedTester(*t,i);
640 egsWarning(
"EGS_GeometryTester::getGeometryTester: unknown tester"
641 " type %s\n",type.c_str());
EGS_GeometryTester class header file.
virtual const string & getType() const =0
Get the geometry type.
A class for testing geometries.
EGS_Float time()
Returns the CPU time in seconds since start() was called.
virtual void printPosition(const EGS_Vector &x)
Outputs the position x to a file.
virtual EGS_Vector getRandomPoint(EGS_RandomGenerator *rndm)
Returns a random 3D vector.
void testHownear(int ntry, EGS_BaseGeometry *g)
Performs a hownear test.
static EGS_BaseShape * createShape(EGS_Input *inp)
Create a shape from the information pointed to by inp.
void testInsideTime(EGS_BaseGeometry *)
Performs an inside time test.
virtual ~EGS_GeometryTester()
Destructor.
A class representing 3D vectors.
static EGS_BaseShape * getShape(const string &Name)
Get a pointer to the shape named Name.
Global egspp functions header file.
static void deleteObject(EGS_Object *o)
Delete an object.
Base shape class. All shapes in the EGSnrc C++ class library are derived from EGS_BaseShape.
virtual int howfar(int ireg, const EGS_Vector &x, const EGS_Vector &u, EGS_Float &t, int *newmed=0, EGS_Vector *normal=0)=0
Calculate the distance to a boundary from x along the direction u.
const EGS_Float veryFar
A very large float.
Base geometry class. Every geometry class must be derived from EGS_BaseGeometry.
void testHowfarTime(EGS_BaseGeometry *)
Performs a howfar time test.
Base random number generator class. All random number generators should be derived from this class...
const EGS_AffineTransform * getTransform() const
Get a pointer to the affine transformation attached to this shape.
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
EGS_RandomGenerator class header file.
EGS_GeometryTester(EGS_Input *)
Construct a geometry tester from an input tree.
virtual int inside(const EGS_Vector &x)=0
Returns the region index, if inside, or -1 if outside (obsolete)
int ref()
Increase the reference count to this object.
EGS_BaseShape and shape classes header file.
A simple class for measuring CPU time.
virtual EGS_Float hownear(int ireg, const EGS_Vector &x)=0
Calculate the distance to a boundary for position x in any direction.
Attempts to fix broken math header files.
static EGS_GeometryTester * getGeometryTester(EGS_Input *i)
Creates a geometry tester object from the input i.
void testHownearTime(EGS_BaseGeometry *)
Performs a hownear time test.
const string & getObjectType() const
Get the object type.
static EGS_RandomGenerator * createRNG(EGS_Input *inp, int sequence=0)
Create a RNG object from the information pointed to by inp and return a pointer to it...
const string & getName() const
Get the name of this geometry.
static EGS_RandomGenerator * defaultRNG(int sequence=0)
Returns a pointer to the default egspp RNG.
void setDebug(bool deb)
Turn debugging on.
void testHowfar(EGS_BaseGeometry *)
Performs a howfar test.
EGS_BaseGeometry class header file.
EGS_Timer class header file.
void testInside(EGS_BaseGeometry *g)
Performs an inside test.
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.