IBM Mainframe Forum Index
 
Log In
 
IBM Mainframe Forum Index Mainframe: Search IBM Mainframe Forum: FAQ Register
 

NUMPROC PFD vs NOPFD


IBM Mainframe Forums -> COBOL Programming
Post new topic   Reply to topic
View previous topic :: View next topic  
Author Message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Mon May 02, 2011 4:56 am
Reply with quote

This topic has received some coverage in this forum before, but, from some recent questions (why did this not S0C7?) and idiotic code which "works" I think it is worth looking at.

Why? Because anyone with an ounce of programming-self-respect "feels" for the system when bad data gets into it.

Compiler option NUMPROC with NOPFD makes me sick to my stomach, at least initially.

First of all, what is PFD/NOPFD? PFD means "preferred", and NOPFD means "non-preferred" - however, don't take that as indicating the use of one over the other. What is "preferred", or not, is the sign symbol.

Ignoring "sign is seperate", IBM zoned and packed decimals have a "preferred" sign of C (positive), D (negative) or F (unsigned, assumed positive). "Non-preferred" opens up the possibility of other sign values, in fact A, B, C, D, E and F. Why? TBD.

Now, if you had a whole load of different sign values for your program to cater with, things would get more complicated. So, what NOPFD does is to "fix" the sign for you, so it can then only be a C, D or F when it is actually used for anything (IF, MOVE, calculation, any sort of reference) in your program. It doesn't "fix" the sign in the DATA DIVISION location, but in the progam's temporary storage area. Meaning that it does this each time any zoned (PIC (S)9(n) USAGE DISPLAY) or packed (COMP-3) field is referenced.

The way PFD (preferred sign) behaves is to assume that the DATA DIVISION fields all have a correct sign (C or D in PIC S9(n) and F in PIC 9(n)) with respect to the PICTURE.

Two main problems arise:

Code:

01  W-VALUE-IN-PICX PIC XXX.
01  W-VALUE-IN-PIC9 REDEFINES W-VALUE-IN-PICX PIC S999.

01  W-TEST-FOR-S0C7 COMP-3 PIC S999.


The zoned-decimal looks like this - ZNZNSN
The packed-decimal looks like this - NNNS

Z = Zone = Value Irrelevant
S = Sign (C, D, F valid or A, B, C, D, E, F valid)
N = Number (0-9 valid)

At the moment, restricting the discussion to zoned-decimals, it goes like this.

With NUMPROC(NOPFD)

Valid for Sign = Any single-byte binary value where high-order nibble is numeric. 160 distinct values.
Valid for Zone = Any single-byte binary value where low-order nibble is numeric. 160 distinct values.

Any receiving field, result of a MOVE, calculation, will have a "preferred sign" C, D or F. An unsigned source to a signed receiving field, will have a C.

NUMPROC(PFD)

Valid for Sign = Any single-byte binary value where high-order nibble is numeric and low-order nibble is C, D or F. 30 distinct values.
Valid for Zone = Any single-byte binary value where low-order nibble is numeric. 160 distinct values.

Any receving field will have its sign propagated from the source field (except in the case of an unsigned source to a signed receiving field, which will have a C).

What does all this mean?

Firstly, fewer S0C7s with NOPFD. Not good.

Secondly, potential errorenous processing with PFD if a signed field has an F for a sign, ie it contains an unsigned value. Not good.

For example, a zoned-decimal containing spaces, or low-values, will be treated as zero with NOPFD. When processed to a packed-decimal receiving field it will look like a completely valid field. With PFD it will S0C7.

For example, for PFD, a signed packed-decimal with an F sign will not compare correctly to another equal-length packed-decimal if a Compare Packed is not generated (ie if Compare Logical Characters is generated by the compiler). With NOPFD the comparison will always be "correct".

So, what do you do? If all your signs conform to the PICTURE, then PFD will always work, produce less code, and optimise better.

If all your signs do not conform to the PICTURE, NOPFD will "fix them" in receiving fields and all processing will be consistent - but a lot more "invalid" data could be made "valid". NOPFD will produce more code, for every reference to zoned- and packed-decimal fields in your program, and will not optimise as well.

So, it seems a bit sloppy. I prefer the sound of PFD so far.

For intial testing, I would use PFD for definite. More likely to get S0C7s. Beyond initial testing, I'd stick to whatever was set in production.

At the end of the day, with proper validation of all data entering the system, they should be equivalent. So, again, I'd go for PFD.

What I'd think long and hard about would be changing the value in production. Could be a nightmare waiting to happen.

Oh, and if you are calling FORTRAN or PL/I from your Cobol program, IBM says you should use NOPFD. I wonder what they get up to? Even there, I'd prefer to handle the individual fields going to those programs, and still use PFD.

Any comments, questions, thoughts, suggestions, attempts to sway me, are welcome.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Wed May 04, 2011 9:43 pm
Reply with quote

