Is there a better way to rewrite this ugly switch and combination of operators?

Essentially, I have a system of gamma detectors, each of which is segmented into 4 crystals, in the case when only 2 of the crystals register an impact, we can determine if the pair was perpendicular or parallel to the reaction plane generating the gamma ray. In the process of writing the logic for this, I started writing a huge and ugly combination of switch statements, which in each detector check combinations of crystal numbers (which are unique across the entire spectrum of detectors and their crystals). Here is the code including this feature.

//The Parallel and Perpendicular designations are used in addition to the Double
//designation for the 90 degree detectors if we get a diagonal scatter in those detectors
//then we use the 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 the 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 the 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 the 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 the 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 it to default case in checkDoubleGamma switch statement, something is wrong");
        break;
    }
}

, , , switch , , 3 , Parallel, , Double, 12 4 , . , , , , , .

, , evList[crysList[0]].crystalNum. , :

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 it to default case in checkDoubleGamma switch statement, something is wrong");
        break;
    }
}

, - , ? ? ?

!

+4
3

, . , , - :

// fill the following table in advance using your existing function, or hard-code the 
// values if you know they will never change:
ScatterType hitTable[60][60];


ScatterType EventBuffer::checkDoubleHit(int det)
{
    // read the crystal Nums once:
    unsigned a = evList[cryList[0]].crystalNum;
    unsigned b = evList[cryList[1]].crystalNum;

    switch(det)
    {
    case 10:
    case 11:
    case 13: 
    case 14:
      // better safe than sorry:
      assert (a < 60);
      assert (b < 60);
      return hitTable[a][b];
    break;

    default:
        throw string("made it to default case in checkDoubleHit switch statement, something is wrong");
        break;
    }
}
+4

/

int nummin=evList[crysList[0]].crystalNum;
int nummax=evList[crysList[1]].crystalNum;

if (nummin > nummax) 
{
    tmp = nummin;
    nummin = nummax;
    nummax = tmp;
}

if ((nummin == 40 && nummax == 41) ||  // no need to compare the reverse
    (nummin == 42 && nummax == 43))    // and reduce haft of the comparison
{ ... }
+1

, 4x4 .

: , , det=10.

{40,41,42,43}. , .

- det*4. , 10*4=40.

 0b101000 (40)  0b101000       0b101000       0b101000
^0b101000 (40) ^0b101001 (41) ^0b101010 (42) ^0b101011 (43)
=0b000000      =0b000001      =0b000010      =0b000011

xor (^) , {0,1,2,3}. , , , num1 ^ mask < 4, , mask, num1 3 , mask. num1 < mask, , (), , , num1 ^ mask 4. , num1 ^ mask < 4 , num1 {40,41,42,43}.

, {0,1,2,3}, .

, num1, num2, .

int checkDoubleGamma(int det){
    static const int hitTable[4][4] = {
        {Double, Parallel, Perpendicular, Double},
        {Parallel, Double, Double, Perpendicular},
        {Perpendicular, Double, Double, Parallel},
        {Double, Perpendicular, Parallel, Double}
    };

    const int num1 = evList[crysList[0]].crystalNum;
    const int num2 = evList[crysList[1]].crystalNum;

    switch(det) {
    case 10: //0b101000
    case 11: //0b101100
    case 13: //0b110100
    case 14: //0b111000
    {
        const unsigned int mask = 4 * det;
        const unsigned int a = num1 ^ mask;
        if(a < 4){
            const unsigned int b = num2 ^ mask;
            if(b < 4)
                return hitTable[a][b];
        }
        return Double;
    }
    default:
        throw string("made it to default case in checkDoubleGamma switch statement, something is wrong");
        break;
    }
    //Never reaches here
}

: 1x4

xor- a^b, , 4x4.

 ^ 00 01 10 11
00 00 01 10 11
01 01 00 11 10
10 10 11 00 01 
11 11 10 01 00

00,11 = Double
01    = Parallel
10    = Perpendicular 

, 1x4 a^b .

a^b, , num1^mask^num2^mask, num1^num2, xor.

, num2 {40,41,42,43}. num1 mask , num2 num1 , num2 mask . num2^mask .

int checkDoubleGamma(int det){
    static const int hitTable[4] = {Double, Parallel, Perpendicular, Double};

    const int num1 = evList[crysList[0]].crystalNum;
    const int num2 = evList[crysList[1]].crystalNum;

    switch(det) {
    case 10: //0b101000
    case 11: //0b101100
    case 13: //0b110100
    case 14: //0b111000
    {
        const unsigned int mask = 4 * det;
        const unsigned int a = num1 ^ mask;
        if(a < 4){
            const unsigned int b = num1 ^ num2;
            if(b < 4)
                return hitTable[b];
        }
        return Double;
    }
    default:
        throw string("made it to default case in checkDoubleGamma switch statement, something is wrong");
        break;
    }
    //Never reaches here
}
0
source

Source: https://habr.com/ru/post/1525554/


All Articles