# Minimal Makefile, Maximum Outcome - C++ Edition

This is an amendment to one of my previous posts ^{[1]}, which was building a small `Makefile`

for simple C projects.

Here, I'm presenting essentially the same file, but with added C++ support:

This is an amendment to one of my previous posts ^{[1]}, which was building a small `Makefile`

for simple C projects.

Here, I'm presenting essentially the same file, but with added C++ support:

Many terms we use everyday were once brand names, but since have become generic terms we're now using to refer to the category of products in general. A majority of these are or were registered trademarks. These are known as genericized trademarks.

**Cotton swabs**, originally known as "Baby Gays" were invented in the 1920s by American Polish inventor Leo Gerstenzang. They were later renamed into Q-Tips, short for "Quality Tips", and have since become a generic trademark. The brand itself is owned by Unilever.

**Adhesive bandages** were invented in 1920 by Thomas Anderson and Earle Dickson, a Johnson & Johnson employee. Dickson pitched the idea to his employer, who started to produce and sell adhesive bandages under the brand name "Band-Aid". The brand has since become the generic term for adhesive bandages in the US.

This one may come as a surprise, the word "Dumpster" was first used in 1936 to refer to **standardized containers** which could be loaded mechanically onto garbage trucks by the Dempster-Dumpsters. First patented by the Dempster Brothers in 1935, dumpsters have since become synonymous with garbage containers.

**Hook-and-loop fasteners** were first invented by Swiss engineer George de Mestral in 1941. Around the 1950s the Velcro company, a small firm from Montreal, acquired the exclusive rights to market them in North and South America. They were marketed under the name "zipperless zipper". Despite the objections of the Velcro brand, the name has since become a generic trademark to refer to hook-and-loop fasteners.

**Compiler explorer** was created by Matt Godbolt in 2012 as a tool help developers reason better about the assembly generated by their compilers. Originally hosted on the gcc.godbolt.org subdomain, it has since moved to godbolt.org, manifesting the use of godbolt to refer to compiler explorer.

Follow me on Twitter: @ArvidGerstmann

Connect on LinkedIn: linkedin.com/in/arvidgerstmann

Yesterday I wrote about the terrible quality of the default pseudo random number generators in the C++ standard library. The article came to the conclusion they're all around terrible, and should generally be avoided, yet, it didn't provide any alternatives. Therefore, today I'll provide you with three very good alternatives to the existing generators in the C++ standard library.

`splitmix`

^{[1]}`xorshift`

^{[2]}`pcg`

^{[3]}

They're almost fully compliant to the standard, and should be an almost drop-in replacement for the old generators.

There is a minor change in the interface, related how the generator is seeded. To seed any of the generators, you need to pass in the `std::random_device`

(or any class which implements `operator()`

and returns an `unsigned int`

) you want to use, instead of just the seed. By doing so, I can make sure each generator is seeded accordingly.

Each of these is passing both the PractRand and BigCrush test. The raw PractRand test results can be found here and the code can be found at the end of the article.

For comparison, I've reproduced the comparison tables from the previous article. The newly added generators are highlighted in bold.

generator | 512M | 1G | 2G | 4G | 8G | 16G | 32G | 64G | 128G | 256G | 512G | 1T | 2T |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|

ranlux24_base | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |

ranlux48_base | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |

minstd_rand | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |

minstd_rand0 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |

knuth_b | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |

mt19937 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |

mt19937_64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ |

ranlux24 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |

ranlux48 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |

splitmix |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |

xorshift |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |

pcg |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |

All three generators have excellent statistical quality, while having a smaller footprint and being faster. As a bonus, each of the three generators can be implemented in less than 10 lines of code, making them super easy to port to other environments or languages.

Name | Predictability | Performance | State | Period |
---|---|---|---|---|

Mersenne Twister | Trivial | Ok | 2 KiB | 2^19937 |

LCG (minstd) | Trivial | Ok | 4-8 byte | <= 2^32 |

LFG (ranluxXX_base) | Trivial | Slow | 8-16 byte | <= 2^32 |

Knuth | Trivial | Ok | 1KiB | <= 2^32 |

ranlux | Unknown? | Super Slow | ~120 byte | 10^171 |

splitmix |
Trivial | Fast | 8 byte | 2^64 |

xorshift |
Yes | Fast | 8 byte | 2^64 |

pcg |
Unknown | Fast | 16 byte | 2^128 |

Following is an example of how to generate 10 random die rolls using the supplied `pcg`

generator:

```
#include <stdio.h>
#include "random.h"
int main()
{
std::random_device rd;
pcg rand(rd);
std::uniform_int_distribution<> u(1, 6);
for (int i = 0; i < 10; ++i)
printf("%d\n", u(rand));
}
```

Code can be found in the following gist.

truncated xorshift32* ↩︎

**tl;dr:** Do not use `<random>`

's generators. There are plenty good alternatives, like PCG, SplitMix, truncated Xorshift32*, or Xorshift1024*.

A recent tweet reminded me of the `<random>`

facilities in the C++ standard library. Having just recently studied and implemented a couple random number generators myself, I was curious how they hold up in a modern test.

From the get-go, I knew this is going to end badly, but I gave it a shot anyway.

I build a little test program, to feed into PractRand:

```
#include <random>
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
template<class Rand, class T>
static void
run()
{
std::random_device rd;
Rand gen(rd());
std::uniform_int_distribution<T> dis(0);
T val;
while (1) {
val = dis(gen);
fwrite((void *)&val, 1, sizeof(T), stdout);
}
}
int main()
{
freopen(nullptr, "wb", stdout); /* only required for windows */
run<std::ranlux24_base, uint32_t>();
return 0;
}
```

The test program is printing unsigned 32bit numbers to stdout, which will be piped into the `RNG_Test`

executable from the PractRand suite.

I compiled a single executable for each generator, and started the tests.

Most of the tests were over in just a couple seconds.

generator | 256M | 512M | 1G | 2G | 4G | 8G | 16G | 32G | 64G | 128G | 256G | 512G | 1T |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|

ranlux24_base | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |

ranlux48_base | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |

minstd_rand | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |

minstd_rand0 | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |

knuth_b | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |

mt19937 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ |

mt19937_64 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ |

ranlux24 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |

ranlux48 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |

The table shows after how many iterations the generator fails the statistical tests.

The earlier it fails, the worse it is. Modern PRNGs, like PCG, are known to not fail the statistical tests at all.

That's only have the story, though.

With the table above showing the statistical quality of each generator, the following is listing it's properties:

Name | Predictability | Performance | State | Period |
---|---|---|---|---|

Mersenne Twister | Trivial | Ok | 2 KiB | 2^19937 |

LCG (minstd) | Trivial | Ok | 4-8 byte | <= 2^32 |

LFG (ranluxXX_base) | Trivial | Slow | 8-16 byte | <= 2^32 |

Knuth | Trivial | Ok | 1KiB | <= 2^32 |

ranlux | Unknown? | Super Slow | ~120 byte | 10^171 |

While both the 32-bit and 64-bit mersenne twister fail (`mt19937`

& `mt19937_64`

) at some seemingly high amount of data (256G and 512G, respectively), they are fundamentally flawed. They're easily predictable, large (2.5KiB of state) and multiple times slower than any other alternative.

**If you must use any generator from <random>, use either ranlux24 or ranlux48, the only two which showed a reasonable result in the test. At the expense of performance.**

While `<random>`

has the building blocks to build a decent generator, with good statistical quality, it requires knowledge of the domain, and is not trivial. The predefined generators didn't stand the test of time, and are weak throughout. To make matters worse, the `default_random_engine`

often defaults to `mt19937`

, which, while not as bad as the other choices, is neither fast, lean nor unpredictable.

There is a certain irony, that it's known that `rand()`

is terrible generator, while everybody is fine that C++ includes almost the exact same generator (`rand()`

is usually implemented as an LCG).

Following are the raw tests results linked, for your viewing pleasure.

`ranlux24_base`