The "sign-fixing" of NUMPROC(NOPFD) is interesting, and not as bad as I was thinking it might be.

For example, here is an IF comparing two PIC S9(4) zoned decimals:

Code:

000052  IF
   00035E  F223 D0F0 A000          PACK  240(3,13),0(4,10)       TS2=0            W-DISPNUM-SIZE4-S
   000364  F223 D0F8 A040          PACK  248(3,13),64(4,10)      TS2=8            W-DISPNUM-SIZE4-ST
   00036A  F922 D0F0 D0F8          CP    240(3,13),248(3,13)     TS2=0            TS2=8
   000370  4770 B15A               BC    7,346(0,11)             GN=5(000386)


Pretty straightforward. Pack 'em into temporary storage, packed compare, branch on condition. Although the PACK leaves the signs alone, the CP "knows" about non-preferred signs. So here, no "sign-fixing" at all.

Here is a MOVE involving the same two fields.

Code:

000053  MOVE
   000374  F223 D0F0 A000          PACK  240(3,13),0(4,10)       TS2=0              W-DISPNUM-SIZE4-S
   00037A  F822 D0F0 D0F0          ZAP   240(3,13),240(3,13)     TS2=0              TS2=0
   000380  F332 A040 D0F0          UNPK  64(4,10),240(3,13)      W-DISPNUM-SIZE4-ST TS2=0


Now it gets more interesting. Pack the field with the potential non-preferred sign into Temporary Storage. Then ZAP (Zero and Add Packed) it to itself! What does that do? Well, the "ADD" part is what is crucial here, because, from the POP:

Quote:

The preferred sign codes are 1100 for plus and 1101 for minus. These are the sign codes generated for the results of the decimal-arithmetic instructions and the CONVERT TO DECIMAL instruction.

Alternate sign codes are also recognized as valid in the sign position: 1010, 1110, and 1111 are alternate codes for plus, and 1011 is an alternate code for minus. Alternate sign codes are accepted for any decimal source operand, but are not generated in the completed result of a decimal-arithmetic instruction or CONVERT TO DECIMAL. This is true even when an operand remains otherwise unchanged, such as when adding zero to a number. An alternate sign code is, however, left unchanged by MOVE NUMERICS, MOVE WITH OFFSET, MOVE ZONES, PACK, and UNPACK.


(my emphasis added).

So the ZAP is how NOPFD does the "sign-fixing" in this case (two signed four byte, zoned decimals, in a MOVE).

Having ZAP'd it, unpack it in to the receiving field.

For PFD, by comparison:

Code:

000052  IF
   00035E  D503 A000 A040          CLC   0(4,10),64(10)          W-DISPNUM-SIZE4-S  W-DISPNUM-SIZE4-ST
   000364  4770 B142               BC    7,322(0,11)             GN=5(00036E)


Now, this is doing a logical compare. If one of the signs is actually non-preferred, then the compare is not going to work properly. More on that later.


Code:

000053  MOVE
   000368  D203 A040 A000          MVC   64(4,10),0(10)          W-DISPNUM-SIZE4-ST W-DISPNUM-SIZE4-S


And the move, just picks up four bytes and drops 'em down again in the right place.

So far, this is un-optimised code.

So, NOPFD again

Code:

000052  IF
   000256  F223 D100 A000          PACK  256(3,13),0(4,10)       OPT=0              W-DISPNUM-SIZE4-S
   00025C  F223 D0F8 A030          PACK  248(3,13),48(4,10)      TS2=8              W-DISPNUM-SIZE4-ST
   000262  F922 D100 D0F8          CP    256(3,13),248(3,13)     OPT=0              TS2=8
   000268  4770 B060               BC    7,96(0,11)              GN=5(000278)


Code is the same for the IF, except for use of OPT storage for one field.

Code:

   00026C  F822 D100 D100          ZAP   256(3,13),256(3,13)     OPT=0              OPT=0
   000272  F332 A030 D100          UNPK  48(4,10),256(3,13)      W-DISPNUM-SIZE4-ST OPT=0



For the MOVE, one instruction is saved, because it's value has already been packed from the IF immediately before it. Still doing the ZAP to itself.

Code:

000052  IF
   000256  D503 A000 A030          CLC   0(4,10),48(10)          W-DISPNUM-SIZE4-S  W-DISPNUM-SIZE4-ST
   00025C  4770 B04E               BC    7,78(0,11)              GN=5(000266)
000053  MOVE
   000260  D203 A030 A000          MVC   48(4,10),0(10)          W-DISPNUM-SIZE4-ST W-DISPNUM-SIZE4-S


For PFD, the IF and the MOVE remain the same, even when OPT'd.
Back to top
View user's profile Send private message
Akatsukami

Global Moderator


Joined: 03 Oct 2009
Posts: 1788
Location: Bloomington, IL

PostPosted: Wed May 04, 2011 10:24 pm
Reply with quote

