Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.sys.apple2.programmer > #2386 > unrolled thread
| Started by | gids.rs@sasktel.net |
|---|---|
| First post | 2016-02-28 21:02 -0800 |
| Last post | 2018-10-01 07:27 -0700 |
| Articles | 20 on this page of 45 — 16 participants |
Back to article view | Back to comp.sys.apple2.programmer
Streamlining Applesoft - Random number generators gids.rs@sasktel.net - 2016-02-28 21:02 -0800
Re: Streamlining Applesoft - Random number generators qkumba <peter.ferrie@gmail.com> - 2016-02-29 09:05 -0800
Re: Streamlining Applesoft - Random number generators wssimms@gmail.com - 2016-02-29 09:07 -0800
Re: Streamlining Applesoft - Random number generators Michael Pohoreski <michael.pohoreski@gmail.com> - 2016-02-29 12:57 -0800
Re: Streamlining Applesoft - Random number generators "Michael J. Mahon" <mjmahon@aol.com> - 2016-02-29 17:50 -0800
Re: Streamlining Applesoft - Random number generators Michael Barry <barrym95838@yahoo.com> - 2016-02-29 17:44 -0800
Re: Streamlining Applesoft - Random number generators gids.rs@sasktel.net - 2016-02-29 18:38 -0800
Re: Streamlining Applesoft - Random number generators "Michael J. Mahon" <mjmahon@aol.com> - 2016-02-29 18:46 -0800
Re: Streamlining Applesoft - Random number generators wssimms@gmail.com - 2016-02-29 18:53 -0800
Re: Streamlining Applesoft - Random number generators Michael Barry <barrym95838@yahoo.com> - 2016-03-01 00:11 -0800
Re: Streamlining Applesoft - Random number generators wssimms@gmail.com - 2016-03-01 05:17 -0800
Re: Streamlining Applesoft - Random number generators Michael J. Mahon <mjmahon@aol.com> - 2016-03-01 10:38 -0600
Re: Streamlining Applesoft - Random number generators qkumba <peter.ferrie@gmail.com> - 2016-03-01 11:56 -0800
Re: Streamlining Applesoft - Random number generators Michael Pohoreski <michael.pohoreski@gmail.com> - 2016-03-01 12:13 -0800
Re: Streamlining Applesoft - Random number generators Michael J. Mahon <mjmahon@aol.com> - 2016-03-01 15:32 -0600
Re: Streamlining Applesoft - Random number generators qkumba <peter.ferrie@gmail.com> - 2016-03-01 22:47 -0800
Re: Streamlining Applesoft - Random number generators Michael J. Mahon <mjmahon@aol.com> - 2016-03-01 17:28 -0600
Re: Streamlining Applesoft - Random number generators Michael Pohoreski <michael.pohoreski@gmail.com> - 2016-03-01 18:50 -0800
Re: Streamlining Applesoft - Random number generators "Michael J. Mahon" <mjmahon@aol.com> - 2016-03-01 19:25 -0800
Re: Streamlining Applesoft - Random number generators gids.rs@sasktel.net - 2016-03-01 22:03 -0800
Re: Streamlining Applesoft - Random number generators "Michael J. Mahon" <mjmahon@aol.com> - 2016-03-02 20:49 -0800
Re: Streamlining Applesoft - Random number generators "Michael J. Mahon" <mjmahon@aol.com> - 2016-03-03 14:48 -0800
Re: Streamlining Applesoft - Random number generators "Michael J. Mahon" <mjmahon@aol.com> - 2016-03-01 20:02 -0800
Re: Streamlining Applesoft - Random number generators Michael Pohoreski <michael.pohoreski@gmail.com> - 2016-03-03 07:48 -0800
Re: Streamlining Applesoft - Random number generators gids.rs@sasktel.net - 2016-03-03 08:05 -0800
Re: Streamlining Applesoft - Random number generators Michael Pohoreski <michael.pohoreski@gmail.com> - 2016-03-03 09:24 -0800
Re: Streamlining Applesoft - Random number generators Michael J. Mahon <mjmahon@aol.com> - 2016-03-03 22:51 -0600
Re: Streamlining Applesoft - Random number generators gids.rs@sasktel.net - 2016-03-03 21:34 -0800
Re: Streamlining Applesoft - Random number generators Michael J. Mahon <mjmahon@aol.com> - 2016-03-04 00:50 -0600
Re: Streamlining Applesoft - Random number generators Scott Hemphill <hemphill@hemphills.net> - 2016-03-04 10:47 -0500
Re: Streamlining Applesoft - Random number generators qkumba <peter.ferrie@gmail.com> - 2018-09-05 20:41 -0700
Re: Streamlining Applesoft - Random number generators Antoine Vignau <antoine.vignau@laposte.net> - 2018-09-06 09:13 -0700
Re: Streamlining Applesoft - Random number generators qkumba <peter.ferrie@gmail.com> - 2018-09-06 10:33 -0700
Re: Streamlining Applesoft - Random number generators Michael J. Mahon <mjmahon@aol.com> - 2018-09-06 17:58 -0500
Re: Streamlining Applesoft - Random number generators John Brooks <jbrooks@blueshiftinc.com> - 2018-09-06 22:26 -0700
Re: Streamlining Applesoft - Random number generators John Brooks <jbrooks@blueshiftinc.com> - 2018-09-07 18:08 -0700
Re: Streamlining Applesoft - Random number generators John Brooks <jbrooks@blueshiftinc.com> - 2018-09-07 18:11 -0700
Re: Streamlining Applesoft - Random number generators the.ertceps@gmail.com - 2018-09-29 05:03 -0700
Re: Streamlining Applesoft - Random number generators James Davis <JPD.Enterprises@outlook.com> - 2018-09-29 10:24 -0700
Re: Streamlining Applesoft - Random number generators Marco Verpelli <mverpelli@libero.it> - 2018-09-29 10:30 -0700
Re: Streamlining Applesoft - Random number generators Brian Patrie <bpatrie@bellsouth.spamisicky.net> - 2018-09-29 12:36 -0500
Re: Streamlining Applesoft - Random number generators Michael J. Mahon <mjmahon@aol.com> - 2018-09-29 12:41 -0500
Re: Streamlining Applesoft - Random number generators Andy McFadden <thefadden@gmail.com> - 2018-09-29 21:06 -0700
Re: Streamlining Applesoft - Random number generators James Davis <JPD.Enterprises@outlook.com> - 2018-09-30 19:28 -0700
Re: Streamlining Applesoft - Random number generators "Frank M." <frank_o_rama@hotmail.com> - 2018-10-01 07:27 -0700
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
| From | "Michael J. Mahon" <mjmahon@aol.com> |
|---|---|
| Date | 2016-03-02 20:49 -0800 |
| Message-ID | <w6WdnZOov-7eX0rLnZ2dnUU7-XXNnZ2d@giganews.com> |
| In reply to | #2417 |
On 3/1/2016 10:03 PM, gids.rs@sasktel.net wrote: > On Tuesday, March 1, 2016 at 9:24:53 PM UTC-6, mjm...@aol.com wrote: >> On 3/1/2016 6:50 PM, Michael Pohoreski wrote: >>> On Tuesday, March 1, 2016 at 3:28:19 PM UTC-8, mjm...@aol.com wrote: >>>> I couldn't help it--I just had to determine the period of Applesoft's RND >>>> function... ;-) >>> >>> That's OK, you're in good company -- obsessed ^H^H^H inquiring minds want to know. :-) >>> >>>> From a cold start without seeding, it cycles after 37758 calls. (Since >>>> Applesoft doesn't fully initialize the seed, >>> >>> You wouldn't happen to remember where Applesoft inits RNDSEED ? >>> I had found it and lost it again. :-/ >>> >>>> this may vary depending on the >>>> prior content of page zero.) >>> >>> Is 37758 the max period ? >>> >>> Hmm, I guess the F800 ROM random bytes (RNDL = $4E, RNDH = $4F) are never used. >>> >>> Hmm, looking over the disassembly I see RNDSEED is a 5 byte floating-point, using a simple linear congruential generator: >>> >>> C9- RNDSEED .EQ $C9 - CD >>> >>> EFA6- 98 35 44 >>> EFA9- 7A CON.RND.1 .HS 9835447A <<< THESE ARE MISSING ONE BYTE >>> >>> EFAA- 68 28 B1 >>> EFAD- 46 CON.RND.2 .HS 6828B146 <<< FOR FP VALUES >>> >>> *-------------------------------- >>> * "RND" FUNCTION >>> *-------------------------------- >>> EFAE- 20 82 EB RND JSR SIGN REDUCE ARGUMENT TO -1, 0, OR +1 >>> EFB1- AA TAX SAVE ARGUMENT >>> EFB2- 30 18 BMI .1 = -1, USE CURRENT ARGUMENT FOR SEED >>> EFB4- A9 C9 LDA #RNDSEED USE CURRENT SEED >>> EFB6- A0 00 LDY /RNDSEED >>> EFB8- 20 F9 EA JSR LOAD.FAC.FROM.YA >>> EFBB- 8A TXA RECALL SIGN OF ARGUMENT >>> EFBC- F0 E7 BEQ RTS.19 =0, RETURN SEED UNCHANGED >>> EFBE- A9 A6 LDA #CON.RND.1 VERY POOR RND ALGORITHM >>> EFC0- A0 EF LDY /CON.RND.1 >>> EFC2- 20 7F E9 JSR FMULT >>> EFC5- A9 AA LDA #CON.RND.2 ALSO, CONSTANTS ARE TRUNCATED >>> EFC7- A0 EF LDY /CON.RND.2 <<<THIS DOES NOTHING, DUE TO >>> >>> * <<<SMALL EXPONENT >>> >>> EFC9- 20 BE E7 JSR FADD >>> EFCC- A6 A1 .1 LDX FAC+4 SHUFFLE HI AND LO BYTES >>> EFCE- A5 9E LDA FAC+1 TO SUPPOSEDLY MAKE IT MORE RANDOM >>> EFD0- 85 A1 STA FAC+4 >>> EFD2- 86 9E STX FAC+1 >>> EFD4- A9 00 LDA #0 MAKE IT POSITIVE >>> EFD6- 85 A2 STA FAC.SIGN >>> EFD8- A5 9D LDA FAC A SOMEWHAT RANDOM EXTENSION >>> EFDA- 85 AC STA FAC.EXTENSION >>> EFDC- A9 80 LDA #$80 EXPONENT TO MAKE VALUE < 1.0 >>> EFDE- 85 9D STA FAC >>> EFE0- 20 2E E8 JSR NORMALIZE.FAC.2 >>> EFE3- A2 C9 LDX #RNDSEED MOVE FAC TO RND SEED >>> EFE5- A0 00 LDY /RNDSEED >>> EFE7- 4C 2B EB GO.MOVMF JMP STORE.FAC.AT.YX.ROUNDED >>> >>> Did I get CON.RND.1 and CON.RND.2 right? >>> >>> ; CON.RND.1 EQU $EFA6; 11879546.4 >>> ; CON.RND.2 EQU $EFAA; 3.92767778E-08 >>> >>> 300: LDA #$A6 >>> LDY #$EF >>> JSR $EAF9 ; LOAD.FAC.YA >>> JSR $ED34 ; FOUT >>> JSR $E3E7 ; STRLIT >>> JMP $DACD ; STRPRT >>> LDA #AA >>> BNE $302 >>> >>> >>>> Seeded with RND(-2.71828), it cycles after 37758 calls (same cycle). >>> >>> I guess with a period of ~32K for an 8-bit CPU it isn't going to win any "good" distributions anytime soon. :-/ >>> >>>> Seeded with RND(-3.14159), it cycles after only 202 calls! >>>> This is a seriously broken PRNG! >>> >>> WOW -- that is horrible!! Especially for a 5 byte seed! >>> >>> So this is a legitimate case of where we can blame Bill Gates? :-) >>> >>>> If we take 37758 as the typical cycle, and we take two RNDs per attempted >>>> pixel set, there will be only 18879 different pairs of coordinates, so the >>>> 53760 pixel HGR screen will stay mostly black. >>>> If the cycle were an odd length, then as many as 37758 pixels might be set. >>> >>> Mind posting your test program per chance please? :-) >>> >>> >>> Great investigation BTW ! >> >> Thanks, but it's pretty trivial--it's fun to answer a question in a few >> minutes at the keyboard. ;-) >> >> Here's the program: >> >> 100 REM RND Cycle Length Test >> 110 REM MJM - 03/01/16 >> 120 : >> 130 REM Empirical RND cycle is 37758 from cold start. >> 140 REM 37758 from seed with -2.71828 >> 150 REM 202 from seed with -3.14159 >> 190 REM 200 not needed; RND cycles from the start. >> 200 REM FOR I = 1 TO 37758:X = RND (1): NEXT : REM Get into cycle >> 205 X = RND (1) >> 210 : >> 220 FOR I = 1 TO 100000:Y = RND (1): IF X = Y GOTO 300 >> 230 NEXT >> 290 : >> 300 PRINT "RND cycle is "I" long." >> >> Note that since RND has only it's seed/previous result for state, once >> it is seeded you are already in whatever cycle there will be, so no >> initial cycling is needed (which is why line 200 is commented out). >> >> Contrast this with the shift register PRNG I posted earlier in this >> thread, which has 32 bytes of internal state, holding eight parallel >> 32-bit shift registers with a period of 2^32-1. >> -- >> >> -michael >> > > > Uhm! Your test seems to fail, Michael. If you poked the last byte into the seed from the prompt, it seems to run forever, but then try the test plot program. The plotting still stops about the same time without the full 5 byte seedrun. > > > 10 POKE 205,88:X=RND(1) > 20 FOR I=1 TO 10000000:Y=RND(1):ONX=YGOTO100 > 30 NEXT > 100 ? I" random numbers" > > > 5 KB=49152: POKE 205,88 > 10 HGR : HCOLOR= 3: POKE 49234,0 > 20 X = RND (1) * 280:Y = RND (1) * 192:I=I+2 > 30 HPLOT X,Y: ON PEEK (KB) < 128 GOTO 20 > > > After a few tests, I came to the determination that the applesoft code is not so much at fault as it is just a bad seed. Even with the 5th byte. > > Try this seed that I came up with and try applesoft again. Also instead of rebooting your computer each time, you can just poke in the original seed to get the same result. > > Here is a new test. > Type HGR:RUN the first time, then RUN5 the second time. Notice that line #30 never takes. How full is the hi-res screen now? Also line #50 can be used to keep track of a good seed that can be either saved to disk and re-entered later. > > > 2 POKE 201,128: POKE 202,79: POKE 203,199: POKE 204,82: POKE 205,88 > 3 GOTO 10 > 5 POKE 205,88: J=1 :Z1 = RND(1):Z2=RND(2) > 10 KB=49152: POKE 49232,0: HCOLOR=3: POKE 49234,0 > 20 X=RND(1)*280: Y=RND(1)*192 > 25 I=I+2:IF J=0 THEN IF I>57232 THEN ?CHR$(7):GOTO 50 > 30 IF X=Z1 OR X=Z2 THEN 50 > 35 IF J=1 THEN IF I>100000 THEN ?CHR$(7):GOTO 50 > 40 HPLOT X,Y: ON PEEK(KB)<128 GOTO 20 > 50 TEXT:?I: FOR J=0 TO 4:? PEEK(201+J),:NEXT The reason that the test seemed to fail is that the RND generator was not yet in a cycle when the test started, so the initial random number never recurred within the cycle. The remark in line 190 of my program is incorrect--a "run-in" is needed to get into the cycle before attempting to measure its length. Here's a newer, more useful version of my program: 100 REM RND Cycle Length Test 110 REM MJM - 03/01/16 115 REM 03/03/16 - Added seed POKEs and initial "run-in" to cycle 120 : 130 REM RND cycle is 37758 (cold start after 6817 run-in) 140 REM 37758 (seed with -2.71828 after 13218 run-in) 150 REM (see note!) ==> 202 (seed with -3.14159 after 30771 run-in) 160 REM 202 (intended cold start after 15381 run-in) 170 REM 202 (seed with -4 or -5) 180 REM 32366 (seed with -2, -3, or -6) 190 : 200 INPUT "Seed? (0=default, >0=intended, <0=seed): ";S 210 POKE 201,128: POKE 202,79: POKE 203,199: POKE 204,82: POKE 205,255 220 IF S = 0 GOTO 310: REM Use default seed (with init bug) 230 IF S > 0 THEN POKE 205,88: GOTO 310: REM Use intended seed 240 REM Else use supplied seed 250 : 300 X = RND (S): REM Optional seed 310 FOR I = 1 TO 50000:X = RND (1): NEXT : REM Run-in to cycle 320 : 330 X = RND (1): REM Sample cycle for comparison 340 GOSUB 430: REM Print seed 350 : 360 FOR I = 1 TO 100000:Y = RND (1): IF X = Y GOTO 390 370 NEXT 380 : 390 PRINT "RND cycle is "I" long." 400 GOSUB 430: REM Print seed 410 END 420 : 430 REM Print the seed 440 SEED = 201 450 FOR J = 0 TO 4: PRINT PEEK (SEED + J)" ";: NEXT : PRINT 460 RETURN First, the "note" referred to in line 150 is that I found a peculiarity in Applesoft: if you INPUT -3.14159 into a variable and then call RND with that variable as an argument, the result is subtly different (low byte(s)?) from calling RND with the literal, e.g. RND(3.14159). This was mildly surprising, but I left the result for the literal call in line 150 since I had taken the trouble to determine the required run-in using binary search. ;-) Now for the general comments... Different seeds result in differing numbers of RND results which are *outside* the eventual cycle. After this "run-in", you are in the cycle and it can be measured. Since a cycle is a cycle, it doesn't matter if the run-in is longer than necessary (except for time), since once you're in the cycle, you stay there (until re-seeding). As I mentioned, I determined a few actual run-in values by varying the run-in (using binary search) until I just entered the cycle. Note that the longest run-in I found was just over 30,000 calls in, at which point RND entered a length 202 cycle. So I took a stab at "enough" of a run-in at 50,000 calls. This may not be large enough for some seeds, but I'm guessing that it's plenty for such a rasty generator. Trust me, the RND code is a disaster--it's not just the seed value! Of course, it's OK for shuffling cards or rolling dice, but don't ever use it when you really need a lot of pseudorandom numbers. -- -michael NadaNet 3.1 for Apple II parallel computing! Home page: http://michaeljmahon.com "The wastebasket is our most important design tool--and it's seriously underused."
[toc] | [prev] | [next] | [standalone]
| From | "Michael J. Mahon" <mjmahon@aol.com> |
|---|---|
| Date | 2016-03-03 14:48 -0800 |
| Message-ID | <JsmdndHmlLu1IkXLnZ2dnUU7-fXNnZ2d@giganews.com> |
| In reply to | #2420 |
On 3/2/2016 8:49 PM, Michael J. Mahon wrote: > On 3/1/2016 10:03 PM, gids.rs@sasktel.net wrote: >> On Tuesday, March 1, 2016 at 9:24:53 PM UTC-6, mjm...@aol.com wrote: >>> On 3/1/2016 6:50 PM, Michael Pohoreski wrote: >>>> On Tuesday, March 1, 2016 at 3:28:19 PM UTC-8, mjm...@aol.com wrote: >>>>> I couldn't help it--I just had to determine the period of >>>>> Applesoft's RND >>>>> function... ;-) >>>> >>>> That's OK, you're in good company -- obsessed ^H^H^H inquiring minds >>>> want to know. :-) >>>> >>>>> From a cold start without seeding, it cycles after 37758 calls. >>>>> (Since >>>>> Applesoft doesn't fully initialize the seed, >>>> >>>> You wouldn't happen to remember where Applesoft inits RNDSEED ? >>>> I had found it and lost it again. :-/ >>>> >>>>> this may vary depending on the >>>>> prior content of page zero.) >>>> >>>> Is 37758 the max period ? >>>> >>>> Hmm, I guess the F800 ROM random bytes (RNDL = $4E, RNDH = $4F) are >>>> never used. >>>> >>>> Hmm, looking over the disassembly I see RNDSEED is a 5 byte >>>> floating-point, using a simple linear congruential generator: >>>> >>>> C9- RNDSEED .EQ $C9 - CD >>>> >>>> EFA6- 98 35 44 >>>> EFA9- 7A CON.RND.1 .HS 9835447A <<< THESE ARE MISSING ONE >>>> BYTE >>> >>>> EFAA- 68 28 B1 >>>> EFAD- 46 CON.RND.2 .HS 6828B146 <<< FOR FP >>>> VALUES >>> >>>> *-------------------------------- >>>> * "RND" FUNCTION >>>> *-------------------------------- >>>> EFAE- 20 82 EB RND JSR SIGN REDUCE ARGUMENT TO -1, 0, OR +1 >>>> EFB1- AA TAX SAVE ARGUMENT >>>> EFB2- 30 18 BMI .1 = -1, USE CURRENT ARGUMENT FOR SEED >>>> EFB4- A9 C9 LDA #RNDSEED USE CURRENT SEED >>>> EFB6- A0 00 LDY /RNDSEED >>>> EFB8- 20 F9 EA JSR LOAD.FAC.FROM.YA >>>> EFBB- 8A TXA RECALL SIGN OF ARGUMENT >>>> EFBC- F0 E7 BEQ RTS.19 =0, RETURN SEED UNCHANGED >>>> EFBE- A9 A6 LDA #CON.RND.1 VERY POOR RND ALGORITHM >>>> EFC0- A0 EF LDY /CON.RND.1 >>>> EFC2- 20 7F E9 JSR FMULT >>>> EFC5- A9 AA LDA #CON.RND.2 ALSO, CONSTANTS ARE TRUNCATED >>>> EFC7- A0 EF LDY /CON.RND.2 <<<THIS DOES NOTHING, DUE TO >>> >>>> * <<<SMALL >>>> EXPONENT >>> >>>> EFC9- 20 BE E7 JSR FADD >>>> EFCC- A6 A1 .1 LDX FAC+4 SHUFFLE HI AND LO BYTES >>>> EFCE- A5 9E LDA FAC+1 TO SUPPOSEDLY MAKE IT MORE RANDOM >>>> EFD0- 85 A1 STA FAC+4 >>>> EFD2- 86 9E STX FAC+1 >>>> EFD4- A9 00 LDA #0 MAKE IT POSITIVE >>>> EFD6- 85 A2 STA FAC.SIGN >>>> EFD8- A5 9D LDA FAC A SOMEWHAT RANDOM EXTENSION >>>> EFDA- 85 AC STA FAC.EXTENSION >>>> EFDC- A9 80 LDA #$80 EXPONENT TO MAKE VALUE < 1.0 >>>> EFDE- 85 9D STA FAC >>>> EFE0- 20 2E E8 JSR NORMALIZE.FAC.2 >>>> EFE3- A2 C9 LDX #RNDSEED MOVE FAC TO RND SEED >>>> EFE5- A0 00 LDY /RNDSEED >>>> EFE7- 4C 2B EB GO.MOVMF JMP STORE.FAC.AT.YX.ROUNDED >>>> >>>> Did I get CON.RND.1 and CON.RND.2 right? >>>> >>>> ; CON.RND.1 EQU $EFA6; 11879546.4 >>>> ; CON.RND.2 EQU $EFAA; 3.92767778E-08 >>>> >>>> 300: LDA #$A6 >>>> LDY #$EF >>>> JSR $EAF9 ; LOAD.FAC.YA >>>> JSR $ED34 ; FOUT >>>> JSR $E3E7 ; STRLIT >>>> JMP $DACD ; STRPRT >>>> LDA #AA >>>> BNE $302 >>>> >>>> >>>>> Seeded with RND(-2.71828), it cycles after 37758 calls (same cycle). >>>> >>>> I guess with a period of ~32K for an 8-bit CPU it isn't going to win >>>> any "good" distributions anytime soon. :-/ >>>> >>>>> Seeded with RND(-3.14159), it cycles after only 202 calls! >>>>> This is a seriously broken PRNG! >>>> >>>> WOW -- that is horrible!! Especially for a 5 byte seed! >>>> >>>> So this is a legitimate case of where we can blame Bill Gates? :-) >>>> >>>>> If we take 37758 as the typical cycle, and we take two RNDs per >>>>> attempted >>>>> pixel set, there will be only 18879 different pairs of coordinates, >>>>> so the >>>>> 53760 pixel HGR screen will stay mostly black. >>>>> If the cycle were an odd length, then as many as 37758 pixels might >>>>> be set. >>>> >>>> Mind posting your test program per chance please? :-) >>>> >>>> >>>> Great investigation BTW ! >>> >>> Thanks, but it's pretty trivial--it's fun to answer a question in a few >>> minutes at the keyboard. ;-) >>> >>> Here's the program: >>> >>> 100 REM RND Cycle Length Test >>> 110 REM MJM - 03/01/16 >>> 120 : >>> 130 REM Empirical RND cycle is 37758 from cold start. >>> 140 REM 37758 from seed with -2.71828 >>> 150 REM 202 from seed with -3.14159 >>> 190 REM 200 not needed; RND cycles from the start. >>> 200 REM FOR I = 1 TO 37758:X = RND (1): NEXT : REM Get into cycle >>> 205 X = RND (1) >>> 210 : >>> 220 FOR I = 1 TO 100000:Y = RND (1): IF X = Y GOTO 300 >>> 230 NEXT >>> 290 : >>> 300 PRINT "RND cycle is "I" long." >>> >>> Note that since RND has only it's seed/previous result for state, once >>> it is seeded you are already in whatever cycle there will be, so no >>> initial cycling is needed (which is why line 200 is commented out). >>> >>> Contrast this with the shift register PRNG I posted earlier in this >>> thread, which has 32 bytes of internal state, holding eight parallel >>> 32-bit shift registers with a period of 2^32-1. >>> -- >>> >>> -michael >>> >> >> >> Uhm! Your test seems to fail, Michael. If you poked the last byte >> into the seed from the prompt, it seems to run forever, but then try >> the test plot program. The plotting still stops about the same time >> without the full 5 byte seedrun. >> >> >> 10 POKE 205,88:X=RND(1) >> 20 FOR I=1 TO 10000000:Y=RND(1):ONX=YGOTO100 >> 30 NEXT >> 100 ? I" random numbers" >> >> >> 5 KB=49152: POKE 205,88 >> 10 HGR : HCOLOR= 3: POKE 49234,0 >> 20 X = RND (1) * 280:Y = RND (1) * 192:I=I+2 >> 30 HPLOT X,Y: ON PEEK (KB) < 128 GOTO 20 >> >> >> After a few tests, I came to the determination that the applesoft code >> is not so much at fault as it is just a bad seed. Even with the 5th >> byte. >> >> Try this seed that I came up with and try applesoft again. Also >> instead of rebooting your computer each time, you can just poke in the >> original seed to get the same result. >> >> Here is a new test. >> Type HGR:RUN the first time, then RUN5 the second time. Notice that >> line #30 never takes. How full is the hi-res screen now? Also line >> #50 can be used to keep track of a good seed that can be either saved >> to disk and re-entered later. >> >> >> 2 POKE 201,128: POKE 202,79: POKE 203,199: POKE 204,82: POKE 205,88 >> 3 GOTO 10 >> 5 POKE 205,88: J=1 :Z1 = RND(1):Z2=RND(2) >> 10 KB=49152: POKE 49232,0: HCOLOR=3: POKE 49234,0 >> 20 X=RND(1)*280: Y=RND(1)*192 >> 25 I=I+2:IF J=0 THEN IF I>57232 THEN ?CHR$(7):GOTO 50 >> 30 IF X=Z1 OR X=Z2 THEN 50 >> 35 IF J=1 THEN IF I>100000 THEN ?CHR$(7):GOTO 50 >> 40 HPLOT X,Y: ON PEEK(KB)<128 GOTO 20 >> 50 TEXT:?I: FOR J=0 TO 4:? PEEK(201+J),:NEXT > > The reason that the test seemed to fail is that the RND generator was > not yet in a cycle when the test started, so the initial random number > never recurred within the cycle. The remark in line 190 of my program > is incorrect--a "run-in" is needed to get into the cycle before > attempting to measure its length. > > Here's a newer, more useful version of my program: > > 100 REM RND Cycle Length Test > 110 REM MJM - 03/01/16 > 115 REM 03/03/16 - Added seed POKEs and initial "run-in" to cycle > 120 : > 130 REM RND cycle is 37758 (cold start after 6817 run-in) > 140 REM 37758 (seed with -2.71828 after 13218 run-in) > 150 REM (see note!) ==> 202 (seed with -3.14159 after 30771 run-in) > 160 REM 202 (intended cold start after 15381 run-in) > 170 REM 202 (seed with -4 or -5) > 180 REM 32366 (seed with -2, -3, or -6) > 190 : > 200 INPUT "Seed? (0=default, >0=intended, <0=seed): ";S > 210 POKE 201,128: POKE 202,79: POKE 203,199: POKE 204,82: POKE 205,255 > 220 IF S = 0 GOTO 310: REM Use default seed (with init bug) > 230 IF S > 0 THEN POKE 205,88: GOTO 310: REM Use intended seed > 240 REM Else use supplied seed > 250 : > 300 X = RND (S): REM Optional seed > 310 FOR I = 1 TO 50000:X = RND (1): NEXT : REM Run-in to cycle > 320 : > 330 X = RND (1): REM Sample cycle for comparison > 340 GOSUB 430: REM Print seed > 350 : > 360 FOR I = 1 TO 100000:Y = RND (1): IF X = Y GOTO 390 > 370 NEXT > 380 : > 390 PRINT "RND cycle is "I" long." > 400 GOSUB 430: REM Print seed > 410 END > 420 : > 430 REM Print the seed > 440 SEED = 201 > 450 FOR J = 0 TO 4: PRINT PEEK (SEED + J)" ";: NEXT : PRINT > 460 RETURN > > First, the "note" referred to in line 150 is that I found a peculiarity > in Applesoft: if you INPUT -3.14159 into a variable and then call RND > with that variable as an argument, the result is subtly different (low > byte(s)?) from calling RND with the literal, e.g. RND(3.14159). > > This was mildly surprising, but I left the result for the literal call > in line 150 since I had taken the trouble to determine the required > run-in using binary search. ;-) > > Now for the general comments... > > Different seeds result in differing numbers of RND results which are > *outside* the eventual cycle. After this "run-in", you are in the cycle > and it can be measured. Since a cycle is a cycle, it doesn't matter if > the run-in is longer than necessary (except for time), since once you're > in the cycle, you stay there (until re-seeding). > > As I mentioned, I determined a few actual run-in values by varying the > run-in (using binary search) until I just entered the cycle. Note that > the longest run-in I found was just over 30,000 calls in, at which point > RND entered a length 202 cycle. So I took a stab at "enough" of a > run-in at 50,000 calls. This may not be large enough for some seeds, > but I'm guessing that it's plenty for such a rasty generator. > > Trust me, the RND code is a disaster--it's not just the seed value! > > Of course, it's OK for shuffling cards or rolling dice, but don't ever > use it when you really need a lot of pseudorandom numbers. I got tired of doing the binary search for entry to the cycle by hand, so here's a new version of the RND.CYCLE program that accepts any key and determines the length of the eventual cycle and the length of the run-in to the cycle. 100 REM RND Cycle Length Test 110 REM MJM - 03/01/16 120 REM 03/02/16 - Added seed POKEs and initial "run-in" to cycle 130 REM 03/03/16 - Added binary search for "run-in" to cycle 140 : 150 REM RND cycle is 37758 (cold start after 6817 run-in) 160 REM 202 (intended cold start after 15381 run-in) 170 REM 37758 (seed with -2.71828 after 13218 run-in) 180 REM 37758 (seed with -3.14159 after 9256 run-in) 190 REM (note!) ==> 37758 (seed with -3.14159 after 6817 run-in) 200 REM 32366 (seed with -2 after 3887 run-in) 210 REM 32366 (seed with -3 after 22481 run-in) 220 REM 202 (seed with -4 after 22731 run-in) 230 REM 202 (seed with -5 after 36775 run-in) 240 REM 32366 (seed with -6 after 7912 run-in) 250 : 300 RI = 50000:ST = INT (RI + .7) / 2:CY = 100000 310 INPUT "Seed? (0=default, >0=intended, <0=seed): ";S 320 POKE 201,128: POKE 202,79: POKE 203,199: POKE 204,82: POKE 205,255 330 IF S = 0 GOTO 420: REM Use default seed (with init bug) 340 IF S > 0 THEN POKE 205,88: GOTO 420: REM Use intended seed 350 REM Else use supplied seed 360 : 400 X = RND (S): REM Optional seed 420 PRINT "Run-in = "RI", step = "ST", cycle = "CY - 5 430 FOR I = 1 TO RI:X = RND (1): NEXT : REM Run-in to cycle 440 : 450 X = RND (1): REM Sample cycle for comparison 460 : 470 FOR I = 1 TO CY:Y = RND (1): IF X = Y GOTO 540 480 NEXT 490 : 500 REM Not in cycle, increase run-in by step and try again 510 RI = RI + ST:ST = INT (ST / 2 + .7) 520 GOTO 320 530 : 540 IF ST = 1 GOTO 600 550 REM In cycle. Decrease RI and CY and try again 560 RI = RI - ST:CY = I + 5 570 ST = INT (ST / 2 + .7) 580 GOTO 320 590 : 600 PRINT "RND run-in is "RI 610 PRINT "RND cycle is "I" long." 620 END It seems that any seed will, pretty quickly, enter a cycle. There are apparently several cycles of various lengths, including one just 202 numbers long! -michael NadaNet 3.1 for Apple II parallel computing! Home page: http://michaeljmahon.com "The wastebasket is our most important design tool--and it's seriously underused."
[toc] | [prev] | [next] | [standalone]
| From | "Michael J. Mahon" <mjmahon@aol.com> |
|---|---|
| Date | 2016-03-01 20:02 -0800 |
| Message-ID | <xaudncrlbLxK-EvLnZ2dnUU7-LfNnZ2d@giganews.com> |
| In reply to | #2414 |
On 3/1/2016 6:50 PM, Michael Pohoreski wrote:
> On Tuesday, March 1, 2016 at 3:28:19 PM UTC-8, mjm...@aol.com wrote:
>> I couldn't help it--I just had to determine the period of Applesoft's RND
>> function... ;-)
>
> That's OK, you're in good company -- obsessed ^H^H^H inquiring minds want to know. :-)
>
>> From a cold start without seeding, it cycles after 37758 calls. (Since
>> Applesoft doesn't fully initialize the seed,
>
> You wouldn't happen to remember where Applesoft inits RNDSEED ?
> I had found it and lost it again. :-/
>
>> this may vary depending on the
>> prior content of page zero.)
>
> Is 37758 the max period ?
>
> Hmm, I guess the F800 ROM random bytes (RNDL = $4E, RNDH = $4F) are never used.
>
> Hmm, looking over the disassembly I see RNDSEED is a 5 byte floating-point, using a simple linear congruential generator:
>
> C9- RNDSEED .EQ $C9 - CD
>
> EFA6- 98 35 44
> EFA9- 7A CON.RND.1 .HS 9835447A <<< THESE ARE MISSING ONE BYTE >>>
> EFAA- 68 28 B1
> EFAD- 46 CON.RND.2 .HS 6828B146 <<< FOR FP VALUES >>>
> *--------------------------------
> * "RND" FUNCTION
> *--------------------------------
> EFAE- 20 82 EB RND JSR SIGN REDUCE ARGUMENT TO -1, 0, OR +1
> EFB1- AA TAX SAVE ARGUMENT
> EFB2- 30 18 BMI .1 = -1, USE CURRENT ARGUMENT FOR SEED
> EFB4- A9 C9 LDA #RNDSEED USE CURRENT SEED
> EFB6- A0 00 LDY /RNDSEED
> EFB8- 20 F9 EA JSR LOAD.FAC.FROM.YA
> EFBB- 8A TXA RECALL SIGN OF ARGUMENT
> EFBC- F0 E7 BEQ RTS.19 =0, RETURN SEED UNCHANGED
> EFBE- A9 A6 LDA #CON.RND.1 VERY POOR RND ALGORITHM
> EFC0- A0 EF LDY /CON.RND.1
> EFC2- 20 7F E9 JSR FMULT
> EFC5- A9 AA LDA #CON.RND.2 ALSO, CONSTANTS ARE TRUNCATED
> EFC7- A0 EF LDY /CON.RND.2 <<<THIS DOES NOTHING, DUE TO >>>
> * <<<SMALL EXPONENT >>>
> EFC9- 20 BE E7 JSR FADD
> EFCC- A6 A1 .1 LDX FAC+4 SHUFFLE HI AND LO BYTES
> EFCE- A5 9E LDA FAC+1 TO SUPPOSEDLY MAKE IT MORE RANDOM
> EFD0- 85 A1 STA FAC+4
> EFD2- 86 9E STX FAC+1
> EFD4- A9 00 LDA #0 MAKE IT POSITIVE
> EFD6- 85 A2 STA FAC.SIGN
> EFD8- A5 9D LDA FAC A SOMEWHAT RANDOM EXTENSION
> EFDA- 85 AC STA FAC.EXTENSION
> EFDC- A9 80 LDA #$80 EXPONENT TO MAKE VALUE < 1.0
> EFDE- 85 9D STA FAC
> EFE0- 20 2E E8 JSR NORMALIZE.FAC.2
> EFE3- A2 C9 LDX #RNDSEED MOVE FAC TO RND SEED
> EFE5- A0 00 LDY /RNDSEED
> EFE7- 4C 2B EB GO.MOVMF JMP STORE.FAC.AT.YX.ROUNDED
>
> Did I get CON.RND.1 and CON.RND.2 right?
>
> ; CON.RND.1 EQU $EFA6; 11879546.4
> ; CON.RND.2 EQU $EFAA; 3.92767778E-08
>
> 300: LDA #$A6
> LDY #$EF
> JSR $EAF9 ; LOAD.FAC.YA
> JSR $ED34 ; FOUT
> JSR $E3E7 ; STRLIT
> JMP $DACD ; STRPRT
> LDA #AA
> BNE $302
>
>
>> Seeded with RND(-2.71828), it cycles after 37758 calls (same cycle).
>
> I guess with a period of ~32K for an 8-bit CPU it isn't going to win any "good" distributions anytime soon. :-/
>
>> Seeded with RND(-3.14159), it cycles after only 202 calls!
>> This is a seriously broken PRNG!
>
> WOW -- that is horrible!! Especially for a 5 byte seed!
>
> So this is a legitimate case of where we can blame Bill Gates? :-)
>
>> If we take 37758 as the typical cycle, and we take two RNDs per attempted
>> pixel set, there will be only 18879 different pairs of coordinates, so the
>> 53760 pixel HGR screen will stay mostly black.
>> If the cycle were an odd length, then as many as 37758 pixels might be set.
>
> Mind posting your test program per chance please? :-)
>
>
> Great investigation BTW !
Here, from Bob Sander-Cederlof's disassembly of Applesoft, is the
COLD_START routine that incorrectly initializes the RND seed. This code
snippet starts at $F10B in the ROM.
Combined with the "mantissa-only" bug in the RND routine itself, this
routine is a disaster.
One of the problems with a PRNG is that it's not as easy to test as a
math function, like SIN or SQR, and clearly RND didn't get much testing!
;--------------------------------
; GENERIC COPY OF CHRGET SUBROUTINE, WHICH
; IS COPIED INTO $00B1...$00C8 DURING INITIALIZATION
;
; CORNELIS BONGERS DESCRIBED SEVERAL IMPROVEMENTS
; TO CHRGET IN MICRO MAGAZINE OR CALL A_P.P.L_E.
; (I DON'T REMEMBER WHICH OR EXACTLY WHEN)
;--------------------------------
GENERIC_CHRGET:
INC TXTPTR
BNE @1
INC TXTPTR+1
@1: LDA $EA60 ;<<< ACTUAL ADDRESS FILLED IN LATER >>>
CMP #':' ;EOS, ALSO TOP OF NUMERIC RANGE
BCS @2 ;NOT NUMBER, MIGHT BE EOS
CMP #' ' ;IGNORE BLANKS
BEQ GENERIC_CHRGET
SEC ;TEST FOR NUMERIC RANGE IN WAY THAT
SBC #'0' ;CLEARS CARRY IF CHAR IS DIGIT
SEC ;AND LEAVES CHAR IN A-REG
SBC #-'0'
@2: RTS
;--------------------------------
; INITIAL VALUE FOR RANDOM NUMBER, ALSO COPIED
; IN ALONG WITH CHRGET, BUT ERRONEOUSLY:
; <<< THE LAST BYTE IS NOT COPIED >>>
;--------------------------------
; .HS 804FC75258 APPROX. = .81163515
.byte $80, $4F, $C7, $52, $58
GENERIC_END:
;--------------------------------
COLD_START:
LDX #$FF ;SET DIRECT MODE FLAG
STX CURLIN+1
LDX #$FB ;SET STACK POINTER, LEAVING ROOM FOR
TXS ;LINE BUFFER DURING PARSING
LDA #<COLD_START ;SET RESTART TO COLD_START
LDY #>COLD_START ;UNTIL COLDSTART IS COMPLETED
STA GOWARM+1
STY GOWARM+2
STA GOSTROUT+1 ;ALSO SECOND USER VECTOR_..
STY GOSTROUT+2 ;..WE SIMPLY MUST FINISH COLD_START!
JSR NORMAL ;SET NORMAL DISPLAY MODE
LDA #$4C ;"JMP" OPCODE FOR 4 VECTORS
STA GOWARM ;WARM START
STA GOSTROUT ;ANYONE EVER USE THIS ONE?
STA JMPADRS ;USED BY FUNCTIONS (JSR JMPADRS)
STA USR ;"USR" FUNCTION VECTOR
LDA #<IQERR ;POINT "USR" TO ILLEGAL QUANTITY
LDY #>IQERR ;ERROR, UNTIL USER SETS IT UP
STA USR+1
STY USR+2
;--------------------------------
; MOVE GENERIC CHRGET AND RANDOM SEED INTO PLACE
;
; <<< NOTE THAT LOOP VALUE IS WRONG! >>>
; <<< THE LAST BYTE OF THE RANDOM SEED IS NOT >>>
; <<< COPIED INTO PAGE ZERO! >>>
;--------------------------------
LDX #GENERIC_END-GENERIC_CHRGET-1
@1: LDA GENERIC_CHRGET-1,X
STA CHRGET-1,X
STX SPEEDZ ;ON LAST PASS STORES $01)
DEX
BNE @1
;--------------------------------
--
-michael
NadaNet 3.1 for Apple II parallel computing!
Home page: http://michaeljmahon.com
"The wastebasket is our most important design
tool--and it's seriously underused."
[toc] | [prev] | [next] | [standalone]
| From | Michael Pohoreski <michael.pohoreski@gmail.com> |
|---|---|
| Date | 2016-03-03 07:48 -0800 |
| Message-ID | <6d52de94-fc33-423d-abdb-fad2ec5af67e@googlegroups.com> |
| In reply to | #2416 |
On Tuesday, March 1, 2016 at 8:02:32 PM UTC-8, mjm...@aol.com wrote: > Here, from Bob Sander-Cederlof's disassembly of Applesoft, is the > COLD_START routine that incorrectly initializes the RND seed. This code > snippet starts at $F10B in the ROM. > > Combined with the "mantissa-only" bug in the RND routine itself, this > routine is a disaster. Thanks Michael! That's *exactly* the code I was thinking of -- just couldn't remember the name (or location). Pity that AppleSoft doesn't use the 16-bit RNDL and RNDH as part of its seed. :-/ Off-topic: So it's Applesoft that copies code into the zero page -- **grr**.
[toc] | [prev] | [next] | [standalone]
| From | gids.rs@sasktel.net |
|---|---|
| Date | 2016-03-03 08:05 -0800 |
| Message-ID | <cbeb44d3-b7ef-486f-982f-dafebf271b97@googlegroups.com> |
| In reply to | #2421 |
> Pity that AppleSoft doesn't use the 16-bit RNDL and RNDH as part of its seed. :-/ > > Off-topic: So it's Applesoft that copies code into the zero page -- **grr**. That doesn't mean you can't copy over it once your program gets control. :) Just reseed with your own seed.
[toc] | [prev] | [next] | [standalone]
| From | Michael Pohoreski <michael.pohoreski@gmail.com> |
|---|---|
| Date | 2016-03-03 09:24 -0800 |
| Message-ID | <dc132c99-920e-4b8d-b9b9-ac3b04f1097b@googlegroups.com> |
| In reply to | #2422 |
On Thursday, March 3, 2016 at 8:05:13 AM UTC-8, gid...@sasktel.net wrote: > > Pity that AppleSoft doesn't use the 16-bit RNDL and RNDH as part of its seed. :-/ > That doesn't mean you can't copy over it once your program gets control. :) > Just reseed with your own seed. Touché. :-)
[toc] | [prev] | [next] | [standalone]
| From | Michael J. Mahon <mjmahon@aol.com> |
|---|---|
| Date | 2016-03-03 22:51 -0600 |
| Message-ID | <ysydnSecMKD8iUTLnZ2dnUU7-LHNnZ2d@giganews.com> |
| In reply to | #2421 |
Michael Pohoreski <michael.pohoreski@gmail.com> wrote: > On Tuesday, March 1, 2016 at 8:02:32 PM UTC-8, mjm...@aol.com wrote: >> Here, from Bob Sander-Cederlof's disassembly of Applesoft, is the >> COLD_START routine that incorrectly initializes the RND seed. This code >> snippet starts at $F10B in the ROM. >> >> Combined with the "mantissa-only" bug in the RND routine itself, this >> routine is a disaster. > > Thanks Michael! That's *exactly* the code I was thinking of -- just > couldn't remember the name (or location). > > Pity that AppleSoft doesn't use the 16-bit RNDL and RNDH as part of its seed. :-/ When debugging, you want deterministic pseudorandom numbers. You can always PEEK the GETCHR counter and use it to seed RND if you want a different set each time. By default, RND delivers the same sequence each time after a cold start (assuming that the uninitialized low byte of the seed powers up in the same state ;-). If you really want to be sure the same sequence occurs on each run, you should seed RND at the start of your program, though a good fraction of seeds seem to deliver a modest pseudorandom sequence followed by a short cycle... -- -michael - NadaNet 3.1 and AppleCrate II: http://michaeljmahon.com
[toc] | [prev] | [next] | [standalone]
| From | gids.rs@sasktel.net |
|---|---|
| Date | 2016-03-03 21:34 -0800 |
| Message-ID | <b798ece7-5b0d-44d6-ab1d-aee6dee0e8ab@googlegroups.com> |
| In reply to | #2425 |
> > Thanks Michael! That's *exactly* the code I was thinking of -- just > > couldn't remember the name (or location). > > > > Pity that AppleSoft doesn't use the 16-bit RNDL and RNDH as part of its seed. :-/ > > When debugging, you want deterministic pseudorandom numbers. You can > always PEEK the GETCHR counter and use it to seed RND if you want a > different set each time. > > By default, RND delivers the same sequence each time after a cold start > (assuming that the uninitialized low byte of the seed powers up in the same > state ;-). > > If you really want to be sure the same sequence occurs on each run, you > should seed RND at the start of your program, though a good fraction of > seeds seem to deliver a modest pseudorandom sequence followed by a short > cycle... For the IIGS anyways, I think the VBL and HBL would be an excellent source for a seed on startup. These values are always random and when used in conjunction with RNDL and RNDH can give a 4-byte random seed, and you can even give a random key press for a 5th byte, different every time on bootup. I use this for a 5 byte random seed in Sweet 16 and GSPORT and real IIGS. I believe this should work in a IIc as well but not II+ or IIe's standard or enhanced. ]LOOP INC $4E BNE NOTHI INC $4F NOTHI BIT $C000 BPL ]LOOP LDA $C010 STA $C9 LDX $C02E LDA $C02F STX $CD STA $CC LDA $4E LDX $4F STA $CB STX $C9 ... test to see if your computer's VBL or HBL gives values with this: 300: LDX $C02E LDA $C02F JSR $F941 BIT $C000 BPL $300 BIT $C010 RTS
[toc] | [prev] | [next] | [standalone]
| From | Michael J. Mahon <mjmahon@aol.com> |
|---|---|
| Date | 2016-03-04 00:50 -0600 |
| Message-ID | <7NadnThcNNnNrUTLnZ2dnUU7-KfNnZ2d@giganews.com> |
| In reply to | #2426 |
<gids.rs@sasktel.net> wrote: >>> Thanks Michael! That's *exactly* the code I was thinking of -- just >>> couldn't remember the name (or location). >>> >>> Pity that AppleSoft doesn't use the 16-bit RNDL and RNDH as part of its seed. :-/ >> >> When debugging, you want deterministic pseudorandom numbers. You can >> always PEEK the GETCHR counter and use it to seed RND if you want a >> different set each time. >> >> By default, RND delivers the same sequence each time after a cold start >> (assuming that the uninitialized low byte of the seed powers up in the same >> state ;-). >> >> If you really want to be sure the same sequence occurs on each run, you >> should seed RND at the start of your program, though a good fraction of >> seeds seem to deliver a modest pseudorandom sequence followed by a short >> cycle... > > > For the IIGS anyways, I think the VBL and HBL would be an excellent > source for a seed on startup. These values are always random and when > used in conjunction with RNDL and RNDH can give a 4-byte random seed, and > you can even give a random key press for a 5th byte, different every time on bootup. > > I use this for a 5 byte random seed in Sweet 16 and GSPORT and real IIGS. > I believe this should work in a IIc as well but not II+ or IIe's standard or enhanced. > > ]LOOP INC $4E > BNE NOTHI > INC $4F > NOTHI BIT $C000 > BPL ]LOOP > LDA $C010 > STA $C9 > LDX $C02E > LDA $C02F > STX $CD > STA $CC > LDA $4E > LDX $4F > STA $CB > STX $C9 > ... > > > test to see if your computer's VBL or HBL gives values with this: > > 300: LDX $C02E > LDA $C02F > JSR $F941 > BIT $C000 > BPL $300 > BIT $C010 > RTS > When you seed a random number generator you are only selecting a point in the generators cycle where you want to start. A good generator will have a very long cycle, but every generator has at least one cycle, and a good generator has only one, maximal length cycle. So if you have a two-byte seed, you are randomly selecting one of 2^16 starting points in the cycle. A longer seed does not make the numbers more random, it just selects from a larger number of starting points. The quality of a PRNG is not determined by its seed, but only by its algorithm. I'd guess that 2^16 different sequences of pseudorandom numbers is more than enough for any application. In the case of Applesoft's RND generator, it is so riddled with short cycles that seeding with a random (and therefore untested) seed has a high probability of producing a short, degenerate sequence. Better to select from a small set of seeds that have been verified to generate at least a few thousand different numbers. Of course, it's actually best to avoid RND entirely for any serious work. -- -michael - NadaNet 3.1 and AppleCrate II: http://michaeljmahon.com
[toc] | [prev] | [next] | [standalone]
| From | Scott Hemphill <hemphill@hemphills.net> |
|---|---|
| Date | 2016-03-04 10:47 -0500 |
| Message-ID | <87ziue2qke.fsf@hemphills.net> |
| In reply to | #2427 |
Michael J. Mahon <mjmahon@aol.com> writes: > <gids.rs@sasktel.net> wrote: >>>> Thanks Michael! That's *exactly* the code I was thinking of -- just >>>> couldn't remember the name (or location). >>>> >>>> Pity that AppleSoft doesn't use the 16-bit RNDL and RNDH as part >>>> of its seed. :-/ >>> >>> When debugging, you want deterministic pseudorandom numbers. You can >>> always PEEK the GETCHR counter and use it to seed RND if you want a >>> different set each time. >>> >>> By default, RND delivers the same sequence each time after a cold start >>> (assuming that the uninitialized low byte of the seed powers up in the same >>> state ;-). >>> >>> If you really want to be sure the same sequence occurs on each run, you >>> should seed RND at the start of your program, though a good fraction of >>> seeds seem to deliver a modest pseudorandom sequence followed by a short >>> cycle... >> >> >> For the IIGS anyways, I think the VBL and HBL would be an excellent >> source for a seed on startup. These values are always random and when >> used in conjunction with RNDL and RNDH can give a 4-byte random seed, and >> you can even give a random key press for a 5th byte, different every >> time on bootup. >> >> I use this for a 5 byte random seed in Sweet 16 and GSPORT and real IIGS. >> I believe this should work in a IIc as well but not II+ or IIe's >> standard or enhanced. >> >> ]LOOP INC $4E >> BNE NOTHI >> INC $4F >> NOTHI BIT $C000 >> BPL ]LOOP >> LDA $C010 >> STA $C9 >> LDX $C02E >> LDA $C02F >> STX $CD >> STA $CC >> LDA $4E >> LDX $4F >> STA $CB >> STX $C9 >> ... >> >> >> test to see if your computer's VBL or HBL gives values with this: >> >> 300: LDX $C02E >> LDA $C02F >> JSR $F941 >> BIT $C000 >> BPL $300 >> BIT $C010 >> RTS >> > > When you seed a random number generator you are only selecting a point in > the generators cycle where you want to start. > > A good generator will have a very long cycle, but every generator has at > least one cycle, and a good generator has only one, maximal length cycle. > > So if you have a two-byte seed, you are randomly selecting one of 2^16 > starting points in the cycle. A longer seed does not make the numbers more > random, it just selects from a larger number of starting points. The > quality of a PRNG is not determined by its seed, but only by its algorithm. > > > I'd guess that 2^16 different sequences of pseudorandom numbers is more > than enough for any application. > > In the case of Applesoft's RND generator, it is so riddled with short > cycles that seeding with a random (and therefore untested) seed has a high > probability of producing a short, degenerate sequence. Better to select > from a small set of seeds that have been verified to generate at least a > few thousand different numbers. > > Of course, it's actually best to avoid RND entirely for any serious work. I used a high-quality linear congruential generator in my 3D tic-tac-toe program. I was just going to say something about it, and I found this URL in my program comments: http://www.6502.org/source/integers/random/random.html Scott -- Scott Hemphill hemphill@alumni.caltech.edu "This isn't flying. This is falling, with style." -- Buzz Lightyear
[toc] | [prev] | [next] | [standalone]
| From | qkumba <peter.ferrie@gmail.com> |
|---|---|
| Date | 2018-09-05 20:41 -0700 |
| Message-ID | <03b0c495-f0c0-404b-82ec-7694ed8f71f3@googlegroups.com> |
| In reply to | #2429 |
Okay, finally I returned to the SQR code. Here's the whole source with my changes. It caches the temp1 in X instead of zpage, so it shaves 7(?) cycles per iteration. To save two bytes, you could omit the "bne :start ; (always)" but it would cost 31 cycles. ********************************************************** * * * SQR (X) as USR (X) * * * * Michael J. Mahon * * April 03, 2009 * * Copyright 2009 * * * * Called by USR(X), computes square root of X using a * * direct non-restoring algorithm requiring about 5.2 * * milliseconds on a 1MHz processor, or about nine times * * faster than the Applesoft SQR function. * * * * USR.SQR is location-independent, and so may be BRUN * * at any location to install it as the USR function. * * * ********************************************************** * Applesoft Page Zero Definitions USR equ $0A ; JMP to USR function FAC equ $9D ; Floating-Point Accumulator FACSGN equ FAC+5 ; FAC unpacked sign EXTRAFAC equ $AC ; FAC guard byte TEMP1 equ $93 ; Temp FP storage ARG equ $A5 ; Aux FAC * Apple ROM routines IQERR equ $E199 ; "Illegal Quantity Error" MOVAF equ $EB63 ; Move rounded FAC to ARG IORTS equ $FF58 ; Location of RTS * Macro Definitions rol32 mac ; Rotate 32 bit int left rol ]1+3 rol ]1+2 rol ]1+1 rol eom asl32 mac ; Shift 32 bit int left asl ]1+3 rol ]1+2 rol ]1+1 rol ]1 eom pag org $310 * Set up USR jump to go to sqr entry jsr IORTS ; Get entry+2 on stack tsx clc ldaa $100-1,x ; Lo byte of entry+2 adc #<]offset ; Lo byte of sqr sta USR+1 ldaa $100,x ; Hi byte of entry+2 adc #>]offset ; Hi byte of sqr sta USR+2 rts rts pag * Square Root function sqr lda FAC ; Is FAC zero? beq rts ; -Yes, sqrt(0) = 0. bit FACSGN ; -No, is argument negative? bpl :ok ; -No, go ahead. jmp IQERR ; -Yes, Illegal Quantity! :ok lda FAC ; Divide exponent by 2 clc ; for initial approximation. adc #$80 ; Move hi bit to C & clear it. ror ; Divide by 2, restore hi bit. sta FAC bcc :even ; If exp even, no adjust, inc FAC ; If odd, inc exponent lsr FAC+1 ; and shift it right. ror FAC+2 ror FAC+3 ror FAC+4 ror EXTRAFAC ; (save low bit) :even jsr MOVAF ; Move rounded FAC to ARG ldy #3 ;;ldx #0 ; Zero FAC & TEMP1 mants :clear stx FAC+1,y stx TEMP1+1,y dey bpl :clear ldy #32 ; Gen 32 bits of sqrt bne :start ; (always) :loop ;;ldx TEMP1+1 ; Compare 40 bits of X cpx FAC+1 ; with current sqrt. bne :check1 lda TEMP1+2 ; Compare next byte cmp FAC+2 bne :check lda TEMP1+3 ; Compare next byte cmp FAC+3 bne :check lda TEMP1+4 ; Compare next byte cmp FAC+4 bne :check :start lda ARG+1 ; Compare final byte cmp #%01000000 :check txa :check1 bcc :shift0 ; X > sqrt lda ARG+1 ; X <= sqrt, so subtract sbc #%01000000 sta ARG+1 lda TEMP1+4 sbc FAC+4 sta TEMP1+4 lda TEMP1+3 sbc FAC+3 sta TEMP1+3 lda TEMP1+2 sbc FAC+2 sta TEMP1+2 txa sbc FAC+1 :shift0 rol32 FAC+1 ; Rotate C into sqrt asl32 ARG+1 ; Left shift X rol32 TEMP1+1 asl32 ARG+1 ; by 2 bits. rol32 TEMP1+1 tax dey ; Done? bne :loop ; -No, keep looping. ;;lda TEMP1+1 ; -Yes, compute final cmp FAC+1 ; bit of sqrt ror EXTRAFAC ; in FAC extension. rts ]offset equ sqr-entry-2 ; Offset = sqr - (entry+2)
[toc] | [prev] | [next] | [standalone]
| From | Antoine Vignau <antoine.vignau@laposte.net> |
|---|---|
| Date | 2018-09-06 09:13 -0700 |
| Message-ID | <7628daf5-6574-47dc-8e10-6b3eee6ce2da@googlegroups.com> |
| In reply to | #4750 |
nice. is the rol32 macro missing a ]1 in the fourth rol? av
[toc] | [prev] | [next] | [standalone]
| From | qkumba <peter.ferrie@gmail.com> |
|---|---|
| Date | 2018-09-06 10:33 -0700 |
| Message-ID | <fdcf6b66-b7bf-4a2c-b905-a3edd53f1d8e@googlegroups.com> |
| In reply to | #4753 |
> is the rol32 macro missing a ]1 in the fourth rol? No, it's an intentional rol of A.
[toc] | [prev] | [next] | [standalone]
| From | Michael J. Mahon <mjmahon@aol.com> |
|---|---|
| Date | 2018-09-06 17:58 -0500 |
| Message-ID | <k8WdnahRx9-4LAzGnZ2dnUU7-X_NnZ2d@giganews.com> |
| In reply to | #4750 |
qkumba <peter.ferrie@gmail.com> wrote: > Okay, finally I returned to the SQR code. > Here's the whole source with my changes. > It caches the temp1 in X instead of zpage, so it shaves 7(?) cycles per iteration. Nice time shaving. ;-) > To save two bytes, you could omit the "bne :start ; (always)" but it would cost 31 cycles. > > ********************************************************** > * * > * SQR (X) as USR (X) * > * * > * Michael J. Mahon * > * April 03, 2009 * > * Copyright 2009 * > * * > * Called by USR(X), computes square root of X using a * > * direct non-restoring algorithm requiring about 5.2 * > * milliseconds on a 1MHz processor, or about nine times * > * faster than the Applesoft SQR function. * > * * > * USR.SQR is location-independent, and so may be BRUN * > * at any location to install it as the USR function. * > * * > ********************************************************** > > * Applesoft Page Zero Definitions > > USR equ $0A ; JMP to USR function > FAC equ $9D ; Floating-Point Accumulator > FACSGN equ FAC+5 ; FAC unpacked sign > EXTRAFAC equ $AC ; FAC guard byte > TEMP1 equ $93 ; Temp FP storage > ARG equ $A5 ; Aux FAC > > * Apple ROM routines > > IQERR equ $E199 ; "Illegal Quantity Error" > MOVAF equ $EB63 ; Move rounded FAC to ARG > IORTS equ $FF58 ; Location of RTS > > * Macro Definitions > > rol32 mac ; Rotate 32 bit int left > rol ]1+3 > rol ]1+2 > rol ]1+1 > rol > eom > > asl32 mac ; Shift 32 bit int left > asl ]1+3 > rol ]1+2 > rol ]1+1 > rol ]1 > eom > pag > org $310 > > * Set up USR jump to go to sqr > > entry jsr IORTS ; Get entry+2 on stack > tsx > clc > ldaa $100-1,x ; Lo byte of entry+2 > adc #<]offset ; Lo byte of sqr > sta USR+1 > ldaa $100,x ; Hi byte of entry+2 > adc #>]offset ; Hi byte of sqr > sta USR+2 > rts rts > pag > * Square Root function > > sqr lda FAC ; Is FAC zero? > beq rts ; -Yes, sqrt(0) = 0. > bit FACSGN ; -No, is argument negative? > bpl :ok ; -No, go ahead. > jmp IQERR ; -Yes, Illegal Quantity! > :ok lda FAC ; Divide exponent by 2 > clc ; for initial approximation. > adc #$80 ; Move hi bit to C & clear it. > ror ; Divide by 2, restore hi bit. > sta FAC > bcc :even ; If exp even, no adjust, > inc FAC ; If odd, inc exponent > lsr FAC+1 ; and shift it right. > ror FAC+2 > ror FAC+3 > ror FAC+4 > ror EXTRAFAC ; (save low bit) > :even jsr MOVAF ; Move rounded FAC to ARG > ldy #3 > ;;ldx #0 ; Zero FAC & TEMP1 mants > :clear stx FAC+1,y > stx TEMP1+1,y > dey > bpl :clear > ldy #32 ; Gen 32 bits of sqrt > bne :start ; (always) > > :loop ;;ldx TEMP1+1 ; Compare 40 bits of X > cpx FAC+1 ; with current sqrt. > bne :check1 > lda TEMP1+2 ; Compare next byte > cmp FAC+2 > bne :check > lda TEMP1+3 ; Compare next byte > cmp FAC+3 > bne :check > lda TEMP1+4 ; Compare next byte > cmp FAC+4 > bne :check > :start lda ARG+1 ; Compare final byte > cmp #%01000000 > :check txa > :check1 bcc :shift0 ; X > sqrt > lda ARG+1 ; X <= sqrt, so subtract > sbc #%01000000 > sta ARG+1 > lda TEMP1+4 > sbc FAC+4 > sta TEMP1+4 > lda TEMP1+3 > sbc FAC+3 > sta TEMP1+3 > lda TEMP1+2 > sbc FAC+2 > sta TEMP1+2 > txa > sbc FAC+1 > :shift0 rol32 FAC+1 ; Rotate C into sqrt > asl32 ARG+1 ; Left shift X > rol32 TEMP1+1 > asl32 ARG+1 ; by 2 bits. > rol32 TEMP1+1 > tax > dey ; Done? > bne :loop ; -No, keep looping. > ;;lda TEMP1+1 ; -Yes, compute final > cmp FAC+1 ; bit of sqrt > ror EXTRAFAC ; in FAC extension. > rts > > ]offset equ sqr-entry-2 ; Offset = sqr - (entry+2) > -- -michael - NadaNet 3.1 and AppleCrate II: http://michaeljmahon.com
[toc] | [prev] | [next] | [standalone]
| From | John Brooks <jbrooks@blueshiftinc.com> |
|---|---|
| Date | 2018-09-06 22:26 -0700 |
| Message-ID | <4e02b421-dd7f-47ad-98d9-ef838dafd70d@googlegroups.com> |
| In reply to | #2386 |
> I am looking for generators that are comparatively small in size, are quite fast in its algorythm and does a good job of filling the hi-res screen to white using the test program.
For things like dissolves and crossfades where each value should be visited just once, my favorite is the 16-bit shift-xor prng which got heavy use in my AppleII and GS games:
300:46 4F 66 4E 90 06 A9 B4 45 4F 85 4F 60
Here's an example program which fills the screen randomly:
5 REM PRNG demo. J.Brooks 9/6/2018
10 HGR2 : HCOLOR= 3: POKE 79,1
20 FOR I = 0 TO 65535: CALL 768
30 R = PEEK (78) + PEEK (79) * 256 - 1
40 Y = INT (R / 280):X = R - (Y * 280)
50 IF Y < 192 THEN HPLOT X,Y
60 NEXT : PRINT CHR$ (7): GET A$: TEXT
> Are there other more efficient methods for random number generation than ones mentioned here that I may have overlooked?
Below is the RND function used in many of Datasoft's Apple/Atari/C64 games that were made in the late 80s. It's not the fastest PRNG, but it's pretty small, effective, and often fast enough.
-JB
@JBrooksBSI
* DATASOFT RND 6502
* BY JAMES GARON
* 10/02/86
RNDINIT
LDA #$AB
STA RNDSEED
LDA #$55
STA RNDSEED+1
LDA #$7E
STA RNDSEED+2
RTS
* RESULT IN ACC
RND LDA RNDSEED
ROL RNDSEED
EOR RNDSEED
ROR RNDSEED
INC RNDSEED+1
BNE RND10
LDA RNDSEED+2
INC RNDSEED+2
RND10 ADC RNDSEED+1
BVC RND20
INC RNDSEED+1
BNE RND20
LDA RNDSEED+2
INC RNDSEED+2
RND20 STA RNDSEED
RTS
[toc] | [prev] | [next] | [standalone]
| From | John Brooks <jbrooks@blueshiftinc.com> |
|---|---|
| Date | 2018-09-07 18:08 -0700 |
| Message-ID | <ea7648c0-c1a5-4712-8ad4-e866da1558ff@googlegroups.com> |
| In reply to | #4756 |
On Thursday, September 6, 2018 at 10:26:10 PM UTC-7, John Brooks wrote: > > I am looking for generators that are comparatively small in size, are quite fast in its algorythm and does a good job of filling the hi-res screen to white using the test program. > > For things like dissolves and crossfades where each value should be visited just once, my favorite is the 16-bit shift-xor prng which got heavy use in my AppleII and GS games: > > 300:46 4F 66 4E 90 06 A9 B4 45 4F 85 4F 60 > > Here's an example program which fills the screen randomly: > > 5 REM PRNG demo. J.Brooks 9/6/2018 > 10 HGR2 : HCOLOR= 3: POKE 79,1 > 20 FOR I = 0 TO 65535: CALL 768 > 30 R = PEEK (78) + PEEK (79) * 256 - 1 > 40 Y = INT (R / 280):X = R - (Y * 280) > 50 IF Y < 192 THEN HPLOT X,Y > 60 NEXT : PRINT CHR$ (7): GET A$: TEXT > > > > Are there other more efficient methods for random number generation than ones mentioned here that I may have overlooked? > > Below is the RND function used in many of Datasoft's Apple/Atari/C64 games that were made in the late 80s. It's not the fastest PRNG, but it's pretty small, effective, and often fast enough. > > -JB > @JBrooksBSI > > > * DATASOFT RND 6502 > * BY JAMES GARON > * 10/02/86 > > RNDINIT > LDA #$AB > STA RNDSEED > LDA #$55 > STA RNDSEED+1 > LDA #$7E > STA RNDSEED+2 > RTS > > * RESULT IN ACC > RND LDA RNDSEED > ROL RNDSEED > EOR RNDSEED > ROR RNDSEED > INC RNDSEED+1 > BNE RND10 > LDA RNDSEED+2 > INC RNDSEED+2 > RND10 ADC RNDSEED+1 > BVC RND20 > INC RNDSEED+1 > BNE RND20 > LDA RNDSEED+2 > INC RNDSEED+2 > RND20 STA RNDSEED > RTS Smaller 12-byte version of the 16-bit shift-xor PRNG: 300:A5 4F 4A 66 4E 90 02 49 B4 85 4F 60 Returns $4E=RndL, $4F(& acc)=RndH -JB @JBrooksBSI
[toc] | [prev] | [next] | [standalone]
| From | John Brooks <jbrooks@blueshiftinc.com> |
|---|---|
| Date | 2018-09-07 18:11 -0700 |
| Message-ID | <5f960b86-8487-469a-ab16-c314f3cf93be@googlegroups.com> |
| In reply to | #4756 |
On Thursday, September 6, 2018 at 10:26:10 PM UTC-7, John Brooks wrote: > > I am looking for generators that are comparatively small in size, are quite fast in its algorythm and does a good job of filling the hi-res screen to white using the test program. > > For things like dissolves and crossfades where each value should be visited just once, my favorite is the 16-bit shift-xor prng which got heavy use in my AppleII and GS games: > > 300:46 4F 66 4E 90 06 A9 B4 45 4F 85 4F 60 > > Here's an example program which fills the screen randomly: > > 5 REM PRNG demo. J.Brooks 9/6/2018 > 10 HGR2 : HCOLOR= 3: POKE 79,1 > 20 FOR I = 0 TO 65535: CALL 768 > 30 R = PEEK (78) + PEEK (79) * 256 - 1 > 40 Y = INT (R / 280):X = R - (Y * 280) > 50 IF Y < 192 THEN HPLOT X,Y > 60 NEXT : PRINT CHR$ (7): GET A$: TEXT > > > > Are there other more efficient methods for random number generation than ones mentioned here that I may have overlooked? > > Below is the RND function used in many of Datasoft's Apple/Atari/C64 games that were made in the late 80s. It's not the fastest PRNG, but it's pretty small, effective, and often fast enough. > > -JB > @JBrooksBSI > > > * DATASOFT RND 6502 > * BY JAMES GARON > * 10/02/86 > > RNDINIT > LDA #$AB > STA RNDSEED > LDA #$55 > STA RNDSEED+1 > LDA #$7E > STA RNDSEED+2 > RTS > > * RESULT IN ACC > RND LDA RNDSEED > ROL RNDSEED > EOR RNDSEED > ROR RNDSEED > INC RNDSEED+1 > BNE RND10 > LDA RNDSEED+2 > INC RNDSEED+2 > RND10 ADC RNDSEED+1 > BVC RND20 > INC RNDSEED+1 > BNE RND20 > LDA RNDSEED+2 > INC RNDSEED+2 > RND20 STA RNDSEED > RTS Smaller 12-byte version of the 16-bit shift-xor PRNG: 300:A5 4F 4A 66 4E 90 02 49 B4 85 4F 60 Returns $4E=RndL, $4F(& acc)=RndH -JB @JBrooksBSI
[toc] | [prev] | [next] | [standalone]
| From | the.ertceps@gmail.com |
|---|---|
| Date | 2018-09-29 05:03 -0700 |
| Message-ID | <fbecc8a9-c5a1-4248-a578-77c6fbc77461@googlegroups.com> |
| In reply to | #2386 |
depending on what you're doing and how intensive it it, I read on a machine that had no practical way of producing random numbers, was to simply have it sit there count from 1-... and when you need a number you pull it out of the loop. In the original case it counted while waiting for input. But it could be adapted to other uses.
[toc] | [prev] | [next] | [standalone]
| From | James Davis <JPD.Enterprises@outlook.com> |
|---|---|
| Date | 2018-09-29 10:24 -0700 |
| Message-ID | <d924c2c5-1853-4111-b309-d94a597db6de@googlegroups.com> |
| In reply to | #4788 |
On Saturday, September 29, 2018 at 5:03:12 AM UTC-7, Anthony Adverse wrote: > depending on what you're doing and how intensive it it, I read on a machine that had no practical way of producing random numbers, was to simply have it sit there count from 1-... and when you need a number you pull it out of the loop. In the original case it counted while waiting for input. But it could be adapted to other uses. Doesn't something similar for generating random numbers occur in the Apple II monitor?
[toc] | [prev] | [next] | [standalone]
| From | Marco Verpelli <mverpelli@libero.it> |
|---|---|
| Date | 2018-09-29 10:30 -0700 |
| Message-ID | <501a2f57-19fd-4ddf-8888-f736a67f58a7@googlegroups.com> |
| In reply to | #4789 |
On Saturday, September 29, 2018 at 7:24:44 PM UTC+2, James Davis wrote: > On Saturday, September 29, 2018 at 5:03:12 AM UTC-7, Anthony Adverse wrote: > > depending on what you're doing and how intensive it it, I read on a machine that had no practical way of producing random numbers, was to simply have it sit there count from 1-... and when you need a number you pull it out of the loop. In the original case it counted while waiting for input. But it could be adapted to other uses. > > Doesn't something similar for generating random numbers occur in the Apple II monitor? A counter is incremented while waiting for a key pressed Marco
[toc] | [prev] | [next] | [standalone]
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
Back to top | Article view | comp.sys.apple2.programmer
csiph-web