```
$ ./ranlux24_base | ./PractRand/RNG_test stdin32 -multithreaded
RNG_test using PractRand version 0.93
RNG = RNG_stdin32, seed = 0xc6851f49
test set = normal, folding = standard (32 bit)
rng=RNG_stdin32, seed=0xc6851f49
length= 256 megabytes (2^28 bytes), time= 3.5 seconds
Test Name Raw Processed Evaluation
BCFN(2+1,13-2,T) R= +9.7 p = 1.5e-4 mildly suspicious
BCFN(2+2,13-3,T) R= +9.0 p = 4.6e-4 unusual
[Low8/32]BCFN(2+0,13-3,T) R= +91.1 p = 6.3e-43 FAIL !!!
[Low8/32]BCFN(2+1,13-3,T) R= +24.4 p = 2.4e-11 FAIL
[Low8/32]BCFN(2+2,13-4,T) R= +12.3 p = 2.4e-5 mildly suspicious
[Low1/32]BCFN(2+0,13-5,T) R= +45.5 p = 5.4e-18 FAIL !
[Low1/32]DC6-9x1Bytes-1 R=+485.8 p = 1.8e-256 FAIL !!!!!!
...and 117 test result(s) without anomalies
```

`ranlux48_base`

```
$ ./ranlux48_base | ./PractRand/RNG_test stdin32 -multithreaded
RNG_test using PractRand version 0.93
RNG = RNG_stdin32, seed = 0x13294a68
test set = normal, folding = standard (32 bit)
rng=RNG_stdin32, seed=0x13294a68
length= 256 megabytes (2^28 bytes), time= 2.8 seconds
Test Name Raw Processed Evaluation
BCFN(2+1,13-2,T) R= +28.1 p = 6.0e-14 FAIL
[Low8/32]BCFN(2+0,13-3,T) R=+251.2 p = 1.0e-118 FAIL !!!!!
[Low8/32]BCFN(2+1,13-3,T) R= +20.5 p = 1.6e-9 VERY SUSPICIOUS
[Low1/32]BCFN(2+0,13-5,T) R= +16.0 p = 1.9e-6 very suspicious
[Low1/32]DC6-9x1Bytes-1 R= +49.8 p = 3.4e-26 FAIL !!
...and 119 test result(s) without anomalies
```

`minstd_rand`

```
$ ./minstd_rand | ./PractRand/RNG_Test stdin32 -multithreaded
RNG_test using PractRand version 0.93
RNG = RNG_stdin32, seed = 0x665a9f8e
test set = normal, folding = standard (32 bit)
rng=RNG_stdin32, seed=0x665a9f8e
length= 256 megabytes (2^28 bytes), time= 3.9 seconds
Test Name Raw Processed Evaluation
FPF-14+6/16:(0,14-0) R= -7.9 p =1-6.2e-7 mildly suspicious
FPF-14+6/16:(1,14-0) R= -7.1 p =1-2.8e-6 mildly suspicious
FPF-14+6/16:(2,14-0) R= -6.3 p =1-1.8e-5 unusual
FPF-14+6/16:all R= -13.4 p =1-1.0e-12 FAIL
FPF-14+6/16:all2 R= +24.9 p = 2.8e-11 VERY SUSPICIOUS
[Low8/32]FPF-14+6/16:all R= -6.7 p =1-4.2e-6 suspicious
...and 118 test result(s) without anomalies
```

`minstd_rand0`

```
$ ./minstd_rand0 | ./PractRand/RNG_Test stdin32 -multithreaded
RNG_test using PractRand version 0.93
RNG = RNG_stdin32, seed = 0x3b74f60f
test set = normal, folding = standard (32 bit)
rng=RNG_stdin32, seed=0x3b74f60f
length= 128 megabytes (2^27 bytes), time= 2.2 seconds
Test Name Raw Processed Evaluation
BCFN(2+2,13-3,T) R= +7.8 p = 1.8e-3 unusual
FPF-14+6/16:(0,14-0) R= -6.5 p =1-1.0e-5 unusual
FPF-14+6/16:all R= -8.2 p =1-1.5e-7 very suspicious
FPF-14+6/16:all2 R= +10.6 p = 1.3e-5 mildly suspicious
...and 113 test result(s) without anomalies
rng=RNG_stdin32, seed=0x3b74f60f
length= 256 megabytes (2^28 bytes), time= 4.6 seconds
Test Name Raw Processed Evaluation
FPF-14+6/16:(0,14-0) R= -9.4 p =1-2.6e-8 very suspicious
FPF-14+6/16:(2,14-0) R= -8.7 p =1-9.5e-8 suspicious
FPF-14+6/16:all R= -13.5 p =1-8.8e-13 FAIL
FPF-14+6/16:all2 R= +31.8 p = 5.2e-14 FAIL
[Low8/32]FPF-14+6/16:all R= -4.2 p =1-1.2e-3 unusual
[Low1/32]BCFN(2+1,13-5,T) R= -6.5 p =1-5.1e-4 unusual
...and 118 test result(s) without anomalies
```

