Repository navigation
det: FUNCTION NUMVAL in a fixed-point COMPUTE is exact decimal; IBM evaluates NUMVAL in long HFP (register C6) #4741
Description
Part of #4270. Found while making CBSA's BNK1CAC / BNK1TFN / BNK1UAC translate whole (NUMVAL in a floating-point expression).
What IBM does. NUMVAL / NUMVAL-C / NUMVAL-F "return long (64-bit) floating-point values in compatibility mode, and return extended-precision (128-bit) floating-point values in extended mode" (Enterprise COBOL 6.4 Programming Guide, SC27-8714-03, "Converting to numbers (NUMVAL, NUMVAL-C, NUMVAL-F)", p. 115); "The returned value is a floating-point approximation of the numeric value represented by argument-1" (6.4 Language Reference, SC27-8713-03, NUMVAL, p. 605). An operand that is "a reference to a numeric intrinsic function results in floating-point arithmetic when ... the function is a floating-point function" (Programming Guide, "Floating-point evaluations", p. 62). So COMPUTE B = FUNCTION NUMVAL(A) with B fixed point (IBM's own example on p. 115, and CBSA BNK1UAC l.906 COMPUTE COMM-OVERDRAFT = FUNCTION NUMVAL(OVERDRI(1:OVERDRL))) is a floating-point evaluation on z/OS: the value goes through long HFP and back.
What the det translator does. In a fixed-point expression (no COMP-1 / COMP-2 operand or receiver) NUMVAL is an exact decimal (Funcs.numval), as GnuCOBOL computes it. For values of at most 15 digits converted to long HFP and stored back with rounding, the result is the same; but register C6 ASSUMES a float result stored by an arithmetic statement into a fixed-point receiver is truncated unless ROUNDED, and a NUMVAL of e.g. 0.1 truncated to long HFP is 0.0999...: under that assumption COMPUTE N = FUNCTION NUMVAL('0.10') (N PIC 9V99) would give 0.09 on z/OS, the exact model 0.10. Which one z/OS gives is not documented (the conversion NUMVAL uses and the store of a float result into a fixed-point receiver).
To settle. Decide IBM's result for NUMVAL in a fixed-point COMPUTE (a z/OS run, #4050, or IBM documentation of the float-to-decimal store), then either model the long-HFP round trip there too or refuse values whose round trip is undocumented. Also: an argument of more than 18 digits (invalid under ARITH(COMPAT)) and more than 15 significant digits (IBM: precision lost "in an unexpected manner") are not refused on the fixed-point path (the float path, Hfp.numval, refuses both).
Activity
det: FUNCTION NUMVAL / NUMVAL-C in a floating-point expression as IBM…
det: refresh the coverage ledger for carddemo-tranadd (its case decla…
det: NUMVAL in a fixed-point statement rounds its store; drop the per…
carddemo-tranadd: the invalid-card scenario uses a 15-digit value; re…
det: re-prove carddemo-tranadd and refresh the coverage ledger after …
det sweep ledger: re-measured the 4 ports #4741 moves after the main …
det: NUMVAL / NUMVAL-C in a fixed-point COMPUTE as long HFP, its stor…