Jump to content
IGNORED

RND and RAND: Pseudorandom Number Generation by TI Basic


Lee Stewart

Recommended Posts

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 by Lee Stewart
Additional Information
  • Like 8
Link to comment
Share on other sites

  • 6 years later...
Posted (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 by RXB
Link to comment
Share on other sites

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

  • Like 3
Link to comment
Share on other sites

  • 4 weeks later...

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

Link to comment
Share on other sites

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

  • Like 3
  • Thanks 1
Link to comment
Share on other sites

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. 

  • Like 3
Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...