`knuth_b`

```
$ ./knuth_b | ./PractRand/RNG_Test stdin32 -multithreaded
RNG_test using PractRand version 0.93
RNG = RNG_stdin32, seed = 0x2ba764e1
test set = normal, folding = standard (32 bit)
rng=RNG_stdin32, seed=0x2ba764e1
length= 128 megabytes (2^27 bytes), time= 2.9 seconds
no anomalies in 117 test result(s)
rng=RNG_stdin32, seed=0x2ba764e1
length= 256 megabytes (2^28 bytes), time= 5.8 seconds
Test Name Raw Processed Evaluation
FPF-14+6/16:all R= -5.5 p =1-6.4e-5 mildly suspicious
...and 123 test result(s) without anomalies
rng=RNG_stdin32, seed=0x2ba764e1
length= 512 megabytes (2^29 bytes), time= 10.9 seconds
Test Name Raw Processed Evaluation
FPF-14+6/16:(0,14-0) R= -6.8 p =1-5.5e-6 unusual
FPF-14+6/16:all R= -8.7 p =1-4.7e-8 very suspicious
FPF-14+6/16:all2 R= +8.9 p = 4.2e-5 mildly suspicious
...and 129 test result(s) without anomalies
rng=RNG_stdin32, seed=0x2ba764e1
length= 1 gigabyte (2^30 bytes), time= 20.8 seconds
Test Name Raw Processed Evaluation
FPF-14+6/16:(0,14-0) R= -12.8 p =1-1.9e-11 VERY SUSPICIOUS
FPF-14+6/16:(2,14-0) R= -6.7 p =1-7.3e-6 unusual
FPF-14+6/16:all R= -15.4 p =1-1.1e-14 FAIL !
FPF-14+6/16:all2 R= +44.4 p = 2.4e-19 FAIL !
...and 137 test result(s) without anomalies
```

`mt19937`

```
$ ./mt19937 | ./PractRand/RNG_test stdin32 -multithreaded
RNG_test using PractRand version 0.93
RNG = RNG_stdin32, seed = 0xadda9d07
test set = normal, folding = standard (32 bit)
rng=RNG_stdin32, seed=0xadda9d07
length= 512 megabytes (2^29 bytes), time= 3.5 seconds
no anomalies in 132 test result(s)
rng=RNG_stdin32, seed=0xadda9d07
length= 1 gigabyte (2^30 bytes), time= 7.0 seconds
no anomalies in 141 test result(s)
rng=RNG_stdin32, seed=0xadda9d07
length= 2 gigabytes (2^31 bytes), time= 13.6 seconds
no anomalies in 148 test result(s)
rng=RNG_stdin32, seed=0xadda9d07
length= 4 gigabytes (2^32 bytes), time= 26.5 seconds
no anomalies in 156 test result(s)
rng=RNG_stdin32, seed=0xadda9d07
length= 8 gigabytes (2^33 bytes), time= 52.4 seconds
no anomalies in 165 test result(s)
rng=RNG_stdin32, seed=0xadda9d07
length= 16 gigabytes (2^34 bytes), time= 104 seconds
no anomalies in 172 test result(s)
rng=RNG_stdin32, seed=0xadda9d07
length= 32 gigabytes (2^35 bytes), time= 203 seconds
no anomalies in 180 test result(s)
rng=RNG_stdin32, seed=0xadda9d07
length= 64 gigabytes (2^36 bytes), time= 404 seconds
no anomalies in 189 test result(s)
rng=RNG_stdin32, seed=0xadda9d07
length= 128 gigabytes (2^37 bytes), time= 794 seconds
no anomalies in 196 test result(s)
rng=RNG_stdin32, seed=0xadda9d07
length= 256 gigabytes (2^38 bytes), time= 1620 seconds
Test Name Raw Processed Evaluation
DC6-9x1Bytes-1 R= -5.3 p =1-3.6e-3 unusual
[Low8/32]BRank(12):12K(1) R= +6116 p~= 4e-1842 FAIL !!!!!!!!
...and 202 test result(s) without anomalies
```

