$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 USEBANK
statement.
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.
JAZELLE
by 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.
POINTER
statement 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 P_
.
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;
NPHPSUM
will then be the number of PHPSUM banks.
JZBFND
. For example:
$CALL JZBFND( 'PHPSUM', P_PHPSUM ) ERROR RETURN;
P_PHPSUM
will then point to the first bank in the family.
JZBFND
but with some additional arguments. For example:
$CALL JZBFND( 'PHPSUM', P_PHPSUM, IDOUT, 'LAST' ) ERROR RETURN;
P_PHPSUM
will then point to the last bank in the family.
This function returns the extra variable IDOUT
which 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 'LAST'
,
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.
JZBFND
with the bank ID as the fourth argument. For example:
IDIN = 4; $CALL JZBFND( 'PHPSUM', P_PHPSUM, IDOUT, IDIN ) ERROR RETURN;
P_PHPSUM
will then point to the 4th bank in the family.
This function returns the extra variable IDOUT
which 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);
IPH
will then be the ID of the bank pointed to by
P_PHPSUM
.
JB$FORPT
construction.
For example:
P_PHPSUM = P_PHPSUM%(JB$FORPT);
BANKLOOP
construction.
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_PHPSUM
to point
to each PHPSUM
bank 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
IPART
would 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 PHPSUM
which contains all of the pointers to all of the PHPSUM
banks.
MAXID
set in their templates.
This MAXID
tells 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
MAXID
set 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 $USEBANK
statement in the declarations part of your routine.
For example:
$USEBANK PHPSUM;This statement includes an indexed pointer array, called
PHPSUM
,
which contains one pointer for each bank in the PHPSUM
family.
You then fill the indexed pointer array with a call to the routine
JZPIDX
.
For example:
$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 PHPSUM(1)
.
The pointer to the second bank would be PHPSUM(2)
.
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.
J$FIRST
and J$LAST
.
For example:
DO ITRACK = PHPSUM(J$FIRST), PHPSUM(J$LAST) [ ... your code here ]
To fill a regular pointer from an indexed pointer, just use =
.
For example:
P_PHPSUM = PHPSUM(22);The above would set the pointer
P_PHPSUM
to point to the
22nd PHPSUM
bank.
P_PHPSUM = PHPSUM(J$LAST);The above would set the pointer
P_PHPSUM
to point to the
last PHPSUM
bank.
To find the indexed pointer that matches a regular pointer,
use the %(JB$ID)
construction.
For example:
IPH = P_PHPSUM%(JB$ID); CHARGE = PHPSUM(IPH)%(CHARGE);
JZBADD
to add a bank.
For example, the following would add a KTAG bank, returning its pointer
as P_KTAG
:
$CALL JZBADD( 'KTAG', P_KTAG ) ERROR RETURN;
JZBPDEL
to delete a bank.
For example, the following would delete the KTAG bank pointed to by
P_KTAG
:
$CALL JZPDEL( P_KTAG ) ERROR RETURN;There is also the routine
JZBDEL
to 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
IKTAG
:
$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;
JZPCPY
to 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 P_NEWKTAG
:
$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.