Bill Woodger wrote:
Ignoring "sign is seperate", IBM zoned and packed decimals have a "preferred" sign of C (positive), D (negative) or F (unsigned, assumed positive). "Non-preferred" opens up the possibility of other sign values, in fact A, B, C, D, E and F. Why? TBD.

It may be worth noting that an overpunched positive sign (punch in zone 12) is interpreted as {-I (EBCDIC C0-C9) and an overpunched negative sign (punch in zone 11) is interpreted as }-R (EBCDIC D0-D9), which is probably why C, D, and F are "preferred".

Overpunching goes back to 1928, IIRC; the association between overpunched digits and alphas is no later than the introduction of the 360 in 1964, and probably older. Unless IBM recorded the reasons (or lack thereof), anyone who could tell us the "whys" has probably long since shuffled off this mortal coil.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Thu May 05, 2011 4:23 am
Reply with quote

Thanks Mr Akatsukami. Understood. Any ideas why the potential to encounter non-preferred signs exists in Cobol to the extent that IBM added the NUMPROC compiler option? VS Cobol had no special processing for them. I guess if they had appeared, they would have failed NUMERIC tests, but otherwise would have got along reasonably well. I have never seen one. I just assumed it was something "assembler guys" used to do, but we didn't need to. Now, there it is. Is it because of the Cobol 85 standard? Is it because of the Web stuff now available? Some managerial nonsense, having found it on some "to do" list from 1964?

Other than deliberately making one, has anyone ever seen a "non-preferred" sign? If they are not scattered all over DASD, why do we have a "new" compiler option for them?
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Thu May 05, 2011 4:56 am
Reply with quote

The next example is four byte zoned signed to four byte zoned unsigned.

With NOPFD, for the IF
Code:

000059  IF
   000386  F223 D0F0 A000          PACK  240(3,13),0(4,10)       TS2=0              W-DISPNUM-SIZE4-S
   00038C  F223 D0F8 A048          PACK  248(3,13),72(4,10)      TS2=8              W-DISPNUM-SIZE4-UT
   000392  960F D0FA               OI    250(13),X'0F'           TS2=10
   000396  F922 D0F0 D0F8          CP    240(3,13),248(3,13)     TS2=0              TS2=8
   00039C  4770 B17E               BC    7,382(0,11)             GN=6(0003AA)


Again, Pack, Pack. Then ensure that the unsigned field is unsigned. Compare packed.

For the MOVE
Code:

000060  MOVE
   0003A0  D203 A048 A000          MVC   72(4,10),0(10)          W-DISPNUM-SIZE4-UT W-DISPNUM-SIZE4-S
   0003A6  96F0 A04B               OI    75(10),X'F0'            W-DISPNUM-SIZE4-UT+3


This time an MVC is used, and the sign is "fixed" for the destination. Can we deduce, from this and the signed-to-signed example previously, that the method for the MOVE is dependent on how the sign is "fixed"? PACK-ZAP-UNPACK for the signed field, because the ZAP is doing the fixing, MVC for the unsigned field because the OI will do the fixing.

With PFD for the IF
Code:

000059  IF
   00036E  F223 D0F0 A000          PACK  240(3,13),0(4,10)       TS2=0              W-DISPNUM-SIZE4-S
   000374  F223 D0F8 A048          PACK  248(3,13),72(4,10)      TS2=8              W-DISPNUM-SIZE4-UT
   00037A  F922 D0F0 D0F8          CP    240(3,13),248(3,13)     TS2=0              TS2=8
   000380  4770 B162               BC    7,354(0,11)             GN=6(00038E)


Which is the same as for NOPFD except for the assumption that the unsigned field has an F sign, rather than forcing it (in NOPFD) for the compare. CLC cannot be used, as the signs should be different.

For the MOVE
Code:

000060  MOVE
   000384  D203 A048 A000          MVC   72(4,10),0(10)          W-DISPNUM-SIZE4-UT W-DISPNUM-SIZE4-S
   00038A  96F0 A04B               OI    75(10),X'F0'            W-DISPNUM-SIZE4-UT+3


Exactly the same as for NOPFD. This time sign is "fixed" to unsiged, because that is the sort of field it is.

OPT, NOPFD
Code:

000059  IF
   000278  F223 D100 A000          PACK  256(3,13),0(4,10)       OPT=0              W-DISPNUM-SIZE4-S
   00027E  F223 D0F8 A038          PACK  248(3,13),56(4,10)      TS2=8              W-DISPNUM-SIZE4-UT
   000284  960F D0FA               OI    250(13),X'0F'           TS2=10
   000288  F922 D100 D0F8          CP    256(3,13),248(3,13)     OPT=0              TS2=8
   00028E  4770 B084               BC    7,132(0,11)             GN=6(00029C)


Again, like the example previously posted, other than using OPT storage to save the value for later (elsewhere in the program this time) the IF is the same as the unoptimised one.