`ranlux24`

```
$ ./ranlux24 | ./PractRand/RNG_test stdin32 -multithreaded
RNG_test using PractRand version 0.93
RNG = RNG_stdin32, seed = 0xd8322a9c
test set = normal, folding = standard (32 bit)
rng=RNG_stdin32, seed=0xd8322a9c
length= 64 megabytes (2^26 bytes), time= 2.1 seconds
no anomalies in 108 test result(s)
rng=RNG_stdin32, seed=0xd8322a9c
length= 128 megabytes (2^27 bytes), time= 4.6 seconds
no anomalies in 117 test result(s)
rng=RNG_stdin32, seed=0xd8322a9c
length= 256 megabytes (2^28 bytes), time= 9.2 seconds
no anomalies in 124 test result(s)
rng=RNG_stdin32, seed=0xd8322a9c
length= 512 megabytes (2^29 bytes), time= 17.6 seconds
no anomalies in 132 test result(s)
rng=RNG_stdin32, seed=0xd8322a9c
length= 1 gigabyte (2^30 bytes), time= 33.7 seconds
no anomalies in 141 test result(s)
rng=RNG_stdin32, seed=0xd8322a9c
length= 2 gigabytes (2^31 bytes), time= 65.8 seconds
no anomalies in 148 test result(s)
rng=RNG_stdin32, seed=0xd8322a9c
length= 4 gigabytes (2^32 bytes), time= 129 seconds
no anomalies in 156 test result(s)
rng=RNG_stdin32, seed=0xd8322a9c
length= 8 gigabytes (2^33 bytes), time= 256 seconds
no anomalies in 165 test result(s)
rng=RNG_stdin32, seed=0xd8322a9c
length= 16 gigabytes (2^34 bytes), time= 510 seconds
no anomalies in 172 test result(s)
rng=RNG_stdin32, seed=0xd8322a9c
length= 32 gigabytes (2^35 bytes), time= 1008 seconds
no anomalies in 180 test result(s)
rng=RNG_stdin32, seed=0xd8322a9c
length= 64 gigabytes (2^36 bytes), time= 1920 seconds
no anomalies in 189 test result(s)
rng=RNG_stdin32, seed=0xd8322a9c
length= 128 gigabytes (2^37 bytes), time= 3743 seconds
no anomalies in 196 test result(s)
rng=RNG_stdin32, seed=0xd8322a9c
length= 256 gigabytes (2^38 bytes), time= 7372 seconds
no anomalies in 204 test result(s)
rng=RNG_stdin32, seed=0xd8322a9c
length= 512 gigabytes (2^39 bytes), time= 14681 seconds
Test Name Raw Processed Evaluation
[Low1/32]DC6-9x1Bytes-1 R= +4.5 p = 0.010 unusual
...and 212 test result(s) without anomalies
rng=RNG_stdin32, seed=0xd8322a9c
length= 1 terabyte (2^40 bytes), time= 29803 seconds
no anomalies in 220 test result(s)
rng=RNG_stdin32, seed=0xd8322a9c
length= 2 terabytes (2^41 bytes), time= 60168 seconds
Test Name Raw Processed Evaluation
[Low1/32]DC6-9x1Bytes-1 R= +5.6 p = 8.4e-3 unusual
...and 227 test result(s) without anomalies
```

`ranlux48`

```
$ ./ranlux48 | ./PractRand/RNG_test stdin32 -multithreaded
RNG_test using PractRand version 0.93
RNG = RNG_stdin32, seed = 0xd97451a6
test set = normal, folding = standard (32 bit)
rng=RNG_stdin32, seed=0xd97451a6
length= 64 megabytes (2^26 bytes), time= 2.1 seconds
no anomalies in 108 test result(s)
rng=RNG_stdin32, seed=0xd97451a6
length= 128 megabytes (2^27 bytes), time= 4.5 seconds
no anomalies in 117 test result(s)
rng=RNG_stdin32, seed=0xd97451a6
length= 256 megabytes (2^28 bytes), time= 8.9 seconds
no anomalies in 124 test result(s)
rng=RNG_stdin32, seed=0xd97451a6
length= 512 megabytes (2^29 bytes), time= 17.2 seconds
Test Name Raw Processed Evaluation
DC6-9x1Bytes-1 R= +5.5 p = 5.4e-3 unusual
...and 131 test result(s) without anomalies
rng=RNG_stdin32, seed=0xd97451a6
length= 1 gigabyte (2^30 bytes), time= 33.1 seconds
Test Name Raw Processed Evaluation
[Low8/32]DC6-9x1Bytes-1 R= +6.1 p = 3.3e-3 unusual
...and 140 test result(s) without anomalies
rng=RNG_stdin32, seed=0xd97451a6
length= 2 gigabytes (2^31 bytes), time= 64.6 seconds
no anomalies in 148 test result(s)
rng=RNG_stdin32, seed=0xd97451a6
length= 4 gigabytes (2^32 bytes), time= 127 seconds
no anomalies in 156 test result(s)
rng=RNG_stdin32, seed=0xd97451a6
length= 8 gigabytes (2^33 bytes), time= 253 seconds
no anomalies in 165 test result(s)
rng=RNG_stdin32, seed=0xd97451a6
length= 16 gigabytes (2^34 bytes), time= 501 seconds
no anomalies in 172 test result(s)
rng=RNG_stdin32, seed=0xd97451a6
length= 32 gigabytes (2^35 bytes), time= 1001 seconds
no anomalies in 180 test result(s)
rng=RNG_stdin32, seed=0xd97451a6
length= 64 gigabytes (2^36 bytes), time= 2014 seconds
no anomalies in 189 test result(s)
rng=RNG_stdin32, seed=0xd97451a6
length= 128 gigabytes (2^37 bytes), time= 4182 seconds
Test Name Raw Processed Evaluation
DC6-9x1Bytes-1 R= -4.3 p = 0.989 unusual
...and 195 test result(s) without anomalies
rng=RNG_stdin32, seed=0xd97451a6
length= 256 gigabytes (2^38 bytes), time= 8169 seconds
no anomalies in 204 test result(s)
rng=RNG_stdin32, seed=0xd97451a6
length= 512 gigabytes (2^39 bytes), time= 16166 seconds
no anomalies in 213 test result(s)
rng=RNG_stdin32, seed=0xd97451a6
length= 1 terabyte (2^40 bytes), time= 32123 seconds
no anomalies in 220 test result(s)
```

The following is a list of architectures where certain instruction sets have been introduced first. The column "instr. set" only lists the *introduced*, not all instruction sets.

Only includes consumer CPUs, not Xeons or other prosumer hardware.

Year | uArch | instr. set |
---|---|---|

2007 | Intel Core | SSE, SSE2, SSE3, SSSE3, SSE4 |

2007 | Penryn | SSE4.1, VT-x, VT-d |

2008 | Nehalem | SSE4.2 |

2010 | Westmere | AES-NI, CLMUL |

2011 | Sandy Bridge | AVX, TXT |

2012 | Ivy Bridge | F16C |

2013 | Haswell | FMA3, AVX2, TSX (only Haswell-EX) |

2014 | Broadwell | ADX, TSX, RDSEED, PREFETCHW |

2015 | Skylake | MPX, SGX, HEVC |

2016 | Kaby Lake | - |

2017 | Coffee Lake | - |

2018 | Cannon Lake | AVX-512, SHA |

2018 | Cascade Lake | TBD |

2018 | Whiskey Lake | TBD |

2019 | Ice Lake | TBD |

Year | uArch | instr. set |
---|---|---|

2003 | Hammer (K8) | SSE, SSE2 (SSE3, starting with Athlon64) |

2007 | K10 | AMD-V, SSE4a |

2011 | Bobcat (K14) | ABM |

2011 | Bulldozer (K15) | SSSE3, SSE4.1, SSE4.2, AES, CLMUL, AVX, XOP, FMA4, F16C |

2012 | Piledriver (K15) | FMA3 |

2012 | Steamroller (K15) | HEVC |

2013 | Jaguar (K16) | MOVBE |

2017 | Zen (K17) | AVX2, SHA, ADX, RDSEE |

If you see any errors, please contact me on Twitter @ArvidGerstmann.