// SPDX-License-Identifier: GPL-2.0
/*
* This is a maximally equidistributed combined Tausworthe generator
* based on code from GNU Scientific Library 1 . 5 ( 30 Jun 2004 )
*
* lfsr113 version :
*
* x_n = ( s1_n ^ s2_n ^ s3_n ^ s4_n )
*
* s1_ { n + 1 } = ( ( ( s1_n & 4294967294 ) < < 18 ) ^ ( ( ( s1_n < < 6 ) ^ s1_n ) > > 13 ) )
* s2_ { n + 1 } = ( ( ( s2_n & 4294967288 ) < < 2 ) ^ ( ( ( s2_n < < 2 ) ^ s2_n ) > > 27 ) )
* s3_ { n + 1 } = ( ( ( s3_n & 4294967280 ) < < 7 ) ^ ( ( ( s3_n < < 13 ) ^ s3_n ) > > 21 ) )
* s4_ { n + 1 } = ( ( ( s4_n & 4294967168 ) < < 13 ) ^ ( ( ( s4_n < < 3 ) ^ s4_n ) > > 12 ) )
*
* The period of this generator is about 2 ^ 113 ( see erratum paper ) .
*
* From : P . L ' Ecuyer , " Maximally Equidistributed Combined Tausworthe
* Generators " , Mathematics of Computation , 65 , 213 ( 1996 ) , 203 - - 213 :
* http : //www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
* ftp : //ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps
*
* There is an erratum in the paper " Tables of Maximally Equidistributed
* Combined LFSR Generators " , Mathematics of Computation , 68 , 225 ( 1999 ) ,
* 261 - - 269 : http : //www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
*
* . . . the k_j most significant bits of z_j must be non - zero ,
* for each j . ( Note : this restriction also applies to the
* computer code given in [ 4 ] , but was mistakenly not mentioned
* in that paper . )
*
* This affects the seeding procedure by imposing the requirement
* s1 > 1 , s2 > 7 , s3 > 15 , s4 > 127 .
*/
#include <linux/types.h>
#include <linux/percpu.h>
#include <linux/export.h>
#include <linux/jiffies.h>
#include <linux/prandom.h>
#include <linux/sched.h>
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/unaligned.h>
/**
* prandom_u32_state - seeded pseudo - random number generator .
* @ state : pointer to state structure holding seeded state .
*
* This is used for pseudo - randomness with no outside seeding .
* For more random results , use get_random_u32 ( ) .
*/
u32 prandom_u32_state(struct rnd_state *state)
{
#define TAUSWORTHE(s, a, b, c, d) ((s & c) << d) ^ (((s << a) ^ s) >> b)
state->s1 = TAUSWORTHE(state->s1, 6 U, 13 U, 4294967294 U, 18 U);
state->s2 = TAUSWORTHE(state->s2, 2 U, 27 U, 4294967288 U, 2 U);
state->s3 = TAUSWORTHE(state->s3, 13 U, 21 U, 4294967280 U, 7 U);
state->s4 = TAUSWORTHE(state->s4, 3 U, 12 U, 4294967168 U, 13 U);
return (state->s1 ^ state->s2 ^ state->s3 ^ state->s4);
}
EXPORT_SYMBOL(prandom_u32_state);
/**
* prandom_bytes_state - get the requested number of pseudo - random bytes
*
* @ state : pointer to state structure holding seeded state .
* @ buf : where to copy the pseudo - random bytes to
* @ bytes : the requested number of bytes
*
* This is used for pseudo - randomness with no outside seeding .
* For more random results , use get_random_bytes ( ) .
*/
void prandom_bytes_state(struct rnd_state *state, void *buf, size_t bytes)
{
u8 *ptr = buf;
while (bytes >= sizeof (u32)) {
put_unaligned(prandom_u32_state(state), (u32 *) ptr);
ptr += sizeof (u32);
bytes -= sizeof (u32);
}
if (bytes > 0 ) {
u32 rem = prandom_u32_state(state);
do {
*ptr++ = (u8) rem;
bytes--;
rem >>= BITS_PER_BYTE;
} while (bytes > 0 );
}
}
EXPORT_SYMBOL(prandom_bytes_state);
static void prandom_warmup(struct rnd_state *state)
{
/* Calling RNG ten times to satisfy recurrence condition */
prandom_u32_state(state);
prandom_u32_state(state);
prandom_u32_state(state);
prandom_u32_state(state);
prandom_u32_state(state);
prandom_u32_state(state);
prandom_u32_state(state);
prandom_u32_state(state);
prandom_u32_state(state);
prandom_u32_state(state);
}
void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state)
{
int i;
for_each_possible_cpu(i) {
struct rnd_state *state = per_cpu_ptr(pcpu_state, i);
u32 seeds[4 ];
get_random_bytes(&seeds, sizeof (seeds));
state->s1 = __seed(seeds[0 ], 2 U);
state->s2 = __seed(seeds[1 ], 8 U);
state->s3 = __seed(seeds[2 ], 16 U);
state->s4 = __seed(seeds[3 ], 128 U);
prandom_warmup(state);
}
}
EXPORT_SYMBOL(prandom_seed_full_state);
#ifdef CONFIG_RANDOM32_SELFTEST
static struct prandom_test1 {
u32 seed;
u32 result;
} test1[] = {
{ 1 U, 3484351685 U },
{ 2 U, 2623130059 U },
{ 3 U, 3125133893 U },
{ 4 U, 984847254 U },
};
static struct prandom_test2 {
u32 seed;
u32 iteration;
u32 result;
} test2[] = {
/* Test cases against taus113 from GSL library. */
{ 931557656 U, 959 U, 2975593782 U },
{ 1339693295 U, 876 U, 3887776532 U },
{ 1545556285 U, 961 U, 1615538833 U },
{ 601730776 U, 723 U, 1776162651 U },
{ 1027516047 U, 687 U, 511983079 U },
{ 416526298 U, 700 U, 916156552 U },
{ 1395522032 U, 652 U, 2222063676 U },
{ 366221443 U, 617 U, 2992857763 U },
{ 1539836965 U, 714 U, 3783265725 U },
{ 556206671 U, 994 U, 799626459 U },
{ 684907218 U, 799 U, 367789491 U },
{ 2121230701 U, 931 U, 2115467001 U },
{ 1668516451 U, 644 U, 3620590685 U },
{ 768046066 U, 883 U, 2034077390 U },
{ 1989159136 U, 833 U, 1195767305 U },
{ 536585145 U, 996 U, 3577259204 U },
{ 1008129373 U, 642 U, 1478080776 U },
{ 1740775604 U, 939 U, 1264980372 U },
{ 1967883163 U, 508 U, 10734624 U },
{ 1923019697 U, 730 U, 3821419629 U },
{ 442079932 U, 560 U, 3440032343 U },
{ 1961302714 U, 845 U, 841962572 U },
{ 2030205964 U, 962 U, 1325144227 U },
{ 1160407529 U, 507 U, 240940858 U },
{ 635482502 U, 779 U, 4200489746 U },
{ 1252788931 U, 699 U, 867195434 U },
{ 1961817131 U, 719 U, 668237657 U },
{ 1071468216 U, 983 U, 917876630 U },
{ 1281848367 U, 932 U, 1003100039 U },
{ 582537119 U, 780 U, 1127273778 U },
{ 1973672777 U, 853 U, 1071368872 U },
{ 1896756996 U, 762 U, 1127851055 U },
{ 847917054 U, 500 U, 1717499075 U },
{ 1240520510 U, 951 U, 2849576657 U },
{ 1685071682 U, 567 U, 1961810396 U },
{ 1516232129 U, 557 U, 3173877 U },
{ 1208118903 U, 612 U, 1613145022 U },
{ 1817269927 U, 693 U, 4279122573 U },
{ 1510091701 U, 717 U, 638191229 U },
{ 365916850 U, 807 U, 600424314 U },
{ 399324359 U, 702 U, 1803598116 U },
{ 1318480274 U, 779 U, 2074237022 U },
{ 697758115 U, 840 U, 1483639402 U },
{ 1696507773 U, 840 U, 577415447 U },
{ 2081979121 U, 981 U, 3041486449 U },
{ 955646687 U, 742 U, 3846494357 U },
{ 1250683506 U, 749 U, 836419859 U },
{ 595003102 U, 534 U, 366794109 U },
{ 47485338 U, 558 U, 3521120834 U },
{ 619433479 U, 610 U, 3991783875 U },
{ 704096520 U, 518 U, 4139493852 U },
{ 1712224984 U, 606 U, 2393312003 U },
{ 1318233152 U, 922 U, 3880361134 U },
{ 855572992 U, 761 U, 1472974787 U },
{ 64721421 U, 703 U, 683860550 U },
{ 678931758 U, 840 U, 380616043 U },
{ 692711973 U, 778 U, 1382361947 U },
{ 677703619 U, 530 U, 2826914161 U },
{ 92393223 U, 586 U, 1522128471 U },
{ 1222592920 U, 743 U, 3466726667 U },
{ 358288986 U, 695 U, 1091956998 U },
{ 1935056945 U, 958 U, 514864477 U },
{ 735675993 U, 990 U, 1294239989 U },
{ 1560089402 U, 897 U, 2238551287 U },
{ 70616361 U, 829 U, 22483098 U },
{ 368234700 U, 731 U, 2913875084 U },
{ 20221190 U, 879 U, 1564152970 U },
{ 539444654 U, 682 U, 1835141259 U },
{ 1314987297 U, 840 U, 1801114136 U },
{ 2019295544 U, 645 U, 3286438930 U },
{ 469023838 U, 716 U, 1637918202 U },
{ 1843754496 U, 653 U, 2562092152 U },
{ 400672036 U, 809 U, 4264212785 U },
{ 404722249 U, 965 U, 2704116999 U },
{ 600702209 U, 758 U, 584979986 U },
{ 519953954 U, 667 U, 2574436237 U },
{ 1658071126 U, 694 U, 2214569490 U },
{ 420480037 U, 749 U, 3430010866 U },
{ 690103647 U, 969 U, 3700758083 U },
{ 1029424799 U, 937 U, 3787746841 U },
{ 2012608669 U, 506 U, 3362628973 U },
{ 1535432887 U, 998 U, 42610943 U },
{ 1330635533 U, 857 U, 3040806504 U },
{ 1223800550 U, 539 U, 3954229517 U },
{ 1322411537 U, 680 U, 3223250324 U },
{ 1877847898 U, 945 U, 2915147143 U },
{ 1646356099 U, 874 U, 965988280 U },
{ 805687536 U, 744 U, 4032277920 U },
{ 1948093210 U, 633 U, 1346597684 U },
{ 392609744 U, 783 U, 1636083295 U },
{ 690241304 U, 770 U, 1201031298 U },
{ 1360302965 U, 696 U, 1665394461 U },
{ 1220090946 U, 780 U, 1316922812 U },
{ 447092251 U, 500 U, 3438743375 U },
{ 1613868791 U, 592 U, 828546883 U },
{ 523430951 U, 548 U, 2552392304 U },
{ 726692899 U, 810 U, 1656872867 U },
{ 1364340021 U, 836 U, 3710513486 U },
{ 1986257729 U, 931 U, 935013962 U },
{ 407983964 U, 921 U, 728767059 U },
};
static void prandom_state_selftest_seed(struct rnd_state *state, u32 seed)
{
#define LCG(x) ((x) * 69069 U) /* super-duper LCG */
state->s1 = __seed(LCG(seed), 2 U);
state->s2 = __seed(LCG(state->s1), 8 U);
state->s3 = __seed(LCG(state->s2), 16 U);
state->s4 = __seed(LCG(state->s3), 128 U);
}
static int __init prandom_state_selftest(void )
{
int i, j, errors = 0 , runs = 0 ;
bool error = false ;
for (i = 0 ; i < ARRAY_SIZE(test1); i++) {
struct rnd_state state;
prandom_state_selftest_seed(&state, test1[i].seed);
prandom_warmup(&state);
if (test1[i].result != prandom_u32_state(&state))
error = true ;
}
if (error)
pr_warn("prandom: seed boundary self test failed\n" );
else
pr_info("prandom: seed boundary self test passed\n" );
for (i = 0 ; i < ARRAY_SIZE(test2); i++) {
struct rnd_state state;
prandom_state_selftest_seed(&state, test2[i].seed);
prandom_warmup(&state);
for (j = 0 ; j < test2[i].iteration - 1 ; j++)
prandom_u32_state(&state);
if (test2[i].result != prandom_u32_state(&state))
errors++;
runs++;
cond_resched();
}
if (errors)
pr_warn("prandom: %d/%d self tests failed\n" , errors, runs);
else
pr_info("prandom: %d self tests passed\n" , runs);
return 0 ;
}
core_initcall(prandom_state_selftest);
#endif
Messung V0.5 in Prozent C=97 H=74 G=86
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-09-27)
¤
*© Formatika GbR, Deutschland