Thread: Seeded/Seedless random number

  1. #1
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733

    Seeded/Seedless random number

    Just occurred to me a brilliant way to grab random values, I've tested a few times just now and it seems to be a usable option even for security, at least to me anyways:
    Code:
    #include <limits.h>
    #include <malloc.h>
    #include <time.h>
    
    long mcc_rnd( long *seed, long min, long max ) {
    	unsigned char *tmp = malloc(1);
    	/* Initial ranom value */
    	long val = time(NULL) + ((ptrdiff_t)tmp), _seed = 1;
    	if ( !seed ) seed = &seed;
    	if ( *seed == 0 ) *seed = 1;
    	/* Counter possible divide by 0 situation */
    	val %= *seed;
    	val *= clock();
    	free(tmp);
    	*seed <<= 1;
    	return (val > max) ? max : (val < min ? min : val);
    }
    
    int main() {
    	int i;
    	long seed = 1;
    	for ( i = 0; i < 100; ++i ) {
    		(void)printf( "%ld\n", mcc_rnd( &seed, LONG_MIN,LONG_MAX) );
    	}
    }
    A real program will no doubt call malloc & co often providing a greater randomness than already provided, the time() and clock() calls help randomize in between those calls and the seed is for utilizing a change in magnitude while min & max are there to restrain the result
    Go ahead and give it a try with and without a seed

  2. #2
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Noticed a bug, fixed it, turned out to be a feature instead so fixed back and removed the un-needed variable and changed types
    Code:
    typedef ptrdiff_t mcc_rnd_t;
    long mcc_rnd( mcc_rnd_t *seed, long min, long max ) {
    	unsigned char *tmp = malloc(1);
    	/* Initial random value */
    	long val = time(NULL) + ((ptrdiff_t)tmp);
    	if ( !seed ) seed = (mcc_rnd_t*)(&seed);
    	if ( *seed == 0 ) *seed = 1;
    	val %= *seed;
    	val *= clock();
    	free(tmp);
    	*seed <<= 1;
    	return (val > max) ? max : (val < min ? min : val);
    }

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    ptrdiff_t is a signed integer type, and left shifts on signed integers result in undefined behaviour if the value is negative or if the result cannot be represented. Besides a ptrdiff_t doesn't make much sense here since no pointer subtraction is used. An unsigned int as in srand might be simpler.

    time_t isn't guaranteed to be an integer, but we admittedly often use it as such in example/toy programs by providing srand with the result of time(). One idea I've seen (by forum member Prelude) is to hash the bytes of a time_t. You could easily do this while mixing in the (bytes of the) pointer from malloc, resulting in a portable solution.

    I wonder if there's a point exposing the use of a seed in the interface though: you're trying to implement a RNG, not a PRNG, and although the use of a seed for a PRNG is often associated with making the random sequences differ on each run, that could be abstracted away, but isn't because there's value in allowing the seed to be specified: so that we can get the same pseudorandom sequence on each run, hence allowing for things like repeatable simulations, whereas with a RNG we would have to save the entire random sequence in order to replay it.

    I'd definitely be concerned about using this as a secure RNG before you've run any proper tests and attacks on it: even seasoned security folks have been wrong about what they thought would be a sufficiently random source.
    Last edited by laserlight; 01-09-2020 at 07:18 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by laserlight View Post
    ptrdiff_t is a signed integer type, and left shifts on signed integers result in undefined behaviour if the value is negative or if the result cannot be represented. Besides a ptrdiff_t doesn't make much sense here since no pointer subtraction is used. An unsigned int as in srand might be simpler.

    time_t isn't guaranteed to be an integer, but we admittedly often use it as such in example/toy programs by providing srand with the result of time(). One idea I've seen (by forum member Prelude) is to hash the bytes of a time_t. You could easily do this while mixing in the (bytes of the) pointer from malloc, resulting in a portable solution.

    I wonder if there's a point exposing the use of a seed in the interface though: you're trying to implement a RNG, not a PRNG, and although the use of a seed for a PRNG is often associated with making the random sequences differ on each run, that could be abstracted away, but isn't because there's value in allowing the seed to be specified: so that we can get the same pseudorandom sequence on each run, hence allowing for things like repeatable simulations, whereas with a RNG we would have to save the entire random sequence in order to replay it.

    I'd definitely be concerned about using this as a secure RNG before you've run any proper tests and attacks on it: even seasoned security folks have been wrong about what they thought would be a sufficiently random source.
    "undefined behaviour" "random" wonder what those two have in common? also the seed is an option, actually runs better without (when NULL is given), I've already tested this myself and advise you to test it also before you post again, (I did multiple runs just to see if the numbers where consistent or not)

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by awsdert
    "undefined behaviour" "random" wonder what those two have in common?
    One can result in a compile error, segmentation fault, or some other strange result; the other won't. That said, while bit shifting with unsigned integers such that it overflows is well defined, and conversions to unsigned integers is well defined too, multiplication even with unsigned integers technically results in undefined behaviour if the result is out of range... but for the most part people don't care since that one will practically result in the same thing as if it were a conversion for pretty much all implementations.

    Another nice side effect of hashing is that it likely results in a better random mix of bits than simple addition.

    Quote Originally Posted by awsdert
    also the seed is an option, actually runs better without (when NULL is given)
    Exactly: why provide it as an option then? You're making it harder to use well because people will be more likely to mistake this for a PRNG and provide their own seed when it is completely unnecessary for a RNG like this. Or worse still, they might expect repeatable pseudorandom sequences when this won't work since this is not a PRNG.

    Quote Originally Posted by awsdert
    I've already tested this myself and advise you to test it also before you post again (I did multiple runs just to see if the numbers where consistent or not)
    I'm afraid that I don't have the necessary knowledge to run proper tests on this. Have you actually properly tested it? It looks like all you did was run it in a loop and eyeball the result, which unfortunately doesn't count as a proper test of randomness as humans tend to be pretty bad at guessing what's random and what's not from just looking. But because you're using things like addresses allocated and clock() it should be random; the question is whether your choices and the combination of these random sources does produce enough entropy for secure applications.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Quote Originally Posted by awsdert View Post
    "undefined behaviour" "random" wonder what those two have in common? also the seed is an option, actually runs better without (when NULL is given), I've already tested this myself and advise you to test it also before you post again, (I did multiple runs just to see if the numbers where consistent or not)
    But, are they random enough to call random when the code is compiled under other OSes or even with other Compilers?

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > Just occurred to me a brilliant way to grab random values,
    You sound like a noob who just "discovered" bubble sorting and thinks it's the most awesome thing they've ever seen.

    > I've tested a few times just now and it seems to be a usable option even for security, at least to me anyways:
    I wouldn't use this for a student dice rolling program, never mind for any serious statistical or security application.
    The algorithm (such as it is), is painfully slow as well as being singularly useless.

    Diehard tests - Wikipedia

    On my machine, malloc() returns the same pointer every time, and time() is a constant.
    clock() is barely able to do any better than being an incrementing counter.

    Code:
    #include<stdio.h>
    #include<time.h>
    #include<stdlib.h>
    #include<stddef.h>
    #include<limits.h>
    
    typedef ptrdiff_t mcc_rnd_t;
    long mcc_rnd( mcc_rnd_t *seed, long min, long max ) {
        unsigned char *tmp = malloc(1);
        /* Initial random value */
        long val = time(NULL) + ((ptrdiff_t)tmp);
        if ( !seed ) seed = (mcc_rnd_t*)(&seed);
        if ( *seed == 0 ) *seed = 1;
        val %= *seed;
        val *= clock();
        free(tmp);
        *seed <<= 1;
        return (val > max) ? max : (val < min ? min : val);
    }
    
    void t1() {
        printf("100 Clocks()\n");
        long tests[100];
        for ( int i = 0; i < 100; ++i ) {
            tests[i] = clock();
        }
        for ( int i = 0; i < 100; ++i ) {
            (void)printf( "%ld\n", tests[i] );
        }
    }
    
    void t2() {
        printf("100 times()\n");
        long tests[100];
        for ( int i = 0; i < 100; ++i ) {
            tests[i] = time(NULL);
        }
        for ( int i = 0; i < 100; ++i ) {
            (void)printf( "%ld\n", tests[i] );
        }
    }
    
    void t3() {
        printf("100 pointers()\n");
        void *tests[100];
        for ( int i = 0; i < 100; ++i ) {
            tests[i] = malloc(1);
            free(tests[i]);
        }
        for ( int i = 0; i < 100; ++i ) {
            (void)printf( "%p\n", tests[i] );
        }
    }
    
    int main() {
        int i;
        long seed = 1;
        long tests[100];
        t1();
        t2();
        t3();
        for ( i = 0; i < 100; ++i ) {
            tests[i] = mcc_rnd( &seed, LONG_MIN,LONG_MAX);
        }
        for ( i = 0; i < 100; ++i ) {
            (void)printf( "%ld\n", tests[i] );
        }
        int dice[6] = { 0 };
        for ( int i = 0 ; i < 60000000 ; i++ ) {
          int d = mcc_rnd( &seed, LONG_MIN,LONG_MAX) % 6;
          dice[d]++;
        }
        for ( int i = 0 ; i < 6 ; i++ ) {
          printf("%d: %d\n", i, dice[i]);
        }
    }
    Your 'distribution' is awful. Your online casino operator is now suing you.
    Code:
    0: 25929392
    1: 3481475
    2: 9589231
    3: 7932192
    4: 9587561
    5: 3480149
    
    real	0m21.880s
    user	0m7.460s
    sys	0m14.416s
    Compare with calling rand() millions of times.
    Much better, and MUCH quicker!.
    Code:
    0: 9998142
    1: 9999581
    2: 10000326
    3: 10003300
    4: 9997641
    5: 10001010
    
    real	0m0.600s
    user	0m0.596s
    sys	0m0.000s
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by Salem View Post
    > Just occurred to me a brilliant way to grab random values,
    You sound like a noob who just "discovered" bubble sorting and thinks it's the most awesome thing they've ever seen.

    > I've tested a few times just now and it seems to be a usable option even for security, at least to me anyways:
    I wouldn't use this for a student dice rolling program, never mind for any serious statistical or security application.
    The algorithm (such as it is), is painfully slow as well as being singularly useless.

    Diehard tests - Wikipedia

    On my machine, malloc() returns the same pointer every time, and time() is a constant.
    clock() is barely able to do any better than being an incrementing counter.

    Code:
    #include<stdio.h>
    #include<time.h>
    #include<stdlib.h>
    #include<stddef.h>
    #include<limits.h>
    
    typedef ptrdiff_t mcc_rnd_t;
    long mcc_rnd( mcc_rnd_t *seed, long min, long max ) {
        unsigned char *tmp = malloc(1);
        /* Initial random value */
        long val = time(NULL) + ((ptrdiff_t)tmp);
        if ( !seed ) seed = (mcc_rnd_t*)(&seed);
        if ( *seed == 0 ) *seed = 1;
        val %= *seed;
        val *= clock();
        free(tmp);
        *seed <<= 1;
        return (val > max) ? max : (val < min ? min : val);
    }
    
    void t1() {
        printf("100 Clocks()\n");
        long tests[100];
        for ( int i = 0; i < 100; ++i ) {
            tests[i] = clock();
        }
        for ( int i = 0; i < 100; ++i ) {
            (void)printf( "%ld\n", tests[i] );
        }
    }
    
    void t2() {
        printf("100 times()\n");
        long tests[100];
        for ( int i = 0; i < 100; ++i ) {
            tests[i] = time(NULL);
        }
        for ( int i = 0; i < 100; ++i ) {
            (void)printf( "%ld\n", tests[i] );
        }
    }
    
    void t3() {
        printf("100 pointers()\n");
        void *tests[100];
        for ( int i = 0; i < 100; ++i ) {
            tests[i] = malloc(1);
            free(tests[i]);
        }
        for ( int i = 0; i < 100; ++i ) {
            (void)printf( "%p\n", tests[i] );
        }
    }
    
    int main() {
        int i;
        long seed = 1;
        long tests[100];
        t1();
        t2();
        t3();
        for ( i = 0; i < 100; ++i ) {
            tests[i] = mcc_rnd( &seed, LONG_MIN,LONG_MAX);
        }
        for ( i = 0; i < 100; ++i ) {
            (void)printf( "%ld\n", tests[i] );
        }
        int dice[6] = { 0 };
        for ( int i = 0 ; i < 60000000 ; i++ ) {
          int d = mcc_rnd( &seed, LONG_MIN,LONG_MAX) % 6;
          dice[d]++;
        }
        for ( int i = 0 ; i < 6 ; i++ ) {
          printf("%d: %d\n", i, dice[i]);
        }
    }
    Your 'distribution' is awful. Your online casino operator is now suing you.
    Code:
    0: 25929392
    1: 3481475
    2: 9589231
    3: 7932192
    4: 9587561
    5: 3480149
    
    real	0m21.880s
    user	0m7.460s
    sys	0m14.416s
    Compare with calling rand() millions of times.
    Much better, and MUCH quicker!.
    Code:
    0: 9998142
    1: 9999581
    2: 10000326
    3: 10003300
    4: 9997641
    5: 10001010
    
    real	0m0.600s
    user	0m0.596s
    sys	0m0.000s
    Maybe be slower but it does it's job, and you've been corrected on the randomness:
    Code:
    #include<stdio.h>
    #include<time.h>
    #include<stdlib.h>
    #include<stddef.h>
    #include<limits.h>
    #define PER_LOOP 30
    #define DIE_ROLL 600000
    typedef ptrdiff_t mcc_rnd_t;
    ulong mcc__rnd( mcc_rnd_t *seed ) {
    	unsigned char *tmp = malloc(1);
    	/* Initial random value */
    	ulong val = (time(NULL) + ((ptrdiff_t)tmp));
    	if ( seed ) {
    		if ( *seed == 0 ) *seed = 1;
    		val %= *seed;
    		*seed <<= 1;
    	}
    	val *= clock();
    	free(tmp);
    	return val;
    }
    long mcc_rnd( mcc_rnd_t *seed, long min, long max ) {
    	unsigned char *tmp = malloc(1);
    	/* Initial random value */
    	long val = time(NULL) + ((ptrdiff_t)tmp);
    	if ( seed ) {
    		if ( *seed == 0 ) *seed = 1;
    		val %= *seed;
    		*seed <<= 1;
    	}
    	val *= clock();
    	free(tmp);
    	return (val > max) ? max : (val < min ? min : val);
    }
    
    void t( char *name, long (*func)() ) {
    	printf("%d %s()\n",PER_LOOP,name);
    	long tests[PER_LOOP];
    	for ( int i = 0; i < PER_LOOP; ++i ) {
    		tests[i] = func();
    	}
    	for ( int i = 0; i < PER_LOOP; ++i ) {
    		(void)printf( "%ld\n", tests[i] );
    	}
    }
    
    long t_time() { return (long)time(NULL); }
    long t_clock() { return (long)clock(); }
    long t_malloc() {
    	void *tmp = malloc(1);
    	free(tmp);
    	return (long)tmp;
    }
    long t_mcc_rnd() { return (long)mcc_rnd(NULL,LONG_MIN,LONG_MAX); }
    long t_mcc__rnd() { return (long)mcc__rnd(NULL); }
    
    void t1() {	t("time",t_time); }
    void t2() { t("clock",t_clock); }
    void t3() { t("malloc",t_malloc); }
    void t4() { t("mcc_rnd",t_mcc_rnd); }
    void t5() { t("mcc__rnd",t_mcc__rnd); }
     
    int main() {
    	long seed = 1;
    	t1(); t2(); t3(); t4(); t5();
    	printf("%d dice rolls mcc_rnd(seed)\n",DIE_ROLL);
    	int dice[6] = { 0 };
    	for ( int i = 0 ; i < DIE_ROLL; i++ ) {
    		int d = mcc_rnd( &seed, 0, 5 );
    		dice[d]++;
    	}
    	for ( int i = 0 ; i < 6 ; i++ ) {
    		printf("%d: %d\n", i, dice[i]);
    	}
    	printf("%d dice rolls mcc__rnd(seed)\n",DIE_ROLL);
    	for ( int i = 0 ; i < DIE_ROLL; i++ ) {
    		int d = mcc__rnd( &seed ) % 6;
    		dice[d]++;
    	}
    	for ( int i = 0 ; i < 6 ; i++ ) {
    		printf("%d: %d\n", i, dice[i]);
    	}
    	printf("%d dice rolls mcc_rnd(NULL)\n",DIE_ROLL);
    	for ( int i = 0 ; i < DIE_ROLL; i++ ) {
    		int d = mcc_rnd( NULL, 0, 5 );
    		dice[d]++;
    	}
    	for ( int i = 0 ; i < 6 ; i++ ) {
    		printf("%d: %d\n", i, dice[i]);
    	}
    	printf("%d dice rolls mcc__rnd(NULL)\n",DIE_ROLL);
    	for ( int i = 0 ; i < DIE_ROLL; i++ ) {
    		int d = mcc__rnd( NULL ) % 6;
    		dice[d]++;
    	}
    	for ( int i = 0 ; i < 6 ; i++ ) {
    		printf("%d: %d\n", i, dice[i]);
    	}
    	return 0;
    }
    Code:
    make --no-print-directory rnd
    gcc -ggdb -Wall -lpthread -o ./mcc_rnd.elf mcc_rnd.c
    ./mcc_rnd.elf
    30 time()
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    1578648723
    30 clock()
    754
    755
    756
    757
    757
    758
    759
    759
    760
    760
    761
    762
    762
    763
    764
    764
    765
    766
    766
    767
    768
    768
    769
    770
    770
    771
    772
    772
    773
    774
    30 malloc()
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    94681744093872
    30 mcc_rnd()
    74705141643907455
    74799824966650050
    74894508289392645
    74989191612135240
    74989191612135240
    75083874934877835
    75178558257620430
    75273241580363025
    75273241580363025
    75367924903105620
    75462608225848215
    75462608225848215
    75557291548590810
    75651974871333405
    75746658194076000
    75746658194076000
    75841341516818595
    75936024839561190
    75936024839561190
    76030708162303785
    76125391485046380
    76220074807788975
    76220074807788975
    76314758130531570
    76409441453274165
    76409441453274165
    76504124776016760
    76598808098759355
    76693491421501950
    76693491421501950
    30 mcc__rnd()
    77450958003442710
    77545641326185305
    77640324648927900
    77735007971670495
    77735007971670495
    77829691294413090
    77924374617155685
    77924374617155685
    78019057939898280
    78113741262640875
    78208424585383470
    78208424585383470
    78303107908126065
    78397791230868660
    78397791230868660
    78492474553611255
    78587157876353850
    78681841199096445
    78681841199096445
    78776524521839040
    78871207844581635
    78871207844581635
    78965891167324230
    79060574490066825
    79060574490066825
    79155257812809420
    79249941135552015
    79344624458294610
    79344624458294610
    79439307781037205
    600000 dice rolls mcc_rnd(seed)
    0: 74556
    1: 0
    2: 0
    3: 0
    4: 0
    5: 525444
    600000 dice rolls mcc__rnd(seed)
    0: 219695
    1: 97168
    2: 62456
    3: 135375
    4: 97256
    5: 588050
    600000 dice rolls mcc_rnd(NULL)
    0: 499668
    1: 97168
    2: 62456
    3: 135375
    4: 97256
    5: 908077
    600000 dice rolls mcc__rnd(NULL)
    0: 699594
    1: 97168
    2: 262438
    3: 135375
    4: 297348
    5: 908077
    Compilation finished successfully.

  9. #9
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by awsdert View Post
    A real program will no doubt call malloc & co often providing a greater randomness than already provided, the time() and clock() calls help randomize in between those calls
    Btw salem did you read this bit?

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Both mcc_rnd and mcc__rnd appear to be generating successive duplicates. That's weird: I would have thought that even if clock() didn't result in a different random number, at the very least seed doing the job of internal state would have done the trick.

    That said, Salem's right about the low entropy of time() and malloc(), as you have observed, and with its continuously increasing value clock() only fares a little better.

    Quote Originally Posted by awsdert
    Btw salem did you read this bit?
    Simulations requiring the use of a RNG or PRNG may not necessarily do intermediate memory allocations, e.g., it may be more efficient to allocate once then reuse the memory. A related issue is that the addresses allocated might not differ significantly, i.e. the entropy would be low.
    Last edited by laserlight; 01-10-2020 at 03:55 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Didn't like that I saw frequent doubles so I tried to find another way, I succeeded, gets its pointer from the stack instead now so malloc is no longer needed providing a speed up, although security applications should really sacrifice the time and put it in anyways to reduce chances of calculating to bare minimum.
    Code:
    #include<stdio.h>
    #include<time.h>
    #include<stdlib.h>
    #include<stddef.h>
    #include<limits.h>
    #define PER_LOOP 15
    #define DIE_ROLL 60000
    typedef ptrdiff_t mcc_rnd_t;
    ulong mcc__rnd( mcc_rnd_t *seed ) {
    	/* Initial random value */
    	ulong val = (ulong)(&seed) * (ulong)clock() * (ulong)clock();
    	if ( seed ) {
    		if ( *seed == 0 ) *seed = 1;
    		val %= *seed;
    		*seed <<= 1;
    	}
    	return val;
    }
    long mcc_rnd( mcc_rnd_t *seed, long min, long max ) {
    	/* Initial random value */
    	long val = (ulong)(&seed) * (ulong)clock();
    	if ( seed ) {
    		if ( *seed == 0 ) *seed = 1;
    		val %= *seed;
    		*seed <<= 1;
    	}
    	if ( val > max ) return (max != 0) ? val % max : 0;
    	if ( val < min ) return (min != 0) ? val % min : 0;
    	return val;
    }
    
    void t( char *name, long (*func)() ) {
    	printf("%d %s()\n",PER_LOOP,name);
    	long tests[PER_LOOP];
    	for ( int i = 0; i < PER_LOOP; ++i ) {
    		tests[i] = func();
    	}
    	for ( int i = 0; i < PER_LOOP; ++i ) {
    		(void)printf( "%ld\n", tests[i] );
    	}
    }
    
    long t_time() { return (long)time(NULL); }
    long t_clock() { return (long)clock(); }
    long t_malloc() {
    	void *tmp = malloc(1);
    	free(tmp);
    	return (long)tmp;
    }
    long t_mcc_rnd() { return (long)mcc_rnd(NULL,LONG_MIN,LONG_MAX); }
    long t_mcc__rnd() { return (long)mcc__rnd(NULL); }
    
    void t1() {	t("time",t_time); }
    void t2() { t("clock",t_clock); }
    void t3() { t("malloc",t_malloc); }
    void t4() { t("mcc_rnd",t_mcc_rnd); }
    void t5() { t("mcc__rnd",t_mcc__rnd); }
     
    int main() {
    	long seed = 1;
    	t1(); t2(); t3(); t4(); t5();
    	printf("%d dice rolls mcc_rnd(seed)\n",DIE_ROLL);
    	int dice[6] = { 0 };
    	for ( int i = 0 ; i < DIE_ROLL; i++ ) {
    		int d = mcc_rnd( &seed, 0, 5 );
    		dice[d]++;
    	}
    	for ( int i = 0 ; i < 6 ; i++ ) {
    		printf("%d: %d\n", i, dice[i]);
    	}
    	printf("%d dice rolls mcc__rnd(seed)\n",DIE_ROLL);
    	for ( int i = 0 ; i < DIE_ROLL; i++ ) {
    		int d = mcc__rnd( &seed ) % 6;
    		dice[d]++;
    	}
    	for ( int i = 0 ; i < 6 ; i++ ) {
    		printf("%d: %d\n", i, dice[i]);
    	}
    	printf("%d dice rolls mcc_rnd(NULL)\n",DIE_ROLL);
    	for ( int i = 0 ; i < DIE_ROLL; i++ ) {
    		int d = mcc_rnd( NULL, 0, 5 );
    		dice[d]++;
    	}
    	for ( int i = 0 ; i < 6 ; i++ ) {
    		printf("%d: %d\n", i, dice[i]);
    	}
    	printf("%d dice rolls mcc__rnd(NULL)\n",DIE_ROLL);
    	for ( int i = 0 ; i < DIE_ROLL; i++ ) {
    		int d = mcc__rnd( NULL ) % 6;
    		dice[d]++;
    	}
    	for ( int i = 0 ; i < 6 ; i++ ) {
    		printf("%d: %d\n", i, dice[i]);
    	}
    	return 0;
    }
    Had to use stack pointer to get huge values, using clock just once gave me quick repeats while using it twice gave the randomness so that's as fast as the functions can get
    Edit: Forgot to add my output
    Code:
    make --no-print-directory rnd (in directory: /mnt/DATA/github/mc)
    ./mcc_rnd.elf
    15 time()
    1578651387
    1578651387
    1578651387
    1578651387
    1578651387
    1578651387
    1578651387
    1578651387
    1578651387
    1578651387
    1578651387
    1578651387
    1578651387
    1578651387
    1578651387
    15 clock()
    1418
    1422
    1423
    1425
    1427
    1428
    1429
    1431
    1432
    1434
    1435
    1437
    1438
    1440
    1441
    15 malloc()
    94865291133616
    94865291133616
    94865291133616
    94865291133616
    94865291133616
    94865291133616
    94865291133616
    94865291133616
    94865291133616
    94865291133616
    94865291133616
    94865291133616
    94865291133616
    94865291133616
    94865291133616
    15 mcc_rnd()
    205878483718330808
    206159930722730440
    206441377727130072
    206582101229329888
    206863548233729520
    207004271735929336
    207285718740328968
    207426442242528784
    207707889246928416
    207989336251328048
    208130059753527864
    208411506757927496
    208552230260127312
    208833677264526944
    208974400766726760
    15 mcc__rnd()
    1557322605451952320
    2822145443223898528
    4089501304035441424
    5359390187886581008
    6631812094777317280
    7906767024707650240
    9184254977677579888
    -7982468120022445392
    -6699914120973322368
    -5414827098884602656
    -4127207053756286256
    -2837053985588373168
    -1544367894380863392
    -249148780133756928
    1265036103536263232
    60000 dice rolls mcc_rnd(seed)
    0: 15543
    1: 11088
    2: 10635
    3: 11717
    4: 11017
    5: 0
    60000 dice rolls mcc__rnd(seed)
    0: 39888
    1: 11088
    2: 28141
    3: 11717
    4: 29166
    5: 0
    60000 dice rolls mcc_rnd(NULL)
    0: 64546
    1: 19884
    2: 36992
    3: 20594
    4: 37984
    5: 0
    60000 dice rolls mcc__rnd(NULL)
    0: 84429
    1: 19884
    2: 57093
    3: 20594
    4: 58000
    5: 0
    Compilation finished successfully.

  12. #12
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,787

  13. #13
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by Hodor View Post
    Didn't even know about that, thanks, currently installing now

  14. #14
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by awsdert View Post
    Didn't even know about that, thanks, currently installing now
    Still running but I think it is safe to say its passing at least the majority of tests, yet to see a fail after 10 or so different tests

    Edit 1: On rgb_bitdist and still no fails
    Edit 2: Whoops, wrong code got compiled, I noticed a fatal bug and yet dieharder was running fine??? It's using the tests we used a minute ago, perhaps I did something wrong (besides forget to change a bit of code after copy pasting)
    the command I gave was
    Code:
    dieharder -a < ./mcc_rnd_die.elf
    Edit 3: Running with compiled result of this now:
    Code:
    #ifdef BUILD_FOR_DIEHARDER
    #define PER_LOOP 100
    int main() {
    	for ( int i = 0 ; i < PER_LOOP; i++ ) {
    		printf( "%lu",mcc__rnd( NULL ) );
    	}
    }
    #else
    Okay so 1st one to not get a full passing grade is under diehard_sums, that was weak apparently, but everything else so far is a pass
    Edit 5: One of the sts_serial's was weak but all was a pass, waiting on rgb_bitdist now
    Edit 6: One rgb_lagged_sum got a weak but all else is a pass so far
    Last edited by awsdert; 01-10-2020 at 06:20 AM.

  15. #15
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Code:
    make --no-print-directory dieharder_rnd
    gcc -ggdb -Wall -lpthread -DBUILD_FOR_DIEHARDER -o ./mcc_rnd_die.elf mcc_rnd.c
    dieharder -a < ./mcc_rnd_die.elf
    #=============================================================================#
    #            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
    #=============================================================================#
       rng_name    |rands/second|   Seed   |
            mt19937|  7.47e+07  |2183355501|
    #=============================================================================#
            test_name   |ntup| tsamples |psamples|  p-value |Assessment
    #=============================================================================#
       diehard_birthdays|   0|       100|     100|0.68912807|  PASSED
          diehard_operm5|   0|   1000000|     100|0.33185316|  PASSED
      diehard_rank_32x32|   0|     40000|     100|0.20523365|  PASSED
        diehard_rank_6x8|   0|    100000|     100|0.56657362|  PASSED
       diehard_bitstream|   0|   2097152|     100|0.48796673|  PASSED
            diehard_opso|   0|   2097152|     100|0.96932785|  PASSED
            diehard_oqso|   0|   2097152|     100|0.57613400|  PASSED
             diehard_dna|   0|   2097152|     100|0.36391026|  PASSED
    diehard_count_1s_str|   0|    256000|     100|0.95420219|  PASSED
    diehard_count_1s_byt|   0|    256000|     100|0.49438046|  PASSED
     diehard_parking_lot|   0|     12000|     100|0.69671967|  PASSED
        diehard_2dsphere|   2|      8000|     100|0.64493339|  PASSED
        diehard_3dsphere|   3|      4000|     100|0.70045590|  PASSED
         diehard_squeeze|   0|    100000|     100|0.18376720|  PASSED
            diehard_sums|   0|       100|     100|0.00066824|   WEAK
            diehard_runs|   0|    100000|     100|0.95812784|  PASSED
            diehard_runs|   0|    100000|     100|0.73436942|  PASSED
           diehard_craps|   0|    200000|     100|0.59867241|  PASSED
           diehard_craps|   0|    200000|     100|0.64270262|  PASSED
     marsaglia_tsang_gcd|   0|  10000000|     100|0.21112144|  PASSED
     marsaglia_tsang_gcd|   0|  10000000|     100|0.97679564|  PASSED
             sts_monobit|   1|    100000|     100|0.31412247|  PASSED
                sts_runs|   2|    100000|     100|0.38656440|  PASSED
              sts_serial|   1|    100000|     100|0.28265568|  PASSED
              sts_serial|   2|    100000|     100|0.84211097|  PASSED
              sts_serial|   3|    100000|     100|0.85743956|  PASSED
              sts_serial|   3|    100000|     100|0.62893546|  PASSED
              sts_serial|   4|    100000|     100|0.91881379|  PASSED
              sts_serial|   4|    100000|     100|0.99588482|   WEAK
              sts_serial|   5|    100000|     100|0.40422598|  PASSED
              sts_serial|   5|    100000|     100|0.65208682|  PASSED
              sts_serial|   6|    100000|     100|0.84282188|  PASSED
              sts_serial|   6|    100000|     100|0.48041382|  PASSED
              sts_serial|   7|    100000|     100|0.37634899|  PASSED
              sts_serial|   7|    100000|     100|0.94017686|  PASSED
              sts_serial|   8|    100000|     100|0.37766686|  PASSED
              sts_serial|   8|    100000|     100|0.80462312|  PASSED
              sts_serial|   9|    100000|     100|0.79408707|  PASSED
              sts_serial|   9|    100000|     100|0.78934859|  PASSED
              sts_serial|  10|    100000|     100|0.95975152|  PASSED
              sts_serial|  10|    100000|     100|0.95799169|  PASSED
              sts_serial|  11|    100000|     100|0.27117271|  PASSED
              sts_serial|  11|    100000|     100|0.07037894|  PASSED
              sts_serial|  12|    100000|     100|0.76411242|  PASSED
              sts_serial|  12|    100000|     100|0.45373889|  PASSED
              sts_serial|  13|    100000|     100|0.98482625|  PASSED
              sts_serial|  13|    100000|     100|0.32328241|  PASSED
              sts_serial|  14|    100000|     100|0.95671043|  PASSED
              sts_serial|  14|    100000|     100|0.58142558|  PASSED
              sts_serial|  15|    100000|     100|0.46890954|  PASSED
              sts_serial|  15|    100000|     100|0.95074230|  PASSED
              sts_serial|  16|    100000|     100|0.37380906|  PASSED
              sts_serial|  16|    100000|     100|0.65406332|  PASSED
             rgb_bitdist|   1|    100000|     100|0.84937886|  PASSED
             rgb_bitdist|   2|    100000|     100|0.28646607|  PASSED
             rgb_bitdist|   3|    100000|     100|0.51304968|  PASSED
             rgb_bitdist|   4|    100000|     100|0.45667059|  PASSED
             rgb_bitdist|   5|    100000|     100|0.28200974|  PASSED
             rgb_bitdist|   6|    100000|     100|0.91353734|  PASSED
             rgb_bitdist|   7|    100000|     100|0.72428162|  PASSED
             rgb_bitdist|   8|    100000|     100|0.93574763|  PASSED
             rgb_bitdist|   9|    100000|     100|0.69912244|  PASSED
             rgb_bitdist|  10|    100000|     100|0.86384268|  PASSED
             rgb_bitdist|  11|    100000|     100|0.98536743|  PASSED
             rgb_bitdist|  12|    100000|     100|0.49128106|  PASSED
    rgb_minimum_distance|   2|     10000|    1000|0.70161637|  PASSED
    rgb_minimum_distance|   3|     10000|    1000|0.35414237|  PASSED
    rgb_minimum_distance|   4|     10000|    1000|0.47007518|  PASSED
    rgb_minimum_distance|   5|     10000|    1000|0.47663074|  PASSED
        rgb_permutations|   2|    100000|     100|0.01458501|  PASSED
        rgb_permutations|   3|    100000|     100|0.12143930|  PASSED
        rgb_permutations|   4|    100000|     100|0.36905364|  PASSED
        rgb_permutations|   5|    100000|     100|0.55232070|  PASSED
          rgb_lagged_sum|   0|   1000000|     100|0.92829195|  PASSED
          rgb_lagged_sum|   1|   1000000|     100|0.86765846|  PASSED
          rgb_lagged_sum|   2|   1000000|     100|0.36400818|  PASSED
          rgb_lagged_sum|   3|   1000000|     100|0.99972018|   WEAK
          rgb_lagged_sum|   4|   1000000|     100|0.92030661|  PASSED
          rgb_lagged_sum|   5|   1000000|     100|0.31770161|  PASSED
          rgb_lagged_sum|   6|   1000000|     100|0.83334318|  PASSED
          rgb_lagged_sum|   7|   1000000|     100|0.79018869|  PASSED
          rgb_lagged_sum|   8|   1000000|     100|0.49984733|  PASSED
          rgb_lagged_sum|   9|   1000000|     100|0.29544993|  PASSED
          rgb_lagged_sum|  10|   1000000|     100|0.36598678|  PASSED
          rgb_lagged_sum|  11|   1000000|     100|0.53130325|  PASSED
          rgb_lagged_sum|  12|   1000000|     100|0.16963480|  PASSED
          rgb_lagged_sum|  13|   1000000|     100|0.36339478|  PASSED
          rgb_lagged_sum|  14|   1000000|     100|0.39880436|  PASSED
          rgb_lagged_sum|  15|   1000000|     100|0.50221412|  PASSED
          rgb_lagged_sum|  16|   1000000|     100|0.53840220|  PASSED
          rgb_lagged_sum|  17|   1000000|     100|0.98369666|  PASSED
          rgb_lagged_sum|  18|   1000000|     100|0.68814762|  PASSED
          rgb_lagged_sum|  19|   1000000|     100|0.95109665|  PASSED
          rgb_lagged_sum|  20|   1000000|     100|0.75218223|  PASSED
          rgb_lagged_sum|  21|   1000000|     100|0.19693003|  PASSED
          rgb_lagged_sum|  22|   1000000|     100|0.91385411|  PASSED
          rgb_lagged_sum|  23|   1000000|     100|0.88609169|  PASSED
          rgb_lagged_sum|  24|   1000000|     100|0.59183453|  PASSED
          rgb_lagged_sum|  25|   1000000|     100|0.67084305|  PASSED
          rgb_lagged_sum|  26|   1000000|     100|0.47168894|  PASSED
          rgb_lagged_sum|  27|   1000000|     100|0.91754824|  PASSED
          rgb_lagged_sum|  28|   1000000|     100|0.12052571|  PASSED
          rgb_lagged_sum|  29|   1000000|     100|0.83785940|  PASSED
          rgb_lagged_sum|  30|   1000000|     100|0.11108464|  PASSED
          rgb_lagged_sum|  31|   1000000|     100|0.56193332|  PASSED
          rgb_lagged_sum|  32|   1000000|     100|0.94368013|  PASSED
         rgb_kstest_test|   0|     10000|    1000|0.01123703|  PASSED
         dab_bytedistrib|   0|  51200000|       1|0.95472989|  PASSED
                 dab_dct| 256|     50000|       1|0.73259145|  PASSED
    Preparing to run test 207.  ntuple = 0
            dab_filltree|  32|  15000000|       1|0.71115491|  PASSED
            dab_filltree|  32|  15000000|       1|0.51285566|  PASSED
    Preparing to run test 208.  ntuple = 0
           dab_filltree2|   0|   5000000|       1|0.58756546|  PASSED
           dab_filltree2|   1|   5000000|       1|0.14924778|  PASSED
    Preparing to run test 209.  ntuple = 0
            dab_monobit2|  12|  65000000|       1|0.26885641|  PASSED
    Compilation finished successfully.
    Well I'd say a rough 97% pass rate is good enough for a compiler at least, possibly for security apps too, they just need to take care to make work arounds for the final 3 (such as use internet service whenever possible)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. need a random number generator thats not compleatly random
    By thedodgeruk in forum C++ Programming
    Replies: 1
    Last Post: 06-05-2011, 06:48 AM
  2. Replies: 5
    Last Post: 10-05-2009, 10:21 AM
  3. Replies: 2
    Last Post: 12-25-2003, 01:31 AM
  4. random number between negative and positive number
    By anomaly in forum C++ Programming
    Replies: 6
    Last Post: 12-06-2003, 08:40 AM
  5. Random Number problem in number guessing game...
    By -leech- in forum Windows Programming
    Replies: 8
    Last Post: 01-15-2002, 05:00 PM

Tags for this Thread