6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Nov 22, 2024 9:54 am

All times are UTC




Post new topic Reply to topic  [ 245 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6, 7 ... 17  Next
Author Message
PostPosted: Mon Mar 20, 2023 9:54 pm 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
Arlet wrote:
Here's my attempt at a random number generator optimized for 6502. An 8 bit random number is returned in A. It needs 7 bytes of RAM (preferably zero page), and has a period guaranteed to be at least 32 bits. It passes Dieharder and PractRand tests (up to at least 4GB of output).


I would imagine some starting seeds would go farther than others? What starting seed did you use to get the 4 GB output?


Top
 Profile  
Reply with quote  
PostPosted: Mon Mar 20, 2023 11:55 pm 
Offline

Joined: Mon Mar 13, 2023 9:38 pm
Posts: 80
Arlet wrote:
Alex1 wrote:
Is your algorithm based on math? What is the principle in this case? Or did you create randomly by trial and error?


A lot of trial and error, and then using the errors to refine my intuition. There's also some math involved, but I didn't realize that until it was already somewhat successful. Particularly, a chain of ADC instructions like this results in a maximum length permuted counter that will go through all possible states, but in a randomish order (provided that initial input is odd, and carry flag is cleared). The problem with just a simple chain of ADCs is that the lower order bits are quite regular, so I mixed in some EORs to try to break that pattern, and then used PractRand to see if it was successful.

The "magic" $45 constant input isn't very critical. Other odd values will work too.


Could you give us a vector test, the 50 first bytes with this seed ?

seed: .byte $CA,$7E,$67,$9F,$BC,$DE,$DA


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 21, 2023 5:46 am 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
IamRob wrote:
I would imagine some starting seeds would go farther than others? What starting seed did you use to get the 4 GB output?

I used all zeroes for testing.


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 21, 2023 5:49 am 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
With all zeroes, my output looks like this:
Code:
00000000  00 8a a8 73 86 ae 5f e0  ac 63 5d 97 47 42 4a c5  |...s.._..c].GBJ.|
00000010  40 64 e5 05 19 68 42 f1  d6 44 88 47 12 b8 63 3c  |@d...hB..D.G..c<|
00000020  72 84 75 ca 14 8f 28 9b  16 ef 62 b0 9a a6 74 64  |r.u...(...b...td|
00000030  84 3d 1a 30 03 e2 40 cd  49 3d 87 67 ec 86 ea 75  |.=.0..@.I=.g...u|

With $CA,$7E,$67,$9F,$BC,$DE,$DA as seed, I get:
Code:
00000000  cf d7 0e 50 ff 8e 84 05  6d 34 4f d6 1d 9a 2c 29  |...P....m4O...,)|
00000010  19 ca 52 38 83 ca f6 ad  15 7a 36 e9 fb ea bf b6  |..R8.....z6.....|
00000020  9a 4e 13 63 f4 87 0e ee  40 74 0e 78 b4 e5 78 94  |.N.c....@t.x..x.|
00000030  93 25 8a be 89 56 19 09  b5 14 7b 5f 16 3f a6 2e  |.%...V....{_.?..|


(Fixed)


Last edited by Arlet on Tue Mar 21, 2023 3:36 pm, edited 2 times in total.

Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 21, 2023 2:19 pm 
Offline

Joined: Mon Mar 13, 2023 9:38 pm
Posts: 80
Arlet, i've not the same results with seed: .byte $00,$00,$00,$00,$00,$00,$00
How do you create the next byte? do you call the first line $100D for each new byte ?

Here is my code first byte:

Attachment:
Sélection_011.png
Sélection_011.png [ 12.56 KiB | Viewed 2683 times ]


Attachment:
Sélection_012.png
Sélection_012.png [ 6 KiB | Viewed 2683 times ]


Second byte:

Attachment:
Sélection_013.png
Sélection_013.png [ 4.87 KiB | Viewed 2683 times ]


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 21, 2023 3:29 pm 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
Oops. I see that something went wrong in my test code. I used some C macros to emulate the ADC instruction, and didn't use enough parentheses.

Unfortunately, there's no easy way to fix the 6502 code to do the same.

Fortunately, even though my output was all wrong, the actual 6502 code was working fine for the intended purpose. I have fixed my emulation, and the random number output still passes PractRand (up to 16 GB right now, and still going).


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 21, 2023 3:42 pm 
Offline

Joined: Mon Mar 13, 2023 9:38 pm
Posts: 80
Arlet wrote:
Oops. I see that something went wrong in my test code. I used some C macros to emulate the ADC instruction, and didn't use enough parentheses.

Unfortunately, there's no easy way to fix the 6502 code to do the same.

Fortunately, even though my output was all wrong, the actual 6502 code was working fine for the intended purpose. I have fixed my emulation, and the random number output still passes PractRand (up to 16 GB right now, and still going).


Can you paste your C code ?


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 21, 2023 3:50 pm 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
Code:
#define ADD( a, b )                 \
    do {                            \
        x = a + (b);                \
        a = x;                      \
    } while (0)

#define ADC( a, b )                 \
    do {                            \
        x = a + (b) + (x >> 8) % 2; \
        a = x;                      \
    } while (0)

    uint16_t x;

    while( 1 )
    {
        ADD( s0, 0x45 );
        ADC( s1, s0 );
        ADC( s2, s1 );
        ADC( s3, s2 );
        ADC( s4, s3 ^ s6 );
        ADC( s5, s4 );
        ADC( s6, s5 );
        putchar( s6 ^ s4 );
    }


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 21, 2023 3:52 pm 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
PractRand fails hard after 64 GB, but that's not really a huge surprise given that the guaranteed period is only 4GB. Good enough for 6502 work.
Code:
rng=RNG_stdin, seed=unknown
length= 16 gigabytes (2^34 bytes), time= 255 seconds
  no anomalies in 315 test result(s)

rng=RNG_stdin, seed=unknown
length= 32 gigabytes (2^35 bytes), time= 495 seconds
  Test Name                         Raw       Processed     Evaluation
  [Low1/8]Gap-16:B                  R=  +5.9  p =  6.2e-5   mildly suspicious
  ...and 327 test result(s) without anomalies

rng=RNG_stdin, seed=unknown
length= 64 gigabytes (2^36 bytes), time= 982 seconds
  Test Name                         Raw       Processed     Evaluation
  BCFN(2+0,13-0,T)                  R= +92.2  p =  7.6e-49    FAIL !!!!     
  BCFN(2+1,13-0,T)                  R=+105.0  p =  1.0e-55    FAIL !!!!     
  BCFN(2+2,13-0,T)                  R= +97.2  p =  1.6e-51    FAIL !!!! 
....(many more fails)...


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 21, 2023 3:55 pm 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
By the way, I have fixed the test vectors above.


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 21, 2023 4:23 pm 
Offline

Joined: Fri Jul 09, 2021 10:12 pm
Posts: 741
Arlet wrote:
Code:
#define ADD( a, b )                 \
    do {                            \
        x = a + (b);                \
        a = x;                      \
    } while (0)

#define ADC( a, b )                 \
    do {                            \
        x = a + (b) + (x >> 8) % 2; \
        a = x;                      \
    } while (0)

Is it guarranteed that 'a' and 'b' are only 8 bits wide? You didn't include the definitions of s0..s6. The truncation is important though because if 'a' could store more than 8 bits, then a future add operation might pick up the extra bit and feed it into the carry calculation.


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 21, 2023 4:24 pm 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
Quote:
Is it guarranteed that 'a' and 'b' are only 8 bits wide? You didn't include the definitions of s0..s6. The truncation is important though because if 'a' could store more than 8 bits, then a future add operation might pick up the extra bit and feed it into the carry calculation.


Yes. All s0..s6 variables are declared as uint8_t type.

By the way, in case it wasn't clear, the code has been fixed. The problem was the missing parentheses around the 'b' in the macro. Everything works now, and the original 6502 code is still good.


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 21, 2023 4:39 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10985
Location: England
Arlet wrote:
Here's my attempt at a random number generator optimized for 6502. An 8 bit random number is returned in A. It needs 7 bytes of RAM (preferably zero page), and has a period guaranteed to be at least 32 bits. It passes Dieharder and PractRand tests (up to at least 4GB of output).

I find this quite intriguing! I ported it to BBC Basic so I could easily see how the state vector evolves (especially with numbers other than 0x45)
Code:
   10 DIM seed 8: !seed=0: !(seed+4)=0
   20 DIM c 99: P%=c
   30 [ OPT 0
   40 CLC
   50 LDA #&45
   60 ADC seed+0: STA seed+0
   70 ADC seed+1: STA seed+1
   80 ADC seed+2: STA seed+2
   90 ADC seed+3: STA seed+3: EOR seed+6
  100 ADC seed+4: STA seed+4
  110 ADC seed+5: STA seed+5
  120 ADC seed+6: STA seed+6: EOR seed+4
  130 RTS
  140 ]
  150 FOR i=1 TO 20
  160 A%=255 AND USRc
  170 PRINT~A%,~!(seed+4),~!seed
  180 NEXT
>
>RUN
         0    454545  45454545
        8A    EEA964  5A14CF8A
        A8    E0F248   DB39ECF
        73    AFCEDC  7466B314
        86    A2F324  E7730C59
        AE    62BFCC   51DAA9E
        5F    C15E9E  B0AB8DE3
        E0    92D172  1261B628
        AC    DB4877  9785236D
        63    C3E8A0  F25AD5B2
        5D    27637A  1A27CCF7
        97    7149E6  4B31093C
        47    19A85E   6BB8A81
        42    2A1068  130C50C6
        4A    F3C9B9  7B685C0B
        C5    D9E61C  9014AC50
        40    1B415B  E6564195
        64    FBE09F  58721BDA
        E5    7B7F9E   5AD3B1F
         5    C246C7  524C9F64
>



If we change 0x45 to 0x01 it's not too hard to follow the first round or two
Code:
RUN
         0     10101   1010101
         2     70605   5040302
        17    1A130D   F0A0603
        35    735946  23140A04


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 21, 2023 5:04 pm 
Offline

Joined: Mon Mar 13, 2023 9:38 pm
Posts: 80
Here is the detailed code for educational purpose.

Quote:
// ARLET RANDOM C CODE
#include <stdint.h>
#include <stdio.h>
void main()
{

// uint8_t seed[7]={0xca,0x7e,0x67,0x9f,0xbc,0xde,0xda}, rndbyte, carry;
uint8_t seed[7]={0,0,0,0,0,0,0}, rndbyte, carry;
unsigned long i,z;
z=0xffffffff;


for (i=0;i<20;i++)
{
carry=0;
rndbyte=0x45;
if ((rndbyte+seed[0])>255) {carry=1;} else {carry=0;}
rndbyte=(rndbyte+seed[0]);
seed[0]=rndbyte;
rndbyte=(rndbyte+carry);

if ((rndbyte+seed[1])>255) {carry=1;} else {carry=0;}
rndbyte=(rndbyte+seed[1]);
seed[1]=rndbyte;
rndbyte=(rndbyte+carry);

if ((rndbyte+seed[2])>255) {carry=1;} else {carry=0;}
rndbyte=(rndbyte+seed[2]);
seed[2]=rndbyte;
rndbyte=(rndbyte+carry);

if ((rndbyte+seed[3])>255) {carry=1;} else {carry=0;}
rndbyte=(rndbyte+seed[3]);
seed[3]=rndbyte;

rndbyte=(rndbyte^seed[6]);
rndbyte=(rndbyte+carry);

if ((rndbyte+seed[4])>255) {carry=1;} else {carry=0;}
rndbyte=(rndbyte+seed[4]);
seed[4]=rndbyte;
rndbyte=(rndbyte+carry);

if ((rndbyte+seed[5])>255) {carry=1;} else {carry=0;}
rndbyte=(rndbyte+seed[5]);
seed[5]=rndbyte;
rndbyte=(rndbyte+carry);

if ((rndbyte+seed[6])>255) {carry=1;} else {carry=0;}
rndbyte=(rndbyte+seed[6]);
seed[6]=rndbyte;

rndbyte=(rndbyte^seed[4]);

printf("%0.2X %0.2X %0.2X %0.2X %0.2X %0.2X %0.2X = %0.2X\n", seed[0], seed[1], seed[2], seed[3], seed[4], seed[5], seed[6], rndbyte);
// printf("%0.2X ",rndbyte);

}


}



Attachment:
Sélection_014.png
Sélection_014.png [ 13.52 KiB | Viewed 2666 times ]


Last edited by Alex1 on Tue Mar 21, 2023 6:07 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 21, 2023 5:10 pm 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
Quote:
so I could easily see how the state vector evolves (especially with numbers other than 0x45)

If you have a real random source, you could remove the LDA #$45 line, and just call the subroutine with a value in A. Even if it's a mediocre source of randomness, once it makes its way through the state machine, it will be pretty good. Just make sure you get a regular supply of odd numbers in there, or set bit 0 yourself.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 245 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6, 7 ... 17  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 13 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: