Page 1 of 2

Perform calculation with great number

PostPosted: Fri Apr 29, 2011 9:00 pm
by sensuixel
Hello,

I'm currently working on a progam which calculate VSAM file size using IGGCSI then TRKCALC.

I, first, retrieve H-A-RBA and BLOCKSIZE from IGGCSI then I use TRKCALC to calculate the number of Block per track.
Then I do H-A-RBA / (BLOCKSIZE * NUMBER OF BLOCK per track) to get the track allocation of my file.

Unfortunately, on "great" file I get incorrect result, here is an example :

- I have a VSAM File with H-A-RBA = 3,510,190,080 wich i get as X'D1394000'
- Blocksize = 4096 as X'1000'
- I get 12 as number of block per track after TRKCALC (UTYPE = 3390)

I first try to display the H-A-RBA using CVD and ED and I get 784,777,216 (which is wrong), so the rest of my calculation goes wrong.

Here after is a portion of my code.

*
L     2,EHARBA                 
CVD   2,DEC_RBA             
*     
MVC   OUTPUT+45(18),PATTERN1   
ED    OUTPUT+45(18),DEC_RBA+1
PUT   PUTDCB,OUTPUT           
**
EHARBA   DS    XL4  * got from IGGSI result

DEC_RBA   DS   PL8
PATTERN1  DC   XL18'40206B2020206B2020206B2020206B202120'

Re: Perform calculation with great number

PostPosted: Fri Apr 29, 2011 9:57 pm
by Robert Sample
CVD assumes signed binary data -- which will give you problems if you are dealing with numbers that set the first bit (such as X'D1394000'). Either use CVDG or do all your arithmetic in packed decimal fields.

Re: Perform calculation with great number

PostPosted: Fri Apr 29, 2011 11:08 pm
by steve-myers
As Mr. Sample says, the largest number CVD can handle is 2,147,483,647 (X'7FFFFFFF'); your number is larger. You can do your arithmetic in 64-bit registers and use CVDG to perform the conversion from binary to packed decimal, or use packed decimal arithmetic only. You're not the first person to have trouble with the limited range of 32-bit binary numbers; it's something we have to keep in our minds ar all times.

Re: Perform calculation with great number

PostPosted: Sat Apr 30, 2011 6:28 am
by steve-myers
Actually, I suspect the main problem is the high allocated RBA is greater than 2147483647. Use CVBG to convert from packed decimal to get a 64-bit binary value, divide by your estimate of bytes / track, and you should have a 32-bit number that CVD can easily handle.

Re: Perform calculation with great number

PostPosted: Sat Apr 30, 2011 9:23 am
by steve-myers
I was just looking at IGGCSI00 documentation. Now it as been more than 10 years since I've used it, so I don't have any current knowledge, but the documentation says high allocated RBA is a 4 byte (32-bit) value. Given that, I'm not sure where you'd be getting into trouble.

Re: Perform calculation with great number

PostPosted: Sat Apr 30, 2011 6:31 pm
by Robert Sample
VSAM files now support extended mode -- which allows a single VSAM file to be more than 4 GB -- so the 32-bit high allocated RBA is modified to allow for this. I don't know the details but I'm sure they are not hard to find.

Re: Perform calculation with great number

PostPosted: Sat Apr 30, 2011 10:40 pm
by steve-myers
Translating X'D1394000' to its correct decimal value you get -784,777,216. Since your edit mask did not have any provision for negative values, the result is correct.

I have to assume X'D1394000' is what IGGCSI00 returned. I can't guess what it would return if the high allocated RBA is greater than 4 gig. This code will work correctly because the intger divide instruction uses a true 64-bit number in registers 0 and 1. The A(12*4096) is the bytes per track for a "blksize" of 4096 bytes as 12 records / track.
SR    0,0         
L     1,RBAVAL     
D     0,=A(12*4096)
LTR   0,0         
BZ    *+L'*+4     
A     1,=F'1'     

The test after the divide is to test the remainder from the divide; if the remainder is non-zero you have to add 1 track to the total tracks. The L'* in the branch instruction is the length of the instruction; this is just a "trick" to not execute the A instruction.

Re: Perform calculation with great number

