+Lee Stewart Posted January 17, 2018 Share Posted January 17, 2018 (edited) Because this topic has surfaced in several threads on this forum, I decided to give it its own thread and explain in great detail how TI Basic’s RND function and the GPL RAND function it calls 7 – 69 times work. GPL RAND function— RAND takes a one-byte argument (lim) that represents the limit of the pseudorandom number (PRN) that is to be returned to the caller in >8378. RAND first generates a 16-bit PRN from the seed value (16 bits) in >83C0 as follows: PRN = SEED * 28645 + 31417 RAND then stores the PRN thus generated back into >83C0 as the new seed. RAND next adds 1 to the limit value it was passed to use as the modulus to operate on the PRN just generated after its bytes are swapped (now PRN'). The number returned in >8378 = PRN' modulo (lim+1). Here is the code for GPL RAND (coded in TMS9900 Assembler in Console ROM 0: *-------- GENERATE A PSEUDORANDOM NUMBER ---------- * WKSC EQU >83C0 ISR workspace (R0 = PRN SEED) WKSE EQU >83E0 GPL workspace R5LSB EQU WKSE+R5+R5+1 low byte of R5 of GPL WS RANDOM EQU >8378 return location for RAND's PRN return byte RAND LI R4,>6FE5 28645 to R4 MPY @WKSC,R4 SEED * 28645 AI R5,>7AB9 PRN = SEED * 28645 + 31417 MOV R5,@WKSC PRN is stored as new SEED in >83C0 MOVB *R13,R6 load limit number (byte) from caller to R6 SRL R6,8 shift to LSB INC R6 make modulus (lim+1) CLR R4 clear upper half of dividend SWPB R5 swap bytes of PRN to get PRN' DIV R6,R4 perform division by modulus (lim+1) MOVB @R5LSB,@RANDOM store LSB of remainder in >8378 B @NEXT return to caller for next GPL instruction TI Basic RND function— RND takes no arguments and generates a pseudorandom number (PRN) as an 8-byte, radix-100, floating point number (0 <= PRN < 1) and stores it at FAC (>834A). RND calls GPL RAND at least 7 times, once for each radix-100 digit in the significand (7 significant radix-100 digits in mantissa) and as much as 69 times, which is extremely unlikely. RND calls RAND with a limit of 99, which is the highest value possible for a radix-100 digit. The first PRN digit of the significand is in a loop that insures it will not be 0 unless 63 zeros in a row are returned (extremely unlikely), in which case a floating point 0 is returned as the resulting PRN. For each time through the first-digit loop that returns 0, the excess-64 exponent that started at >3F (-1 actual exponent) is decremented by 1 and another PRN is generated. This continues until either a non-zero digit is returned or the excess-64 exponent gets to 0 (-64 actual), in which case RND exits with a floating point 0 in FAC. If a non-zero digit is returned, that becomes the first radix-100 digit of the significand. RND then continues to get the remaining 6 radix-100 digits of the floating point number before returning to the caller. Here is the code for TI Basic RND (coded in GPL in Console GROM 2) from Heiner Martin’s GPL disassembly [Note that, where there are 2 operands, the order is destination,source.]: RND ST @>834A,>3F radix-100 exponent = -1 to FAC ST @>8310,>4B loop counter for significand starting at FAC+1 RND1 RAND >63 get random radix-100 digit to >8378 CZ @>8378 0? BR GROM@RND3 no, keep current exponent and go on DEC @>834A decrement exponent in FAC CZ @>834A 0? BS GROM@RND4 exit with 0 as random number BR GROM@RND1 back to exponent manipulation RND2 RAND >63 get random radix-100 digit to >8378 RND3 ST *>8310,@>8378 all 7 radix-100 digits (FAC+1 to FAC+7) CEQ @>8310,>51 till >8351 (FAC+7) BS GROM@RNDX exit if beyond end of number INC @>8310 increase loop counter BR GROM@RND2 back to get next random digit RND4 CLR @>834B set 0 RNDX CONT return to TI Basic An ALC translation of the above GPL code for the TI Basic RND function follows in the spoiler: Spoiler *==RND from TI Basic=======================================================* * RND is functionally equivalent to TI Basic's GPL RND. RND stores its * * floating point result in FAC as 0 <= FAC < 1. R0 is used to get PRN from * * RAND. Avoid R4,R5,R6, which the called RAND uses. * *==========================================================================* * RND MOV R11,R8 save return LI R7,>003F radix-100 exponent = -1 LI R1,FAC destination RND1 BL @RAND get random radix-100 digit to R0 DATA 99 JNE RND2 keep current exponent and go on DEC R7 decrement exponent JEQ RND5 exit with 0 as random number JMP RND1 back to exponent manipulation RND2 SWPB R7 get exponent to MSB MOVB R7,*R1+ copy exponent to FAC..inc to FAC+1 LI R2,7 counter for 7 radix-100 digits JMP RND4 store first digit RND3 BL @RAND get random radix-100 digit to R0 DATA 99 RND4 MOVB R0,*R1+ store next radix-100 digit DEC R2 done? JNE RND3 no..get next PRN B *R8 yes..return to caller RND5 CLR @FAC set PRN to 0 RNDX B *R8 return to caller *----------------------------------------------------------------- *-- RAND is functionally equivalent to Console ROM 0's ALC for GPL *-- RAND, except that input is via *R11+ instead of *R13 and output *-- is MSB of R0, rather than the byte at RANDOM (>8378). *----------------------------------------------------------------- *------ Generate A Pseudorandom, Centimal Number in R0 MSB ------- *----------------------------------------------------------------- WKSC EQU >83C0 ISR workspace (R0 = PRN SEED) WKSE EQU >83E0 GPL workspace R5LSB EQU WKSE+R5+R5+1 low byte of R5 of GPL WS RAND LI R4,>6FE5 28645 to R4 MPY @WKSC,R4 SEED * 28645 AI R5,>7AB9 PRN = SEED * 28645 + 31417 MOV R5,@WKSC PRN is stored as new SEED in >83C0 MOV *R11+,R6 get maximum byte-value to be returned SB R6,R6 clear MSB, insuring R6 < 256 INC R6 make it a modulus (max+1) CLR R4 clear upper half of dividend SWPB R5 swap bytes of PRN to get PRN' DIV R6,R4 perform division by modulus (lim+1) MOVB @R5LSB,R0 LSB of remainder to MSB of R0 RT Return random centimal digit to caller ...lee Edited May 14 by Lee Stewart Additional Information 8 Quote Link to comment https://forums.atariage.com/topic/274403-rnd-and-rand-pseudorandom-number-generation-by-ti-basic/ Share on other sites More sharing options...
+Vorticon Posted January 17, 2018 Share Posted January 17, 2018 Great explanation Lee! I saved this for future reference. Thanks! 1 Quote Link to comment https://forums.atariage.com/topic/274403-rnd-and-rand-pseudorandom-number-generation-by-ti-basic/#findComment-3937461 Share on other sites More sharing options...
+Lee Stewart Posted May 13 Author Share Posted May 13 To round out this discussion, I added my ALC for TI Basic’s RND function to the first post. It may be a little easier to follow for those unfamiliar with GPL. ...lee 3 Quote Link to comment https://forums.atariage.com/topic/274403-rnd-and-rand-pseudorandom-number-generation-by-ti-basic/#findComment-5465391 Share on other sites More sharing options...
RXB Posted May 13 Share Posted May 13 (edited) TI was having fun with this as hex >63 = 99 Decimal or Integer. And the above listing would never work i.e. BR GROM@RND3 the real GPL code could would be BR RND3 or BR G@RND3 Also the GPL code above is mostly backwards like you would see with GPL disassembly. ST >4B,@>8310 is correct the above listing is wrong and would not work. Edited May 13 by RXB Quote Link to comment https://forums.atariage.com/topic/274403-rnd-and-rand-pseudorandom-number-generation-by-ti-basic/#findComment-5465629 Share on other sites More sharing options...
+Lee Stewart Posted May 14 Author Share Posted May 14 On 5/13/2024 at 12:29 PM, RXB said: Also the GPL code above is mostly backwards like you would see with GPL disassembly. ST >4B,@>8310 is correct the above listing is wrong and would not work. The above GPL does just fine to explain what is going on to the reader. It is Heiner Martin’s disassembly and his comments. I prefaced it with an explanation that, where 2 operands are shown, their order is destination,source. Furthermore, I believe at least one GPL assembler (Reis-Ware), in fact, puts the operands in that order. Even though the use of “GROM” instead of “G” for addresses will not assemble as is (even in Reis-Ware), it does help to make obvious to the GPL incognoscenti that the address is in GROM. At any rate, my principal plan was always to translate it to ALC, which I did 2 days ago and that ALC, indeed, assembles correctly. ...lee 3 Quote Link to comment https://forums.atariage.com/topic/274403-rnd-and-rand-pseudorandom-number-generation-by-ti-basic/#findComment-5466524 Share on other sites More sharing options...
Artoj Posted June 11 Share Posted June 11 Hi All, I am looking through a lot of my own coding from the 80's, I was wondering what the reason I had to chose this memory location and added code for a random number, I hope you guys could enlighten me on the choices I made back in the day. Regards Arto. 1600 SUB R1(Z):: RANDOMIZE :: CALL PEEK(-31880,Z):: Z=INT(Z/2.22)+1 :: SUBEND Quote Link to comment https://forums.atariage.com/topic/274403-rnd-and-rand-pseudorandom-number-generation-by-ti-basic/#findComment-5484168 Share on other sites More sharing options...
+Lee Stewart Posted June 11 Author Share Posted June 11 1 hour ago, Artoj said: Hi All, I am looking through a lot of my own coding from the 80's, I was wondering what the reason I had to chose this memory location and added code for a random number, I hope you guys could enlighten me on the choices I made back in the day. Regards Arto. 1600 SUB R1(Z):: RANDOMIZE :: CALL PEEK(-31880,Z):: Z=INT(Z/2.22)+1 :: SUBEND Well...presuming this is XB, the location -31880 (>8378) is the radix-100 byte returned by the GPL RAND instruction, which is called 4 times by XB’s RANDOMIZE. The value returned by PEEK to Z would be from that fourth call to RAND. Z will have a value from 0 to 99. The result of the calculation will be from 1 to 45. ...lee 4 1 Quote Link to comment https://forums.atariage.com/topic/274403-rnd-and-rand-pseudorandom-number-generation-by-ti-basic/#findComment-5484232 Share on other sites More sharing options...
Artoj Posted June 12 Share Posted June 12 7 hours ago, Lee Stewart said: Well...presuming this is XB, the location -31880 (>8378) is the radix-100 byte returned by the GPL RAND instruction, which is called 4 times by XB’s RANDOMIZE. The value returned by PEEK to Z would be from that fourth call to RAND. Z will have a value from 0 to 99. The result of the calculation will be from 1 to 45. Thanks a heap Lee, That was a clear explanation, this also clarifies my code, I was looking for min/max for the random number choice. I vaguely remember using this after it was commented upon in one of the TI club news letters back in the 80's. Regards Arto. 3 Quote Link to comment https://forums.atariage.com/topic/274403-rnd-and-rand-pseudorandom-number-generation-by-ti-basic/#findComment-5484510 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.