$CALL JZBLOC( 'PHPSUM', F_PHPSUM ) ERROR RETURN;and not
$CALL JZBLOC( 'phpsum', F_PHPSUM ) ERROR RETURN;In the interests of speed, Jazelle functions do not take the time to convert the family name to upper case for you. Be sure to supply all family names to Jazelle functions as upper case.
The first method, the one that works like a modern programming language,
is referred to as the "pointer" method.
The second method, the one that works like Fortran,
is referred to as the "indexed pointer" method.
It is also sometimes referred to as the "usebank" menthod, since one of
the statements required to in this method is the
We recommend you use the "pointer" method whenever you have a choice. Learn about the "indexed pointer" method just so you can recognize and debug it in other peoples code.
JAZELLEby including the following statement:
"&COMMON /JAZELL/"This sets up the basic structure necessary to make pointers work.
This statement can not have any spaces before it. It is, in that sense, different from any other kind of Prepmort statement.
Some routines do the same thing with the statement:
"© FROM JAZELL.COMMON"Again, this statement can not have any spaces before it. The general rule is, statements that begin with the two characters
"&can not have spaces before them.
Don't worry about how these statements work. Just make sure your routine contains one of them.
POINTERstatement in the declarations part of your routine. For example:
POINTER P_IEVENTH --> IEVENTH;The name of the pointer can be any string of up to eight characters.
People often start their pointers with the characters
After the underscore they put the name of the Jazelle family that this
pointer works with.
This is just a convention to make it clear that the variable in question
is a pointer and to tell what bank it points to.
But this is not required.
You could have your pointer be something less helpful such as
POINTER A --> IEVENTH;
Since one often sets up a pointer just to point at the head of a family,
some people use the convention
F_ for a pointer that points
to the head of a family.
For example, they might use:
POINTER F_PHPSUM --> PHPSUM;
JZBLOC. For example:
$CALL JZBLOC( 'PHPSUM', F_PHPSUM ) ERROR RETURN;
JZBLOC. For example:
$CALL JZBLOC( 'PHPSUM', F_PHPSUM, NPHPSUM ) ERROR RETURN;
NPHPSUMwill then be the number of PHPSUM banks.
JZBFND. For example:
$CALL JZBFND( 'PHPSUM', P_PHPSUM ) ERROR RETURN;
P_PHPSUMwill then point to the first bank in the family.
JZBFNDbut with some additional arguments. For example:
$CALL JZBFND( 'PHPSUM', P_PHPSUM, IDOUT, 'LAST' ) ERROR RETURN;
P_PHPSUMwill then point to the last bank in the family. This function returns the extra variable
IDOUTwhich is the bank ID of the bank that is found. This will be zero if no bank is found.
If that last argument is
'FRST' instead of
you get the first bank of the family. For example:
$CALL JZBFND( 'PHPSUM', P_PHPSUM, IDOUT, 'FRST' ) ERROR RETURN;As you have already seen, you get the same result by default when you leave out the last two arguments.
JZBFNDwith the bank ID as the fourth argument. For example:
IDIN = 4; $CALL JZBFND( 'PHPSUM', P_PHPSUM, IDOUT, IDIN ) ERROR RETURN;
P_PHPSUMwill then point to the 4th bank in the family. This function returns the extra variable
IDOUTwhich is the bank ID of the bank that is found. This will be 4 if the bank we were looking for was found or will be zero if the 4th bank did not exist.
%(JB$ID)construction. For example:
IPH = P_PHPSUM%(JB$ID);
IPHwill then be the ID of the bank pointed to by
JB$FORPTconstruction. For example:
P_PHPSUM = P_PHPSUM%(JB$FORPT);
This construction requires that you first declare two pointers to the family and that you set one of these pointers to the head of the family.
POINTER F_PHPSUM --> PHPSUM, P_PHPSUM --> PHPSUM; LOGICAL FIRST /.TRUE./; IF FIRST [ $CALL JZBLOC( 'PHPSUM', F_PHPSUM ) ERROR RETURN; FIRST = .FALSE. ; ]The following construction will cause
P_PHPSUMto point to each
PHPSUMbank in turn:
BANKLOOP F_PHPSUM, P_PHPSUM ... your code here ENDLOOP
CHARGE = P_PHPSUM%(CHARGE);
Here is an example in which we get a variety of information about a particular particle by following pointers from one bank to another:
POINTER P_PHPSUM --> PHPSUM, P_PHPOINT --> PHPOINT, P_PHCHRG --> PHCHRG, P_PHKLUS --> PHKLUS; " Assume that our particle of interest is pointed to by P_PHPSUM " CHARGE = P_PHPSUM%(CHARGE); P_PHPOINT = P_PHPSUM%(PHPOINT); "PHPSUM contains a pointer to PHPOINT" P_PHCHRG = P_PHPOINT%(PHCHRG); "PHPOINT contains a pointer to PHCHRG" IMPACT = P_PHCHRG%(IMPACT); P_PHKLUS = P_PHPOINT%(PHKLUS); "PHPOINT contains a pointer to PHKLUS" ERAW = P_PHKLUS%(ERAW);
Here is an example. The charge of the second PHPSUM partcle can be found as follows:
CHARGE = PHPSUM(2)%(CHARGE);The charge of the fifth PHPSUM particle can be found as follows:
CHARGE = PHPSUM(5)%(CHARGE);A variable can be used an the index as follows:
CHARGE = PHPSUM(IPART)%(CHARGE);where
IPARTwould be some integer variable.
You see that instead of having a standard pointer on the left side of the percent sign, you instead have something that looks like an old fashioned Fortran array. This is comforting to people who are very used to Fortran, but is much less powerful than the regular pointer method.
The method works by having you first create an array called
which contains all of the pointers to all of the
MAXIDset in their templates. This
MAXIDtells Jazelle the maximum number of banks that can ever exist for this family. Jazelle needs this information in order to set up some memory where it will store an index of pointers for this family.
An example of a bank that can be used with indexed pointers is
PHPSUM. It contains the line:
Bank PHPSUM Context=DST Maxid=1000 "Particle parameters"Some banks can not be used with indexed pointers since they do not have a
MAXIDset in their templates. When a bank is not going to be used with indexed pointers, there is no need for Jazelle to set up an index in advance. The user is free to make any number of banks in that family.
An example of a bank that can not be used with indexed pointers is
PHMTOC. It contains the line:
Bank PHMTOC CONTEXT=JAZELLE NOMAXID
When you use only the indexed pointer method in your routine, your routine does not need to include the statement
"&COMMON /JAZELL/"But it does not hurt if you accidentally include it.
You save including that one line, but you need to include some other things that are much worse.
When you need to use constructions that involve banks that point to banks that point to other banks, you will find the pointer method much easier to use than the indexed pointer method.
You declare the indexed pointer array by putting a
statement in the declarations part of your routine.
$USEBANK PHPSUM;This statement includes an indexed pointer array, called
PHPSUM, which contains one pointer for each bank in the
You then fill the indexed pointer array with a call to the routine
$CALL JZPIDX( 'PHPSUM', PHPSUM ) ERROR RETURN;
This routine must be called only once for each family that is to be used with indexed pointers. If someone else has already made this call in their routine, your routine may not need this call. But it does not hurt to call it a second time.
If you try to access a bank using indexed pointers and the appropriate
JZPIDX call has never been made, your routine will crash.
So it is best to include such a call in an
IF FIRST block
at the start of your routine.
The pointer to the first bank will then be
The pointer to the second bank would be
And, as mentioned above, you could access a Jazelle variable as follows:
CHARGE = PHPSUM(2)%(CHARGE);
J$NUMBER. This variable does not use the percent sign. For example:
NCHARGE = PHPSUM(J$NUMBER);
J$FIRST. For example:
FIRSTID = PHPSUM(J$FIRST);Note that this construction does not include the percent sign. That is because this value is not a variable in a bank, it is a variable that tells about the banks.
J$LAST. For example:
LASTID = PHPSUM(J$LAST);Again note that this construction does not include the percent sign.
DO ITRACK = PHPSUM(J$FIRST), PHPSUM(J$LAST) [ ... your code here ]
To fill a regular pointer from an indexed pointer, just use
P_PHPSUM = PHPSUM(22);The above would set the pointer
P_PHPSUMto point to the 22nd
P_PHPSUM = PHPSUM(J$LAST);The above would set the pointer
P_PHPSUMto point to the last
To find the indexed pointer that matches a regular pointer,
IPH = P_PHPSUM%(JB$ID); CHARGE = PHPSUM(IPH)%(CHARGE);
JZBADDto add a bank.
For example, the following would add a KTAG bank, returning its pointer
$CALL JZBADD( 'KTAG', P_KTAG ) ERROR RETURN;
JZBPDELto delete a bank.
For example, the following would delete the KTAG bank pointed to by
$CALL JZPDEL( P_KTAG ) ERROR RETURN;There is also the routine
JZBDELto delete a bank given its family name and bank ID rather than its pointer.
For example, the following would delete the KTAG bank with ID of
$CALL JZBDEL( 'KTAG', IKTAG ) ERROR RETURN;If the second argument is deleted, all banks of the given family are deleted.
For example, the following would delete all KTAG banks from the current event:
$CALL JZBDEL( 'KTAG' ) ERROR RETURN;
JZPCPYto copy a bank to a new bank, leaving the old bank unchanged.
For example, the following would copy the KTAG bank pointed to by
P_OLDKTAG to a new bank pointed to by
$CALL JZPCPY( P_OLDKTAG, P_NEWKTAG ) ERROR RETURN;
The Jazelle Manual is available nicely bound from SLAC Publications as SLAC Report 362 and can also be obtained from the SLD Offline Software Documentation Center, SLAC Central Lab Annex Room B105. At least one copy belongs in every SLD bookshelf.