Code:

000060  MOVE
   000292  D203 A038 A000          MVC   56(4,10),0(10)          W-DISPNUM-SIZE4-UT W-DISPNUM-SIZE4-S
   000298  96F0 A03B               OI    59(10),X'F0'            W-DISPNUM-SIZE4-UT+3


Same instructions as the non-optimised.

OPT, PFD
Code:

000059  IF
   000266  F223 D100 A000          PACK  256(3,13),0(4,10)       OPT=0              W-DISPNUM-SIZE4-S
   00026C  F223 D0F8 A038          PACK  248(3,13),56(4,10)      TS2=8              W-DISPNUM-SIZE4-UT
   000272  F922 D100 D0F8          CP    256(3,13),248(3,13)     OPT=0              TS2=8
   000278  4770 B06E               BC    7,110(0,11)             GN=6(000286)

Code:

000060  MOVE
   00027C  D203 A038 A000          MVC   56(4,10),0(10)          W-DISPNUM-SIZE4-UT W-DISPNUM-SIZE4-S
   000282  96F0 A03B               OI    59(10),X'F0'            W-DISPNUM-SIZE4-UT+3


Both sets of code mirror the non-optimised PFD, except for the preparatory storage for use later.

When comparing the same length signed zoned to unsigned zoned, the code generated of NOPFD and PFD is very similar (one extra OI for NOPFD) and is only open to any optimisation at all where a non-receiving field is used more than once.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Thu May 05, 2011 12:59 pm
Reply with quote

Bill Woodger wrote:
[...]

Other than deliberately making one, has anyone ever seen a "non-preferred" sign? If they are not scattered all over DASD, why do we have a "new" compiler option for them?


I may have been looking at this the wrong way. What NUMPROC(PFD) does is change the way the Cobol compiler generates code for decimals in some common instances. For instance, using CLC instead of CP, MVC instead of ZAP. Goes much faster, well, faster, but your data has to conform to the "preferred" signs. A CP can compare sign F to sign C and find them equal (if the amounts are equal, of course). A CLC cannot.

So maybe NUMPROC(PFD) is NUMPROC(GO-FASTER) and NUMPROC(NOPFD) is NUMPROC(SLOW-DOWN-THE-SIGNS-MIGHT-BE-ODD).

So it is not really all the other odd signs getting in the way, it is when you get an F in a signed field. Not difficult to do (if you want to do that), but when it happens in error it is difficult to get through testing. Well, it should be.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Sun May 08, 2011 5:39 am
Reply with quote

The next example is four byte zoned signed to seven byte zoned unsigned.

With NOPFD, for the IF
Code:

000066  IF
   0003AA  F223 D0F0 A000          PACK  240(3,13),0(4,10)       TS2=0              W-DISPNUM-SIZE4-S
   0003B0  F236 D0F8 A050          PACK  248(4,13),80(7,10)      TS2=8              W-DISPNUM-SIZE7-ST
   0003B6  F923 D0F0 D0F8          CP    240(3,13),248(4,13)     TS2=0              TS2=8
   0003BC  4770 B1A6               BC    7,422(0,11)             GN=7(0003D2)


Again, a straight PACK, PACK, Compare Packed. Just to emphasise, as is indicated in the manual, NOPFD does not always generate "sign fixing" code. Here it does not. It doesn't need to, because the CP can understand all the possibile signs and do a correct comparison.

Code:

000067  MOVE
   0003C0  F223 D0F0 A000          PACK  240(3,13),0(4,10)       TS2=0              W-DISPNUM-SIZE4-S
   0003C6  F822 D0F0 D0F0          ZAP   240(3,13),240(3,13)     TS2=0              TS2=0
   0003CC  F362 A050 D0F0          UNPK  80(7,10),240(3,13)      W-DISPNUM-SIZE7-ST TS2=0


Here, for the MOVE, we need the "sign fixing", to ensure that the receivng field has a "preferred sign".

For PFD, same source code:

Code:

000066  IF
   00038E  F233 D0F0 A000          PACK  240(4,13),0(4,10)       TS2=0              W-DISPNUM-SIZE4-S
   000394  F236 D0F8 A050          PACK  248(4,13),80(7,10)      TS2=8              W-DISPNUM-SIZE7-ST
   00039A  D503 D0F0 D0F8          CLC   240(4,13),248(13)       TS2=0              TS2=8
   0003A0  4770 B184               BC    7,388(0,11)             GN=7(0003B0)


Here, an interesting development. Packing both fields to four-bytes and then a logical compare. Why not pad with three leading zeros the four-byte zoned field in temporary storage and then a CLC? I don't know.

Code:

000067  MOVE
   00029C  D202 A040 C004          MVC   64(3,10),4(12)          W-DISPNUM-SIZE7-ST SYSLIT AT +4
   0002A2  D203 A043 A000          MVC   67(4,10),0(10)          W-DISPNUM-SIZE7-ST+3 W-DISPNUM-SIZE4-S


