English Amiga Board

English Amiga Board (http://eab.abime.net/index.php)
-   Coders. Asm / Hardware (http://eab.abime.net/forumdisplay.php?f=112)
-   -   Random numbers (http://eab.abime.net/showthread.php?t=104687)

sparhawk 15 November 2020 16:24

Random numbers
 
I was looking for some algorithm how to create random numbers. When I look at the glibc source, it looks extremly complicated and expensive. Another approach I became aware of was, to use a Murmur2 hash value. This works quite nice, but it also looks computationally expensive. From guts feeling I think it's not as expensive as the glibc code, but still. So I was wondering if there is some better approach which is also fast.


At least the Murmur2 code looks much easier to translate to asm, so if there is no better alternative I will take that one. As a nice side effect, I have then a hashing algorithm as well. :D

daxb 15 November 2020 17:11

If you search the Coders forum for "random" you get some threads that should give several solutions for fast and cheap random generators. There is also a long discussion I remember with code examples.

thomas 15 November 2020 17:15

I once looked at the algorithm used by C64 Basic. It's really simple: it takes the 32bit seed, EORs it by a large random number (probably a prime number) and orders the bytes backward.

The seed was then interpreted as a float and normalized to be between 0 and 1. But that's not necessary, you already get quite good results if you divide the seed by the desired range and use the remainder as result.

Something like this for random numbers between 1 and 6:

Code:

        move.l        seed,d0
        eor.l        #$87654321,d0
        swap.w        d0
        swap.l        d0
        swap.w        d0
        move.l        d0,seed
        divu        #6,d0
        swap.l        d0
        ext.l        d0
        addq.l        #1,d0

(I don't remember exactly, it might as well be ADD instead of EOR.)

sparhawk 15 November 2020 17:22

Thanks. :D I tried to search, but I didn't find much. Maybe the wrong search phrase.
That algorithm looks nice and simple. :)

jotd 15 November 2020 17:54

Code:

        ;;; EAB simple random generator

; thanks meynaf
 mulu #$a57b,d0
 addi.l #$bb40e62d,d0
 rol.l #6,d0


Wepl 15 November 2020 20:09

Code:

        move.l        seed,d0
        eor.l        #$87654321,d0
        swap.w        d0
        swap.l        d0
        swap.w        d0
        move.l        d0,seed
        divu        #6,d0
        swap.l        d0
        ext.l        d0
        addq.l        #1,d0

swap.w swap.l ??
there is only swap

Thomas Richter 15 November 2020 21:39

Quote:

Originally Posted by sparhawk (Post 1440977)
I was looking for some algorithm how to create random numbers.

Donald Knuth, "The Art of Programming", Vol. II: "Numerical and Semi-numerical algorithms". Contains everything you ever wanted to know about random generators and you never dared to ask.


The quick morale: Do not pick the algorithm to generate random numbers at random. In particular, do not accept "home made" algorithms. About the simplest random number generators are "linear congruence random generators", which use a multiply-add approach. Depending on the numbers you pick, the results are "ok".


Quote:

Originally Posted by sparhawk (Post 1440977)
When I look at the glibc source, it looks extremly complicated and expensive.

For a reason. Better quality requires more complexity. The linear congruence generators are not too good. A simple one is this one:


Code:

        saveregs a2/a6
        lea _Seed(a4),a2
        move.l (a2),d0
        move.l _UtilityBase(a4),a6
        move.l #1664525,d1      ;Knuth's algorithm
        jsr -$90(a6)            ;UMul
        add.l #1013904223,d0
        move.l d0,(a2)
        loadregs
        rts

[/QUOTE]
This is Knuth's linear congruence algorithm with a modulo value of 2^32. It is well researched and well understood. Do not exchange the multiplication with anything else, neither its constant.


Note that if you use the output of this algorithm: Always use data from the MSBs on, do not generate random numbers by "masking", as the LSBs have a much smaller period.

meynaf 15 November 2020 23:10

Quote:

Originally Posted by Thomas Richter (Post 1441064)
Note that if you use the output of this algorithm: Always use data from the MSBs on, do not generate random numbers by "masking", as the LSBs have a much smaller period.

There is another way to work around this shortcoming : just rotate the result.
This will not, however, fix the problem with the short period of the algorithm (for a 32-bit seed, it's in the thousands).

a/b 16 November 2020 10:06

1. short
2. fast
3. accurate
Pick two :P.

This is a quick&dirty one that works for me:
Code:

Init:        move.l        #<seed>,d7        ; large prime numbers
        move.l        #$6be7d35b,d6        ; are good...

Rng:        swap        d7
        add.l        d6,d7
        eor.l        d6,d7

It's based on this: https://en.wikipedia.org/wiki/Xorshift

Thomas Richter 16 November 2020 10:49

Quote:

Originally Posted by meynaf (Post 1441085)
There is another way to work around this shortcoming : just rotate the result.
This will not, however, fix the problem with the short period of the algorithm (for a 32-bit seed, it's in the thousands).

No. The period of a linear congruence random generator does not depend on the seed. It depends on the gcd of the modulo and the multiplier, here 2^32 and, well, the magic number in the code. This number here was not picked at random, so the period is really maximal. It is not in the thousands. Note, however, that this assumes that you pick bits from the MSB on. The period on the LSBs is small.

Thomas Richter 16 November 2020 10:50

Quote:

Originally Posted by a/b (Post 1441120)
1. short
2. fast
3. accurate
Pick two :P.

This is a quick&dirty one that works for me:
Code:

Init:    move.l    #<seed>,d7    ; large prime numbers
    move.l    #$6be7d35b,d6    ; are good...

Rng:    swap    d7
    add.l    d6,d7
    eor.l    d6,d7

It's based on this: https://en.wikipedia.org/wiki/Xorshift

Looks like snake oil to me. Is there anything documented about the properties of this generator.

a/b 16 November 2020 11:05

The one I posted? That one, as stated, works for me, to generate a few thousand random 16-bit numbers very quickly (6 bytes inline, 20 cycles on a 68000).
Xorshift? Yeah, there are many variants that pass the bigcrush tests. Look up xorshift and xoshiro.
But most importantly, read the first 4 lines (and pick two) :P. That's the point.

Thomas Richter 16 November 2020 11:45

The question is not "whether it works for you", but whether it is a good random generator and passes a couple of tests, for example the spectral test. See again Knuth II for a lot of tests and a lot of material on random generators, and in particular why home-made generators are not a good idea.

a/b 16 November 2020 12:22

moveq #oh-how-i-love-arguing-with-internet-strangers-about-nothing,d0
...
not.l d0

Again, you are missing the point. Taking a step back, xorshift is not some mumbo jumbo, and as i said it passes the bigcrush test which is a few hours long test.
Now, back to code I posted... You should stop looking at this from your point of view only, especially in a coders/asm forum.
- Original poster said, in a general manner, that he needs a fast algorithm but doesn't specify how fast is fast enough for his definition of fast in this fast moving thread.
- Apply 2-out-of-3 rule.
- Different people present different options.
0-1 choice
0-$ff better choice
0-$ffff betterer choice
0-$ffffffff bettererer choice
So what's the problem? Need better accuracy (*again*, 2-out-of-3 rule)?
1. pick a better seed/modifier
2. use shift/ror instead of a swap
3. use 2x32 bits
...
9. use the "full-blown" xorshift algorithm, which is still plenty fast, if you still like this type of rng
10. use something else that you like more or that works better in your, and unknown to us, scenario

sparhawk 16 November 2020 12:51

The numbers should be sufficiently random for a game. they don't need to hold against a scientific test. :) So in a game, speed is important, but I think if I have the choice between a bad generator and a little bit slower one, then I might take the slower one. If it starts to get a performance issue, then a less "random" algorithm might be acceptable. I thought of adding a few of them and then compare how the perform vs. how they "feel" regarding randomness.

meynaf 16 November 2020 15:38

Quote:

Originally Posted by Thomas Richter (Post 1441128)
No. The period of a linear congruence random generator does not depend on the seed. It depends on the gcd of the modulo and the multiplier, here 2^32 and, well, the magic number in the code. This number here was not picked at random, so the period is really maximal. It is not in the thousands. Note, however, that this assumes that you pick bits from the MSB on. The period on the LSBs is small.

Well ok, but this has a price : the period of the LSBs is very, very small (lower byte starts to repeat after 256 values !). May make it unsuitable, depending on the needs.

meynaf 16 November 2020 15:45

Quote:

Originally Posted by a/b (Post 1441152)
Taking a step back, xorshift is not some mumbo jumbo, and as i said it passes the bigcrush test which is a few hours long test.

Indeed xorshift is fast and passes many tests (not all : it fails linear complexity tests). While unsuitable for cryptography, for most applications it's more than enough.

Thomas Richter 16 November 2020 16:40

Quote:

Originally Posted by sparhawk (Post 1441156)
The numbers should be sufficiently random for a game. they don't need to hold against a scientific test.

I don't see how one contradicts the other. Depending on the type of game, and your needs for randomness, a good generator is absolutely necessary, and not a "scientific exercise" at all. Without knowing the game and your needs, one cannot give recommendations.

Rotareneg 16 November 2020 16:54

I suggest using RANDU just to irritate PRNG algorithm snobs. ;)

roondar 16 November 2020 17:25

Now I've been looking for a random number algorithm generator as well and it looks like something like xorshift would be good enough for my purpose. Assuming I'd use xorshift, what would be good initial seed (or state) values for 32 bit signed/unsiged random numbers?

See, to me it seems to me that getting the seed right is the critical part for using this type of algorithm properly.


All times are GMT +2. The time now is 02:47.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, vBulletin Solutions Inc.

Page generated in 0.05591 seconds with 11 queries