Path: news.weeg.uiowa.edu!news.uiowa.edu!hobbes.physics.uiowa.edu!math.ohio-state.edu!howland.reston.ans.net!gatech!news-feed-1.peachnet.edu!paperboy.wellfleet.com!noc.near.net!news.delphi.com!usenet
From: John Holmes
Newsgroups: comp.sys.apple2.programmer
Subject: Re: Algorithms anyone?
Date: Sun, 8 May 94 09:33:22 -0500
Organization: Delphi (info@delphi.com email, 800-695-4005 voice)
Lines: 169
Message-ID:
References: <2po99i$c8u@news.ysu.edu>
NNTP-Posting-Host: bos1d.delphi.com
X-To: Eric S. Ford
I have a chunk of source for random numbers that follows..hoope it is of some
help to you.
********************************
* *
* USRND *
* *
* by *
* Tom Hare, John Russ, Gary *
* Faulkner, and David Sparks *
* *
* A random-number generator *
* for 48k ROM or L/C Applesoft *
* *
* Call-A.P.P.L.E. : Jan. 1983 *
* *
********************************
*
*
* The following machine language program is
* relocatable, but is shown here assembled
* to reside at $300. It is "hooked" into the
* Applesoft USR function when it is BRUN.
* The calling format is (e.g.) X = USR (A).
* If A is 1 the value will be a real number
* between 0 and 1 (the usual form for random
* numbers). If A is a positive number greater
* than 1, an integer 0...(A-1) is returned.
* Arguments between 0 and 1 always return 0, and
* arguments < 0 are rejected (error message).
* RND (0) returns the previous value.
*
* The alogrithm for the random number generator
* starts with a seed value S and upon each
* call calculates a new seed value
* S' = (8192 * S) MOD 67099547.
* Each random number is taken as the seed
* value divided by 67099547. This method
* will pass even quite exacting tests for
* "Randomness", and is strongly recommended
* as an alternative to the Applesoft RND function.
* The original alogrithm, which is used in some
* large computer programs, was introduced to
* us by Gary Faulkner, Dept. of Physical and
* Mathematical Sciences, North Carolina State
* University. It was first programmed in BASIC
* and subsequently in machine language by Tom
* Hare, School of Engineering, NCSU. His program
* was refined further by John Russ (Engineering
* Research, NCSU) and David Sparks (Call-A.P.P.L.E.
* staff writer). The accompanying article describes
* the method and several tests of this and other
* random number generators.
*
ORG $2F4 ;A convenient location
*
LDA #$4C ;"JMP"
STA $0A ;The USR vector
LDA #RANDOM ;Hi byte too
STA $0C
LDY #4 ;Use the 4 bytes from
INITR LDA $C9,Y ;Applesoft's RND seed
AND MASK-1,Y ;to create our seed
STA BYT1-1,Y ;(which may not exceed
DEY ;the magic 67099547)
* NOTE: this means that the random number
* generator can be seeded by RND (-N) and CALL 768
BNE INITR
RTS
*
RANDOM LDA $9D ;check for 0
BEQ DIVIDE ;return last one
LDA $A2 ;check positive
BPL SAVE
JMP $E199 ;"ILLEGAL QUANTITY"
*
SAVE LDY #>RANGE ;save the argument
LDX #mem. subr.
LDX #$F3 ;-13 into counter
SUBLOOP ASL BYT1 ;shift the seed 13
ROL BYT2 ;times to multiply
ROL BYT3 ;by 8192
ROL BYT4
SEC ;and try to subtract
LDA BYT1 ;67099547 to perform
SBC #155 ;the MOD function
PHA ;NOTE- the values
LDA BYT2 ;shown are the floating
SBC #219 ;point representation
PHA ;of the number. The
LDA BYT3 ;difference is saved
SBC #255 ;on the stack for now
PHA
LDA BYT4
SBC #3
PHA
BCC LESS ;branch if < 67099547
PLA ;otherwise replace
STA BYT4 ;the seed value
PLA ;with the MOD result
STA BYT3 ;which we cleverly
PLA ;saved on the stack
STA BYT2 ;while testing
PLA
STA BYT1
BCS INCR ;forced branch
LESS PLA ;gotta clean up
PLA ;the stack!
PLA
PLA
INCR INX ;increment counter
BNE SUBLOOP ;and keep shifting
DIVIDE LDA #3 ;place 67099547
STA $9E ;into FAC
LDA #255
STA $9F
LDA #219
STA $A0
LDA #155
STA $A1
LDA #0
STA $A2
STA $AA
STA $AB
LDA #$81
STA $A5
STA $9D
LDA BYT4 ;and move seed value
STA $A6 ;to auxiliary FAC
LDA BYT3 ;before multiplying
STA $A7
LDA BYT2
STA $A8
LDA BYT1
STA $A9
LDA #$9D
JSR $E82E ;Normalize FAC
JSR $EA69 ;Divide AUX/FAC
* These Applesoft calls leave the random number
* in the floating point accumulator (FAC)
LDA RANGE ;now check the user's
SEC ;RANGE argument
SBC #$81 ;is it a 1 (exactly)
ORA RANGE+1
ORA RANGE+2
ORA RANGE+3
BNE SCALE ;NO
RTS ;YES (return with fraction)
SCALE LDY #>RANGE ;load address to use
LDA #