Although, curiously, the padding of three leading zeros is how the compiler achieves the MOVE.

OPT, NOPFD

Code:

000066  IF
   00029C  F236 D0F8 A040          PACK  248(4,13),64(7,10)      TS2=8                     W-DISPNUM-SIZE7-ST
   0002A2  F923 D100 D0F8          CP    256(3,13),248(4,13)     OPT=0                     TS2=8
   0002A8  4770 B0A0               BC    7,160(0,11)             GN=7(0002B8)


Here, the four-byte signed, zoned, field has already been allocated space in the Optimisation area, ie in OPT=0 there is a packed representation of the field, three bytes long. So, then compare packed. Wait, though, although it doesn't matter, what is the sign-type of OPT=0. Let's look back at the last post with code in. OK, so it is still potentially non-preferred.

Code:

000067  MOVE
   0002AC  F822 D100 D100          ZAP   256(3,13),256(3,13)     OPT=0              OPT=0
   0002B2  F362 A040 D100          UNPK  64(7,10),256(3,13)      W-DISPNUM-SIZE7-ST OPT=0


Now, we ZAP the OPT=0, and unpack it to the receiving field. Both OPT=0 and the receiving field are now preferred signs. The optimiser has removed two pack instructions in total, by using the OPT=0 field established earlier.


OPT, PFD

Code:

000066  IF
   000286  F233 D108 A000          PACK  264(4,13),0(4,10)       OPT=8              W-DISPNUM-SIZE4-S
   00028C  F236 D0F8 A040          PACK  248(4,13),64(7,10)      TS2=8              W-DISPNUM-SIZE7-ST
   000292  D503 D108 D0F8          CLC   264(4,13),248(13)       OPT=8              TS2=8
   000298  4770 B090               BC    7,144(0,11)             GN=7(0002A8)


Sticking with the theme, pack both fields to four bytes, and do a logical compare. Note that W-DISPNUM-SIZE4-S is now in two OPT locations, firstly as three bytes packed, secondly as four bytes packed.

Code:

000067  MOVE
   00029C  D202 A040 C004          MVC   64(3,10),4(12)          W-DISPNUM-SIZE7-ST SYSLIT AT +4
   0002A2  D203 A043 A000          MVC   67(4,10),0(10)          W-DISPNUM-SIZE7-ST+3 W-DISPNUM-SIZE4-S


Identical to the un-optimised MOVE. Three zeros padded on the front, then an MVC.

When comparing two signed zoned fields, the code for NOPFD differs substantially from PFD. NOPFD sticks to decimal instructions, PFD uses CLC and a couple of MVC's.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Sun May 08, 2011 6:13 am
Reply with quote

Next up, four bytes zoned signed to seven bytes zoned unsigned. I wonder if we can predict the code yet?

For NOPFD, Pack (3 bytes), Pack (four bytes), OI, CP. MVC LIT, MVC, OI.
For PFD, Pack (four bytes), Pack (four bytes), CP. MVC LIT, MVC, OI.

And for the optimised?

NOPFD
Code:

000073  IF
   0002B8  F223 D100 A000          PACK  256(3,13),0(4,10)       OPT=0              W-DISPNUM-SIZE4-S
   0002BE  F236 D0F8 A048          PACK  248(4,13),72(7,10)      TS2=8              W-DISPNUM-SIZE7-UT
   0002C4  960F D0FB               OI    251(13),X'0F'           TS2=11
   0002C8  F923 D100 D0F8          CP    256(3,13),248(4,13)     OPT=0              TS2=8
   0002CE  4770 B0CA               BC    7,202(0,11)             GN=8(0002E2)


Hang about. Why is that setting OPT=0 again? Well, I missed it earlier, but what is happening is that every time the compiler generates the ZAP-to-itself as part of the MOVE, to get the "preferred sign", then it has to reset OPT=0 (in this case). The result being that for NOPFD the OPT fields for packed data have less of a life-span. The compiler knows the value has changed, if it has carried out "sign fixing", so cannot use it again without re-setting it first. Yet, if it did use it again without resetting, it would make no difference at all to the results of anything. The CP does not mind about the signs as long as they are valid. The receiving field always contains a preferred sign. The manual hints at problems like this when discussing performance.

There is nothing remarkable about the MOVE, as it is the same as the two above.

For OPT, PFD one instruction is saved through the use of the 3-byte packed OPT=0, otherwise the code is the same as for NOOPT, PFD.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Sun May 08, 2011 2:03 pm
Reply with quote

Having looked at a 4-byte signed zoned decimal being compare 4- and 7-byte signed and unsiged zoned decimals, let's have a look at comparing it to a packed decimal.

NOPFD, IF
Code:

