* /* * ------------------------------------------------------------------------------ * readable.c: My random number generator, ISAAC. * (c) Bob Jenkins, March 1996, Public Domain * You may use this code in any way you wish, and it is free. No warrantee. * ------------------------------------------------------------------------------ * */ * #ifndef STANDARD * #include "standard.h" * #endif * * Original can be found at : http://burtleburtle.net/bob/rand/isaacafa.html * * This COBOL implementation is created by Gerald Moull - www.MyDocz.com * * Original C code is commented out with the COBOL equivalent following. * * I believe it is true to ANSI-85 compatibility, or at least should compile in all * COBOL compilers, with the exception of RM/COBOL specific C$ calls for bitwise * operations. These would need adapting for other COBOL dialects. ID Division. Program-ID. ISAAC. Data Division. Working-Storage Section. * /* a ub4 is an unsigned 4-byte quantity */ * * /* external results */ * ub4 randrsl[256], randcnt; * * /* internal state */ * static ub4 mm[256]; * static ub4 aa=0, bb=0, cc=0; 01 RandomData. 03 mmBlock. 05 mm Pic 9(10) Binary(4) Occurs 256. 03 AA Pic 9(10) Binary(4) Value 0. 03 BB Pic 9(10) Binary(4) Value 0. 03 CC Pic 9(10) Binary(4) Value 0. 03 RandRslBlock. 05 RandRsl Pic 9(10) Binary(4) Occurs 256. 03 RandCnt Pic 9(10) Binary(4) Value 0. 03 AAs Pic 9(10) Binary(4). * register ub4 i,x,y; 03 i Pic 9(10) Binary(4) Value 0. 03 x Pic 9(10) Binary(4) Value 0. 03 y Pic 9(10) Binary(4) Value 0. 03 i2 Pic 9(10) Binary(4). 03 i2r Pic 999. 03 i4 Pic 999. 03 ir Pic 999. 03 xs Pic 9(10) Binary(4). 03 ys Pic 9(10) Binary(4). * word i; * ub4 a,b,c,d,e,f,g,h; 03 a Pic 9(10) Binary(4) Value 0. 03 b Pic 9(10) Binary(4) Value 0. 03 c Pic 9(10) Binary(4) Value 0. 03 d Pic 9(10) Binary(4) Value 0. 03 e Pic 9(10) Binary(4) Value 0. 03 f Pic 9(10) Binary(4) Value 0. 03 g Pic 9(10) Binary(4) Value 0. 03 h Pic 9(10) Binary(4) Value 0. * word flag; 03 Flag Pic 9. * ub4 i,j; 03 iMain Pic 9(10) Binary(4) Value 0. 03 jMain Pic 9(10) Binary(4) Value 0. 03 MainDispLine. 05 MainDisp Pic x(8) Occurs 8. 03 MainLines Pic 999. 03 MainPos Pic 999. 03 MainPause Pic x. 03 tMix Pic 9(10) Binary(4). 03 HexValue. 05 HexValueChar Pic x Occurs 4. 03 Hex. 05 HexChar Occurs 4. 07 HexCharH Pic x. 07 HexCharL Pic x. 03 iHex Pic 999. 03 HexWorkX. 05 HexWork9 Pic 999 Binary(1). 03 HexLetters Pic x(16) Value "0123456789abcdef". 03 Redefines HexLetters. 05 HexLetter Pic x Occurs 16. Procedure Division. ***************************************************************** * int main() * { ***************************************************************** main. Display "ISAAC Test". * aa=bb=cc=(ub4)0; Move 0 to aa. Move 0 to bb. Move 0 to cc. * for (i=0; i<256; ++i) mm[i]=randrsl[i]=(ub4)0; Perform Varying iMain From 1 By 1 Until iMain > 256 Move 0 to mm (iMain) Move 0 to RandRsl (iMain) End-Perform. * randinit(TRUE); Move 1 to Flag. Perform randinit. * for (i=0; i<2; ++i) { Move 0 to MainLines. Move 0 to MainPos. Perform Varying iMain From 1 By 1 Until iMain > 2 * isaac(); Perform isaac * for (j=0; j<256; ++j) { Perform Varying jMain From 1 By 1 Until jMain > 256 * printf("%.8lx",randrsl[j]); * if ((j&7)==7) printf("\n"); Move RandRsl (jMain) (1:) to HexValue Perform ToHex Add 1 to MainPos Move Hex to MainDisp (MainPos) If MainPos = 8 Display MainDispLine Move Spaces to MainDispLine Move 0 to MainPos Add 1 to MainLines If MainLines = 20 Display "Press return to continue..." Accept MainPause Col 0 Move 0 to MainLines End-if End-if End-Perform End-Perform. * } } } Display "Press return to continue...". Accept MainPause Col 0. Stop Run. ***************************************************************** * void isaac() { ***************************************************************** isaac. * cc = cc + 1; /* cc just gets incremented once per 256 results */ * bb = bb + cc; /* then combined with bb */ Add 1 to CC. Add CC to BB. * for (i=0; i<256; ++i) Perform Varying i From 1 By 1 Until i > 256 * x = mm[i]; Move mm (i) to x * switch (i%4) { * case 0: aa = aa^(aa<<13); break; * case 1: aa = aa^(aa>>6); break; * case 2: aa = aa^(aa<<2); break; * case 3: aa = aa^(aa>>16); break; } Divide i By 4 giving i4 remainder ir Move AA to AAs Evaluate ir When 1 Call "C$LogicalShiftLeft" Using AAs (1:), 13 When 2 Call "C$LogicalShiftRight" Using AAs (1:), 6 When 3 Call "C$LogicalShiftLeft" Using AAs (1:), 2 When 0 Call "C$LogicalShiftRight" Using AAs (1:), 16 End-Evaluate Call "C$LogicalXor" Using AA (1:), AAs (1:) * aa = mm[(i+128)%256] + aa; Add 128, i giving i2 Divide i2 By 256 giving i2 Remainder i2r If i2r = 0 Move 256 to i2r End-if Add mm (i2r) to AA * mm[i] = y = mm[(x>>2)%256] + aa + bb; Move x to xs Call "C$LogicalShiftRight" Using xs (1:), 2 Add 1 to xs Divide xs By 256 giving i2 Remainder i2r If i2r = 0 Move 256 to i2r End-if Compute y = mm (i2r) + AA + BB Move y to mm (i) * randrsl[i] = bb = mm[(y>>10)%256] + x; Move y to ys Call "C$LogicalShiftRight" Using ys (1:), 10 Add 1 to ys Divide ys By 256 giving i2 Remainder i2r If i2r = 0 Move 256 to i2r End-if Compute BB = mm (i2r) + x Move BB to RandRsl (i) End-Perform. * /* Note that bits 2..9 are chosen from x but 10..17 are chosen * from y. The only important thing here is that 2..9 and 10..17 * don't overlap. 2..9 and 10..17 were then chosen for speed in * the optimized version (rand.c) */ * /* See http://burtleburtle.net/bob/rand/isaac.html * for further explanations and analysis. */ * } ***************************************************************** * /* if (flag==TRUE), then use the contents of randrsl[] to initialize mm[]. */ * * void randinit(flag) * word flag; * { ***************************************************************** randinit. * aa=bb=cc=0; * a=b=c=d=e=f=g=h=0x9e3779b9; /* the golden ratio */ Move 0 to AA. Move 0 to BB. Move 0 to CC. Move x"9e3779b9" to a (1:). Move a to b. Move a to c. Move a to d. Move a to e. Move a to f. Move a to g. Move a to h. * for (i=0; i<4; ++i) /* scramble it */ * { * mix(a,b,c,d,e,f,g,h); * } Perform mix 4 Times. * for (i=0; i<256; i+=8) /* fill in mm[] with messy stuff */ * { Perform Varying i From 1 By 8 Until i > 256 * if (flag) /* use all the information in the seed */ * { * a+=randrsl[i ]; b+=randrsl[i+1]; c+=randrsl[i+2]; d+=randrsl[i+3]; * e+=randrsl[i+4]; f+=randrsl[i+5]; g+=randrsl[i+6]; h+=randrsl[i+7]; * } If Flag = 1 Move i to i2 Add RandRsl (i2) to a Add 1 to i2 Add RandRsl (i2) to b Add 1 to i2 Add RandRsl (i2) to c Add 1 to i2 Add RandRsl (i2) to d Add 1 to i2 Add RandRsl (i2) to e Add 1 to i2 Add RandRsl (i2) to f Add 1 to i2 Add RandRsl (i2) to g Add 1 to i2 Add RandRsl (i2) to h End-if * mix(a,b,c,d,e,f,g,h); Perform mix * mm[i ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d; * mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h; Move i to i2 Move a to mm (i2) Add 1 to i2 Move b to mm (i2) Add 1 to i2 Move c to mm (i2) Add 1 to i2 Move d to mm (i2) Add 1 to i2 Move e to mm (i2) Add 1 to i2 Move f to mm (i2) Add 1 to i2 Move g to mm (i2) Add 1 to i2 Move h to mm (i2) End-Perform. * if (flag) * { /* do a second pass to make all of the seed affect all of mm */ If Flag = 1 * for (i=0; i<256; i+=8) { Perform Varying i From 1 By 8 Until i > 256 * a+=mm[i ]; b+=mm[i+1]; c+=mm[i+2]; d+=mm[i+3]; * e+=mm[i+4]; f+=mm[i+5]; g+=mm[i+6]; h+=mm[i+7]; Move i to i2 Add mm (i2) to a Add 1 to i2 Add mm (i2) to b Add 1 to i2 Add mm (i2) to c Add 1 to i2 Add mm (i2) to d Add 1 to i2 Add mm (i2) to e Add 1 to i2 Add mm (i2) to f Add 1 to i2 Add mm (i2) to g Add 1 to i2 Add mm (i2) to h * mix(a,b,c,d,e,f,g,h); Perform mix * mm[i ]=a; mm[i+1]=b; mm[i+2]=c; mm[i+3]=d; * mm[i+4]=e; mm[i+5]=f; mm[i+6]=g; mm[i+7]=h; Move i to i2 Move a to mm (i2) Add 1 to i2 Move b to mm (i2) Add 1 to i2 Move c to mm (i2) Add 1 to i2 Move d to mm (i2) Add 1 to i2 Move e to mm (i2) Add 1 to i2 Move f to mm (i2) Add 1 to i2 Move g to mm (i2) Add 1 to i2 Move h to mm (i2) End-Perform End-if. * } * } * isaac(); /* fill in the first set of results */ * randcnt=256; /* prepare to use the first set of results */ Perform ISAAC. Move 256 to randcnt. ***************************************************************** * #define mix(a,b,c,d,e,f,g,h) \ * * { \ ***************************************************************** mix. * a^=b<<11; d+=a; b+=c; \ Move b to tMix. Call "C$LogicalShiftLeft" Using tMix (1:), 11. Call "C$LogicalXor" Using a (1:), tMix (1:). Add a to d. Add c to b. * b^=c>>2; e+=b; c+=d; \ Move c to tMix. Call "C$LogicalShiftRight" Using tMix (1:), 2. Call "C$LogicalXor" Using b (1:), tMix (1:). Add b to e. Add d to c. * c^=d<<8; f+=c; d+=e; \ Move d to tMix. Call "C$LogicalShiftLeft" Using tMix (1:), 8. Call "C$LogicalXor" Using c (1:), tMix (1:). Add c to f. Add e to d. * d^=e>>16; g+=d; e+=f; \ Move e to tMix. Call "C$LogicalShiftRight" Using tMix (1:), 16. Call "C$LogicalXor" Using d (1:), tMix (1:). Add d to g. Add f to e. * e^=f<<10; h+=e; f+=g; \ Move f to tMix. Call "C$LogicalShiftLeft" Using tMix (1:), 10. Call "C$LogicalXor" Using e (1:), tMix (1:). Add e to h. Add g to f. * f^=g>>4; a+=f; g+=h; \ Move g to tMix. Call "C$LogicalShiftRight" Using tMix (1:), 4. Call "C$LogicalXor" Using f (1:), tMix (1:). Add f to a. Add h to g. * g^=h<<8; b+=g; h+=a; \ Move h to tMix. Call "C$LogicalShiftLeft" Using tMix (1:), 8. Call "C$LogicalXor" Using g (1:), tMix (1:). Add g to b. Add a to h. * h^=a>>9; c+=h; a+=b; \ Move a to tMix. Call "C$LogicalShiftRight" Using tMix (1:), 9. Call "C$LogicalXor" Using h (1:), tMix (1:). Add h to c. Add b to a. * } ToHex. Perform Varying iHex From 1 By 1 Until iHex > 4 Move HexValueChar (iHex) to HexWorkX Call "C$LogicalShiftRight" Using HexWorkX, 4 Add 1 to HexWork9 Move HexLetter (HexWork9) to HexCharH (iHex) Move HexValueChar (iHex) to HexWorkX Call "C$LogicalAnd" Using HexWorkX, x"0F" Add 1 to HexWork9 Move HexLetter (HexWork9) to HexCharL (iHex) End-Perform.