/* Call as: PACK(nbr,scale,prec) (commas required) Pack the argument. The argument-number must be a number. 'Scale' is the total number of digits. 'Prec' is the number of decimal places. If 'prec' is not specified, default to zero. If 'scale' is not specified, make it large enough to accommodate the number. 'Scale' must be odd. 'C' is the positive sign-nibble; 'D' is the negative sign-nibble. Fill out the 'frac' with zeroes on the right. Fill out the 'whol' with zeroes on the left. Join without the decimal point and with the sign-nibble. Convert to hex. . ----------------------------------------------------------------- */ PACK: /*@ */ arg nbr,scale,prec . /* 347.23 5 2 */ if \Datatype(nbr,"N") then return("ERROR") parse value scale Length(nbr) with scale . /* 5,6 yields 5 */ parse value prec "0" with prec . /* 2,0 yields 2 */ if scale//2 then nop; else scale = scale + 1 /* make it odd */ if nbr < 0 then do; sign = "D"; nbr = nbr*-1; end else sign = "C" ptpos = Pos(".",nbr) /* 347.23 maybe */ if ptpos = 0 then parse value nbr "." with whol frac . else do /* */ whol = Left(nbr,ptpos-1) /* 347 */ frac = Substr(nbr,ptpos) /* .23 */ end frac = Left(frac,prec+1,0) /* recognize the '.' */ newnbr = Right(whol""Strip(frac,"L","."),scale,0)sign return(x2c(newnbr)) /*@ PACK */ /* Call as: UNPK(nbr,scale,prec) (commas required) 'Nbr' is a packed-decimal number. 'Scale' is the size of the target field, NOT the decimal scale (as in PL/I). 'Prec' is decimal places. Convert to hex. The sign is at the extreme right: C=positive, D=negative. Remaining length is 'scale'. Split 'nbr' into 'whol' and 'frac', trim, set sign. . ----------------------------------------------------------------- */ UNPK: /*@ */ numeric digits 31 parse arg nbr , scale, prec . /* :::: 3 maybe */ parse value prec "0" with prec . /* 3,0 yields 3 */ nbrx = C2X(nbr) /* 0034723D maybe */ parse value scale Length(nbrx)-1 with scale . parse value Reverse(nbrx) with sign 2 revnbrx /* D 3274300 */ if Verify(revnbrx,"0123456789") > 0 then, /* bad string */ return("ERROR") if sign = "D" then factor = -1; else factor = 1 revfrac = Left(revnbrx,prec,0) /* 327 */ nbrx = Reverse(revnbrx) /* 0034723 */ if prec > scale then parse value 0 prec with whol scale; else, whol = Left(nbrx,Length(nbrx)-prec) /* 0034 */ frac = Reverse(revfrac) /* 723 */ nbr = Right((whol"."frac)*factor,scale) /* -34.723 */ return(nbr) /*@ UNPK */