c++ - Is there a better way to rewrite this ugly switch and if statement combination? -
essentially have system of gamma detectors segmented 4 crystals each, in case when 2 of of crystals register hit can determine if pair perpendicular or parallel plane of reaction generating gamma-ray. in process of writing logic wound writing huge , ugly combination of switch statements in each detector checks combinations of crystal numbers (which unique across whole array of detectors , crystals). here code, including function in question.
//the parallel , perpendicular designations used in addition double //designation 90 degree detectors if diagonal scatter in detectors //then use double designation enum scattertype{single, double, triple, quadruple, parallel, perpendicular}; scattertype eventbuffer::checkdoublegamma(int det) { int num1=evlist[cryslist[0]].crystalnum; int num2=evlist[cryslist[1]].crystalnum; switch(det) { case 10: //first of 90 degree detectors if( (num1==40 && num2==41) || //combo 1 (num1==41 && num2==40) || //combo 1 reverse (num1==42 && num2==43) || //combo 2 (num1==43 && num2==42) )//combo 2 reverse { return parallel; } else if( (num1==40 && num2==42) || //combo 1 (num1==42 && num2==40) || //combo 1 reverse (num1==41 && num2==43) || //combo 2 (num1==43 && num2==41) )//combo 2 reverse { return perpendicular; } else { return double;} break; case 11: //second of 90 degree detectors if( (num1==44 && num2==45) || //combo 1 (num1==45 && num2==44) || //combo 1 reverse (num1==46 && num2==47) || //combo 2 (num1==47 && num2==46) )//combo 2 reverse { return parallel; } else if( (num1==44 && num2==47) || //combo 1 (num1==47 && num2==44) || //combo 1 reverse (num1==45 && num2==46) || //combo 2 (num1==46 && num2==45) )//combo 2 reverse { return perpendicular; } else { return double;} break; case 13: //third of 90 degree detectors if( (num1==52 && num2==53) || //combo 1 (num1==53 && num2==52) || //combo 1 reverse (num1==54 && num2==55) || //combo 2 (num1==55 && num2==54) )//combo 2 reverse { return parallel; } else if( (num1==52 && num2==55) || //combo 1 (num1==55 && num2==52) || //combo 1 reverse (num1==53 && num2==54) || //combo 2 (num1==54 && num2==53) )//combo 2 reverse { return perpendicular; } else { return double;} break; case 14: //fourth of 90 degree detectors if( (num1==56 && num2==57) || //combo 1 (num1==57 && num2==56) || //combo 1 reverse (num1==58 && num2==59) || //combo 2 (num1==59 && num2==58) )//combo 2 reverse { return parallel; } else if( (num1==56 && num2==59) || //combo 1 (num1==59 && num2==56) || //combo 1 reverse (num1==57 && num2==58) || //combo 2 (num1==58 && num2==57) )//combo 2 reverse { return perpendicular; } else { return double;} break; default: throw string("made default case in checkdoublegamma switch statement, wrong"); break; } }
i aware that, because crystal numbers global rather per detector, away switch statement , have enormous set of conditionals linked or statements, reducing things 3 control paths, 1 returning parallel, 1 returning perpendicular, , 1 returning double, instead of 12 control paths 4 of each have. wrote not thinking , in honesty, thinking it, method reduces average case number of boolean statements grind through.
i worked out how make more efficient switching on evlist[cryslist[0]].crystalnum
can reduce evaluations quite bit, yielding this:
scattertype eventbuffer::checkdoublegamma() { int crysnum = cryslist[1].crystalnum; switch(evlist[cryslist[0]].crystalnum) { case 40: if (crysnum == 41) {return parallel;} else if (crysnum == 42) {return perpendicular;} else {return double;} break; case 41: if (crysnum == 40) {return parallel;} else if (crysnum == 43) {return perpendicular;} else {return double;} break; case 42: if (crysnum == 43) {return parallel;} else if (crysnum == 40) {return perpendicular;} else {return double;} break; case 43: if (crysnum == 42) {return parallel;} else if (crysnum == 41) {return perpendicular;} else {return double;} break; case 44: if (crysnum == 45) {return parallel;} else if (crysnum == 47) {return perpendicular;} else {return double;} break; case 45: if (crysnum == 44) {return parallel;} else if (crysnum == 46) {return perpendicular;} else {return double;} break; case 46: if (crysnum == 47) {return parallel;} else if (crysnum == 45) {return perpendicular;} else {return double;} break; case 47: if (crysnum == 46) {return parallel;} else if (crysnum == 44) {return perpendicular;} else {return double;} break; case 52: if (crysnum == 53) {return parallel;} else if (crysnum == 55) {return perpendicular;} else {return double;} break; case 53: if (crysnum == 52) {return parallel;} else if (crysnum == 54) {return perpendicular;} else {return double;} break; case 54: if (crysnum == 55) {return parallel;} else if (crysnum == 53) {return perpendicular;} else {return double;} break; case 55: if (crysnum == 54) {return parallel;} else if (crysnum == 52) {return perpendicular;} else {return double;} break; case 56: if (crysnum == 57) {return parallel;} else if (crysnum == 59) {return perpendicular;} else {return double;} break; case 57: if (crysnum == 56) {return parallel;} else if (crysnum == 58) {return perpendicular;} else {return double;} break; case 58: if (crysnum == 59) {return parallel;} else if (crysnum == 57) {return perpendicular;} else {return double;} break; case 59: if (crysnum == 58) {return parallel;} else if (crysnum == 56) {return perpendicular;} else {return double;} break; default: throw string("made default case in checkdoublegamma switch statement, wrong"); break; } }
the question still remains though, there trick make shorter? more efficient? more readable?
thanks in advance!
i think can move simple table , away single table lookup. haven't studied conditions in detail, looks job fine:
// fill following table in advance using existing function, or hard-code // values if know never change: scattertype hittable[60][60]; scattertype eventbuffer::checkdoublehit(int det) { // read crystal nums once: unsigned = evlist[crylist[0]].crystalnum; unsigned b = evlist[crylist[1]].crystalnum; switch(det) { case 10: case 11: case 13: case 14: // better safe sorry: assert (a < 60); assert (b < 60); return hittable[a][b]; break; default: throw string("made default case in checkdoublehit switch statement, wrong"); break; } }
Comments
Post a Comment