At the end of a component TRACE function any instances which provided an EXTEND block introduce an if statement guarded block for its extend implementation.
The conditional statement checks the instance component number against the current component number, which is true exactly once for each particle.
If multiple components of the same type provide EXTEND blocks then an equal number of if statements are generated.
If those components happen to define the same EXTEND block, an equal number of copies of that block will be generated.
Example
For a test instrument that contains component instances generated by
for i in range(100):
instr += f"COMPONENT slit_{i} = Slit(xwidth=0.01, yheight=1)\n"
instr += f" AT ({sin(i/180 * pi)}, 0, {cos(i/180 * pi)}) RELATIVE sample\n"
instr += f" EXTEND %{{ who = (SCATTERED) ? {i}: 0; %}}\n"
instr += f"COMPONENT detector_{i} = Arm() WHEN ({i} == who) AT (0, 0, 1) RELATIVE slit_{i}\n"
instr += f" EXTEND %{{ what = (SCATTERED) ? 1: 0; %}}\n"
The Slit trace function ends with
if (_comp->_index == 10) { // EXTEND slit_0
who = (SCATTERED) ? 0: 0;
}
if (_comp->_index == 12) { // EXTEND slit_1
who = (SCATTERED) ? 1: 0;
}
...
if (_comp->_index == 206) { // EXTEND slit_98
who = (SCATTERED) ? 98: 0;
}
if (_comp->_index == 208) { // EXTEND slit_99
who = (SCATTERED) ? 99: 0;
}
and the Arm trace function ends with
if (_comp->_index == 11) { // EXTEND detector_0
what = (SCATTERED) ? 1: 0;
}
if (_comp->_index == 13) { // EXTEND detector_1
what = (SCATTERED) ? 1: 0;
}
...
if (_comp->_index == 207) { // EXTEND detector_98
what = (SCATTERED) ? 1: 0;
}
if (_comp->_index == 209) { // EXTEND detector_99
what = (SCATTERED) ? 1: 0;
}
Ideas
- Replacing the repeated extend block bodies by a function call is likely detrimental to the runtime.
- Replacing the repeated
if statements with a switch statement could allow the compiler to remove a large number of conditional checks
- and could remove repeated blocks by utilizing case fall through.
Possible replacement
The Slit trace part:
switch (_comp->_index) {
case 9: // EXTEND slit_0
{ who = (SCATTERED) ? 0: 0;
break;
}
case 11: // EXTEND slit_1
{ who = (SCATTERED) ? 1: 0;
break;
}
case 13: // EXTEND slit_2
{ who = (SCATTERED) ? 2: 0;
break;
}
...
case 205: // EXTEND slit_98
{ who = (SCATTERED) ? 98: 0;
break;
}
case 207: // EXTEND slit_99
{ who = (SCATTERED) ? 99: 0;
break;
}
default: break;
}
The Arm trace part:
switch (_comp->_index) {
case 10: // EXTEND detector_0
case 12: // EXTEND detector_1
...
case 206: // EXTEND detector_98
case 208: // EXTEND detector_99
{ what = (SCATTERED) ? 1: 0;
break;
}
default: break;
}
At the end of a component
TRACEfunction any instances which provided anEXTENDblock introduce an if statement guarded block for its extend implementation.The conditional statement checks the instance component number against the current component number, which is true exactly once for each particle.
If multiple components of the same type provide
EXTENDblocks then an equal number of if statements are generated.If those components happen to define the same
EXTENDblock, an equal number of copies of that block will be generated.Example
For a test instrument that contains component instances generated by
The
Slittrace function ends withand the
Armtrace function ends withIdeas
ifstatements with aswitchstatement could allow the compiler to remove a large number of conditional checksPossible replacement
The
Slittrace part:The
Armtrace part: