diff --git a/include/stdlib.h b/include/stdlib.h index a915e407ce..a522680a65 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -132,6 +132,19 @@ extern "C" void srand(unsigned int seed); int rand(void); +void lcong48(FAR unsigned short int param[7]); +FAR unsigned short int *seed48(FAR unsigned short int seed16v[3]); +void srand48(long int seedval); +#ifdef CONFIG_HAVE_LONG_LONG +long int jrand48(FAR unsigned short int xsubi[3]); +long int lrand48(void); +long int mrand48(void); +long int nrand48(FAR unsigned short int xsubi[3]); +# ifdef CONFIG_HAVE_DOUBLE +double drand48(void); +double erand48(FAR unsigned short int xsubi[3]); +# endif +#endif #define srandom(s) srand(s) long random(void); diff --git a/libs/libc/stdlib/Make.defs b/libs/libc/stdlib/Make.defs index d495a98a05..2692f315d6 100644 --- a/libs/libc/stdlib/Make.defs +++ b/libs/libc/stdlib/Make.defs @@ -23,7 +23,7 @@ CSRCS += lib_abs.c lib_abort.c lib_atof.c lib_atoi.c lib_getprogname.c CSRCS += lib_atol.c lib_atoll.c lib_div.c lib_ldiv.c lib_lldiv.c lib_exit.c CSRCS += lib_itoa.c lib_labs.c lib_llabs.c lib_realpath.c lib_bsearch.c -CSRCS += lib_rand.c lib_qsort.c lib_srand.c lib_strtol.c +CSRCS += lib_rand.c lib_rand48.c lib_qsort.c lib_srand.c lib_strtol.c CSRCS += lib_strtoll.c lib_strtoul.c lib_strtoull.c lib_strtod.c lib_strtof.c CSRCS += lib_strtold.c lib_checkbase.c lib_mktemp.c lib_mkstemp.c lib_mkdtemp.c CSRCS += lib_aligned_alloc.c lib_posix_memalign.c lib_valloc.c lib_mblen.c diff --git a/libs/libc/stdlib/lib_rand48.c b/libs/libc/stdlib/lib_rand48.c new file mode 100644 index 0000000000..5d083d06aa --- /dev/null +++ b/libs/libc/stdlib/lib_rand48.c @@ -0,0 +1,202 @@ +/**************************************************************************** + * libs/libc/stdlib/lib_rand48.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static unsigned short int g_seed48[7] = +{ + 0, + 0, + 0, + 0xe66d, + 0xdeec, + 0x5, + 0xb +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef CONFIG_HAVE_LONG_LONG +static uint64_t rand48_step(FAR unsigned short int *xi, + FAR unsigned short int *lc) +{ + uint64_t a; + uint64_t x; + + x = xi[0] | ((xi[1] + 0ul) << 16) | ((xi[2] + 0ull) << 32); + a = lc[0] | ((lc[1] + 0ul) << 16) | ((lc[2] + 0ull) << 32); + x = a * x + lc[3]; + + xi[0] = x; + xi[1] = x >> 16; + xi[2] = x >> 32; + return x & 0xffffffffffffull; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: srand48 + ****************************************************************************/ + +void srand48(long seed) +{ + unsigned short int p[3]; + + p[0] = 0x330e; + p[1] = seed; + p[2] = seed >> 16; + seed48(p); +} + +/**************************************************************************** + * Name: seed48 + ****************************************************************************/ + +FAR unsigned short int *seed48(FAR unsigned short int seed16v[3]) +{ + static unsigned short int p[3]; + + memcpy(p, g_seed48, sizeof(p)); + memcpy(g_seed48, seed16v, sizeof(p)); + return p; +} + +/**************************************************************************** + * Name: lcong48 + ****************************************************************************/ + +void lcong48(FAR unsigned short int p[7]) +{ + memcpy(g_seed48, p, sizeof(g_seed48)); +} + +/**************************************************************************** + * Name: jrand48 + * + * Description: + * Return signed long integers uniformly distributed over the + * interval [-2^31, 2^31). + * + ****************************************************************************/ + +#ifdef CONFIG_HAVE_LONG_LONG +long jrand48(FAR unsigned short int s[3]) +{ + return (long)(rand48_step(s, g_seed48 + 3) >> 16); +} + +/**************************************************************************** + * Name: mrand48 + * + * Description: + * Return signed long integers uniformly distributed over the + * interval [-2^31, 2^31). + * + ****************************************************************************/ + +long mrand48(void) +{ + return jrand48(g_seed48); +} + +/**************************************************************************** + * Name: nrand48 + * + * Description: + * Return nonnegative long integers uniformly distributed over the + * interval [0, 2^31). + * + ****************************************************************************/ + +long nrand48(FAR unsigned short int s[3]) +{ + return rand48_step(s, g_seed48 + 3) >> 17; +} + +/**************************************************************************** + * Name: lrand48 + * + * Description: + * Return nonnegative long integers uniformly distributed over the + * interval [0, 2^31). + * + ****************************************************************************/ + +long lrand48(void) +{ + return nrand48(g_seed48); +} + +/**************************************************************************** + * Name: erand48 + * + * Description: + * Return nonnegative double-precision floating-point values uniformly + * distributed over the interval [0.0, 1.0). + * + ****************************************************************************/ + +# ifdef CONFIG_HAVE_DOUBLE +double erand48(FAR unsigned short int s[3]) +{ + union + { + uint64_t u; + double f; + } x; + + x.u = 0x3ff0000000000000ull | rand48_step(s, g_seed48 + 3) << 4; + return x.f - 1.0; +} + +/**************************************************************************** + * Name: drand48 + * + * Description: + * Return nonnegative double-precision floating-point values uniformly + * distributed over the interval [0.0, 1.0). + * + ****************************************************************************/ + +double drand48(void) +{ + return erand48(g_seed48); +} +# endif +#endif