PostPosted: Mon May 02, 2011 1:54 am
by steve-myers
Just for an experiment, I decided to test CVDG. I had no doubt that was the correct solution, but ... In any event, I wrote this little program
CVDG     CSECT
         USING *,15
         STM   14,12,12(13)
         LG    0,=X'00000000D1394000'
         CVDG  0,DECIMAL
         ED    DISPLAY,DECIMAL
         LA    0,L'DISPLAY
         LA    1,DISPLAY
         TPUT  (1),(0),R
         LM    14,12,12(13)
         SR    15,15
         BR    14
         DC    0D'0'
         LTORG ,
DECIMAL  DC    PL16'0'
DISPLAY  DC    0C' N,NNN,NNN,NNN,NNN,NNN,NNN,NNN,NNN,NNN,NNN'
         DC    C' ',X'20'
         DC    C',',X'202020'
         DC    C',',X'202020'
         DC    C',',X'202020'
         DC    C',',X'202020'
         DC    C',',X'202020'
         DC    C',',X'202020'
         DC    C',',X'202020'
         DC    C',',X'202020'
         DC    C',',X'202020'
         DC    C',',X'202120'
         DC    0D'0'
         END   CVDG

Before I started I got out my trusty Principles of Operation and looked up CVDG. I was not certain if the output area for CVDG was 16 bytes or something else since it has been many years since I used it. I built the output area for the ED instruction like this: First I constructed a picture of the basic edit mask -
DISPLAY  DC    0C' NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN'
Since the output area for CVDG contains 16 bytes I knew there would have to be 31 digit select bytes, so I very carefully built 31 N characters.Then I very carefully inserted the commas. This took several tries.
DISPLAY  DC    0C' N,NNN,NNN,NNN,NNN,NNN,NNN,NNN,NNN,NNN,NNN'
Now this is not the actual edit mask; it is just a picture of the edit mask. With a reliable (I hope!) picture I constructed the actual edit mask. First:
         DC    C' ',X'20'
         DC    C',',X'202020'
Then I repeated the last line 9 times, and changed the last X'202020' to X'202120' to complete the edit mask.

Building the edit mask like this means I don't have to memorize the hexadecimal codes for the comma and blank characters, and I don't have to build an extremely long string of hexadecimal digits. I just have to depend on the assembler to insert the correct values into the object code.

With a completed program I assembled, linked, and ran the program. It produced 3,510,190,080 and a lot of leading blanks. I'm certain that sensuixel will verify the output value is correct!

Re: Perform calculation with great number

PostPosted: Tue May 03, 2011 1:06 am
by sensuixel
Sorry for the delay, i took a break during this week-end ;)

Thanks to both of you and I confirm that 3,510,190,080 is the correct output.

I agree with you on the cause of my issue (HI-RBA > 2147483647), so I'll have to take a good look at CVDG to get rid
of this error.

Re: Perform calculation with great number

PostPosted: Tue May 03, 2011 8:54 pm
by sensuixel
steve-myers wrote:Translating X'D1394000' to its correct decimal value you get -784,777,216. Since your edit mask did not have any provision for negative values, the result is correct.

I have to assume X'D1394000' is what IGGCSI00 returned. I can't guess what it would return if the high allocated RBA is greater than 4 gig. This code will work correctly because the intger divide instruction uses a true 64-bit number in registers 0 and 1. The A(12*4096) is the bytes per track for a "blksize" of 4096 bytes as 12 records / track.
SR    0,0         
L     1,RBAVAL     
D     0,=A(12*4096)
LTR   0,0         
BZ    *+L'*+4     
A     1,=F'1'     

The test after the divide is to test the remainder from the divide; if the remainder is non-zero you have to add 1 track to the total tracks. The L'* in the branch instruction is the length of the instruction; this is just a "trick" to not execute the A instruction.


I made a lot of tries today, i tried using CVDG and i'm now able to display the RBA properly, thank you Steve.

I still have issue when perform the division of my HA-RBA, i get a wrong result.

          L         R6,=X'D1394000'      => 3,510,190,080 got via IGGCSI00
          SRDA     R6,32               
          D         R6,=A(12*4096)     
          LTR     R6,R6               
          BZ       *+L'*+4             
          A         R7,=F'1'           
          ST       R7,ARG2             
          PUT     APIFILE,ARG2       


I get X'FFFFC1A3' as a result which is wrong, but when the HA-RBA is smaller I get a correct result.

I'm now looking at DIVIDE LOGICAL in Principles of Operation, since the DIVIDEND is treated as 64 bits or 128 bits unsigned binary, when DIVIDE treats it as signed BINARY.
I think (may be i'm wrong) that the cause of my issue is the signed/unsigned.