000080  IF
   0003FC  F223 D0F0 A000          PACK  240(3,13),0(4,10)       TS2=0              W-DISPNUM-SIZE4-S
   000402  F822 D0F0 D0F0          ZAP   240(3,13),240(3,13)     TS2=0              TS2=0
   000408  F922 A060 D0F0          CP    96(3,10),240(3,13)      W-COMP3PD-SIZE4-ST TS2=0
   00040E  4770 B1F2               BC    7,498(0,11)             GN=9(00041E)


There is nothing unusual here, except, why is it doing the ZAP? OK, it does the ZAP to get a preferred sign, but why does it want a preferred sign, the CP can handle non-preferred as well. In none of the code generated for the zoned fields, which were all packed before doing a CP, did the ZAP-to-itself get done.

Code:

   000412  F223 A060 A000          PACK  96(3,10),0(4,10)        W-COMP3PD-SIZE4-ST W-DISPNUM-SIZE4-S
   000418  F822 A060 A060          ZAP   96(3,10),96(3,10)       W-COMP3PD-SIZE4-ST W-COMP3PD-SIZE4-ST

Pack into the receiver, then ZAP the receiver to itself. Expected.

With PFD, IF
Code:

000080  IF
   0003D6  F223 D0F0 A000          PACK  240(3,13),0(4,10)       TS2=0              W-DISPNUM-SIZE4-S
   0003DC  D502 A060 D0F0          CLC   96(3,10),240(13)        W-COMP3PD-SIZE4-ST TS2=0
   0003E2  4770 B1C0               BC    7,448(0,11)             GN=9(0003EC)


Just a PACK and CLC.

Code:

000081  MOVE
   0003E6  F223 A060 A000          PACK  96(3,10),0(4,10)        W-COMP3PD-SIZE4-ST W-DISPNUM-SIZE4-S


And just a PACK into the receiving field.

For OPT, NOPFD
Code:

000080  IF
   0002E2  D202 D108 D100          MVC   264(3,13),256(13)       OPT=8              OPT=0
   0002E8  F822 D100 D100          ZAP   256(3,13),256(3,13)     OPT=0              OPT=0
   0002EE  F922 A050 D100          CP    80(3,10),256(3,13)      W-COMP3PD-SIZE4-ST OPT=0
   0002F4  4770 B0EC               BC    7,236(0,11)             GN=9(000304)


This time, the code makes use of OPT=8 to generate a new OPT=0 with an MVC, then continues as usual.

Code:

000081  MOVE
   0002F8  F223 A050 A000          PACK  80(3,10),0(4,10)      W-COMP3PD-SIZE4-ST   W-DISPNUM-SIZE4-S
   0002FE  F822 A050 A050          ZAP   80(3,10),80(3,10)       W-COMP3PD-SIZE4-ST W-COMP3PD-SIZE4-ST


For the MOVE, just pack into the receiver and ZAP-to-itself.

For OPT, PFD
Code:

000080  IF
   0002C8  D502 A050 D100          CLC   80(3,10),256(13)        W-COMP3PD-SIZE4-ST OPT=0
   0002CE  4770 B0C0               BC    7,192(0,11)             GN=9(0002D8)


Using OPT=0 which has preserved the 3-byte packed value of the 4-byte zoned, just a logical compare.

Code:

000081  MOVE
   0002D2  F223 A050 A000          PACK  80(3,10),0(4,10)        W-COMP3PD-SIZE4-ST W-DISPNUM-SIZE4-S


And then just a PACK to the receiver.

Overall, to this packed field, the only unexpected this is the ZAP-in-place for the IF with NOPFD, both NOOPT and OPT. Still can't think why it does it.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Sun May 08, 2011 2:44 pm
Reply with quote

Now 4-byte signed zoned to 3-byte unsigned packed.

With NOPFD, IF
Code:

000087  IF
   00041E  F223 D0F0 A000          PACK  240(3,13),0(4,10)       TS2=0              W-DISPNUM-SIZE4-S
   000424  F822 D0F0 D0F0          ZAP   240(3,13),240(3,13)     TS2=0              TS2=0
   00042A  D202 D0F8 A068          MVC   248(3,13),104(10)       TS2=8              W-COMP3PD-SIZE4-UT
   000430  960F D0FA               OI    250(13),X'0F'           TS2=10
   000434  F922 D0F8 D0F0          CP    248(3,13),240(3,13)     TS2=8              TS2=0
   00043A  4770 B21C               BC    7,540(0,11)             GN=10(000448)


Pack it, ZAP-in-place (again curious), MVC and OI for the unsigned packed, then compare packed.

Code:

000088  MOVE
   00043E  F223 A068 A000          PACK  104(3,10),0(4,10)       W-COMP3PD-SIZE4-UT  W-DISPNUM-SIZE4-S
   000444  960F A06A               OI    106(10),X'0F'           W-COMP3PD-SIZE4-UT+2


Just a Pack, and the OI to keep the receiver unsigned.

With PFD, IF

Code:

000087  IF
   0003EC  F223 D0F0 A000          PACK  240(3,13),0(4,10)       TS2=0              W-DISPNUM-SIZE4-S
   0003F2  F922 A068 D0F0          CP    104(3,10),240(3,13)     W-COMP3PD-SIZE4-UT TS2=0
   0003F8  4770 B1DA               BC    7,474(0,11)             GN=10(000406)

Here the Pack, and, as the already packed field is unsigned, a Compare Packed, not a Compare Logical.

Code:

000088  MOVE
   0003FC  F223 A068 A000          PACK  104(3,10),0(4,10)       W-COMP3PD-SIZE4-UT  W-DISPNUM-SIZE4-S
   000402  960F A06A               OI    106(10),X'0F'           W-COMP3PD-SIZE4-UT+2


Pack, and OI, to ensure an unsigned receiver.

OPT, NOPFD
Code:

000087  IF
   000304  D202 D0F8 A058          MVC   248(3,13),88(10)        TS2=8              W-COMP3PD-SIZE4-UT
   00030A  960F D0FA               OI    250(13),X'0F'           TS2=10
   00030E  F922 D0F8 D100          CP    248(3,13),256(3,13)     TS2=8              OPT=0
   000314  4770 B10A               BC    7,266(0,11)             GN=10(000322)

MVC and OI for the packed unsigned field, then compare packed to the OPT=0 field previously stored. Curiously, this time the OPT=0 hasn't been refreshed, even though the current value is a preferred sign.

Code:

000088  MOVE
   000318  F223 A058 A000          PACK  88(3,10),0(4,10)        W-COMP3PD-SIZE4-UT   W-DISPNUM-SIZE4-S
   00031E  960F A05A               OI    90(10),X'0F'            W-COMP3PD-SIZE4-UT+2

Pack and OI, nothing surprising.

OPT, PFD
Code:

000087  IF
   0002D8  F922 A058 D100          CP    88(3,10),256(3,13)      W-COMP3PD-SIZE4-UT OPT=0
   0002DE  4770 B0D4               BC    7,212(0,11)             GN=10(0002EC)


Compare Packed (because unsigned) to the previously stored OPT=0.

Code:

000088  MOVE
   0002E2  F223 A058 A000          PACK  88(3,10),0(4,10)        W-COMP3PD-SIZE4-UT W-DISPNUM-SIZE4-S
   0002E8  960F A05A               OI    90(10),X'0F'            W-COMP3PD-SIZE4-UT+2


Pack and OI.

Because it is interesting above that an OPT=0 with a preferred sign is used for OPT, NOPFD, let's just check by looking at where it is established as well.

Code:

000080  IF
   0002E2  D202 D108 D100          MVC   264(3,13),256(13)       OPT=8              OPT=0
   0002E8  F822 D100 D100          ZAP   256(3,13),256(3,13)     OPT=0              OPT=0
   0002EE  F922 A050 D100          CP    80(3,10),256(3,13)      W-COMP3PD-SIZE4-ST OPT=0
   0002F4  4770 B0EC               BC    7,236(0,11)             GN=9(000304)
000081  MOVE
   0002F8  F223 A050 A000          PACK  80(3,10),0(4,10)        W-COMP3PD-SIZE4-ST W-DISPNUM-SIZE4-S
   0002FE  F822 A050 A050          ZAP   80(3,10),80(3,10)       W-COMP3PD-SIZE4-ST W-COMP3PD-SIZE4-ST
   000304                 GN=9     EQU   *
000087  IF
   000304  D202 D0F8 A058          MVC   248(3,13),88(10)        TS2=8              W-COMP3PD-SIZE4-UT
   00030A  960F D0FA               OI    250(13),X'0F'           TS2=10
   00030E  F922 D0F8 D100          CP    248(3,13),256(3,13)     TS2=8              OPT=0
   000314  4770 B10A               BC    7,266(0,11)             GN=10(000322)


The ZAP-to-itself at displacement 0002E8 is the last instruction which updates OPT=0. Out of the ZAP the sign is preferred. When we go to the next IF instruction, the already preferred OPT=0 is used (even though the sign doesn't matter, as long as valid, for the CP).

This does not follow the previous usage of OPT=0 in these examples. There, if the sign was "rectified", the OPT=0 would be refreshed. Here, not.
Back to top
View user's profile Send private message
PeterHolland

Global Moderator


Joined: 27 Oct 2009
Posts: 2481
Location: Netherlands, Amstelveen

PostPosted: Sun May 08, 2011 3:15 pm
Reply with quote

Oh my goodness, and now?
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Sun May 08, 2011 6:25 pm
Reply with quote

I suppose I am a little "over interested"? When I see those tantalising little bits in the manual, I can't help but wonder why? Sometimes helps. Never hurts (me :-) ).

I get the point.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Mon May 09, 2011 4:32 am
Reply with quote

OK, starting to wind this up.

NUMPROC(NOPFD) does "sign fixing" (another term for this is "sign rectification"). This is not as bad as it sounded to me originally. Previously I had known "sign fixing" in Cobol as the extra code generated to ensure that an unsigned field remained unsigned, so I was concerned about how NOPFD did this for potential "non-preferred signs".

From the Priciples of Operation (POP).
Quote:
The preferred sign codes are 1100 for plus and
1101 for minus. These are the sign codes generated
for the results of the decimal-arithmetic
instructions and the CONVERT TO DECIMAL
instruction.


The result generated, by the CPU, before anyone can get their sticky fingers on it, can only be sign C or D. ZAP is a decimal-arithmetic instruction. ZAP-to-itself is possible (operates right-to-left in this case). So a field which might potentially contain a non-preferred sign can have it "recitified" by a ZAP-to-itself. Compare Packed knows about non-preferred signs, and will compare them correctly.

One other "rectification" is carried out with NOPFD. If a field is unsigned, NOPFD will ensure that it is unsigned for all references to that field (source or receiver).

Two other rectifications are not to do with the NOPFD option, but are the way that Cobol works.

An alphanumeric (PIC X(n)) as a sending field always results in a positive (C) in a signed field (and an F in an unsigned field).

An unsigned field as the source always gives a positive (C) in a signed receiving field.

For a packed receiver this is achieved by using MVN (Move Numerics) on the last byte of the field (ironic, because in that byte the "numeric" is the sign, but it achieves the affect).

For a zoned receiver this is achieved by Or Immediate (OI) to get the F (unsigned) and OI followed by And Immediate (NI) to get the positive (C).

NOPFD relieves heavily on Compare Packed (CP) for "IF tests". This is traditionally the case. With decimal fields, you expect a decimal compare. You can also expect a S0C7 if either field is invalid.

NOPFD will use Compare Logical (CLC) for some compares. If you are comparing two unsigned decimals, either zoned or packed or mixed, and of equal or different size, NOPFD will generate a CLC. You cannot expect an S0C7 (or any abend) in this instance if either field is invalid.

NUMPROC(PFD) does not do "sign fixing", except where required to obey the Cobol rules, as NOPFD does. PFD assumes that a signed field can only contain a C or D sign (F may not give valid results) and an unsiged field can only contain an F sign.

PFD uses Compare Logical (CLC) for "IF tests" more heavily than does NOPFD. You cannot expect an S0C7 (or any abend) in this instance if either field is invalid.

PFD will use Compare Packed (CP) for some compares. If the fields are not the same length by the time a compare of some sort is going to be generated, or one field is signed and the other not, PFD will generate a CP (yes, there is a chicken-or-the-egg situation that is resolved for this). You can expect a S0C7 if either field is invalid.

Both NOPFD and PFD generate CLCs. Both generate CPs. NOPFD will likely generate fewer CLCs.

NOPFD will generate more code, and will tend to generate code options which take longer to execute (because the need for non-preferred processing precludes shorter execution time options).

NOPFD does not optimise very well. Using the ZAP for sign-rectification reduces optimisation options, even the use of OPT fields to retain a value which can be used more than once in a block of code (if a field theoretically has to be packed five times in a block of code, but its value does not change, then it only needs to be packed once and then the value is already available for the other four places).

PFD already produces fairly "good" code from a performance point of view, but still has more possibilities for optimisation that NOPFD.

For decimal fields, PFD OPT is up to 20% faster than NOPFD OPT. This does not mean your program will be up to 20% faster, because your program will be doing many things other than processing decimal fields. If you are processing a lot of decimal fields a lot of time you would expect to be able to notice the difference in CPU usage between the two options.

Remember, you can't just decide to use a different option for your development cycle. Use what you use in production for that. Only change an option in production after very long consideration if potential impacts. PFD works is all your fields are signed correctly, NOPFD works if some (or even all) of your fields have non-preferred signs.

The worst culprits for the amount of code generated are unsigned fields. If you are calculating with the field, give it a sign. If you are not calculating with it, unsigned makes sense. The Oldies amongst us know this from way back. However, with NOPFD, even testing an unsigned field gets you sign-rectification. As does moving to an unsiged field.

Last thought for this post. A non-preferred sign that you do anything to as a receiving field, becomes a preferred sign, with NOPFD. With PFD, if a field contains a non-preffered or F sign, any calculation (including ZAP) will "rectify" it.
Back to top
View user's profile Send private message
View previous topic :: :: View next topic  
Post new topic   Reply to topic View Bookmarks
All times are GMT + 6 Hours
Forum Index -> COBOL Programming

 


Similar Topics
Topic Forum Replies
No new posts NUMPROC(NOPDF) VS NUMPROC(PDF) - How ... COBOL Programming 15
No new posts Got S0C7 error while running job with... COBOL Programming 7
Search our Forums:

Back to Top