summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
Diffstat (limited to 'libc')
-rw-r--r--libc/stdlib/drand48-iter.c40
-rw-r--r--libc/stdlib/srand48_r.c6
2 files changed, 46 insertions, 0 deletions
diff --git a/libc/stdlib/drand48-iter.c b/libc/stdlib/drand48-iter.c
index a69d03326..3247bafbd 100644
--- a/libc/stdlib/drand48-iter.c
+++ b/libc/stdlib/drand48-iter.c
@@ -27,6 +27,7 @@
struct drand48_data __libc_drand48_data;
+#ifdef __UCLIBC_HAS_LONG_LONG__
int
__drand48_iterate (unsigned short int xsubi[3], struct drand48_data *buffer)
{
@@ -55,3 +56,42 @@ __drand48_iterate (unsigned short int xsubi[3], struct drand48_data *buffer)
return 0;
}
+
+#else
+int
+__drand48_iterate (unsigned short int xsubi[3], struct drand48_data *buffer)
+{
+ uint32_t X0, X1;
+ uint32_t result0, result1;
+
+ /* Initialize buffer, if not yet done. */
+ if (unlikely(!buffer->__init))
+ {
+ buffer->__a1 = 0x5;
+ buffer->__a0 = 0xdeece66d;
+ buffer->__c = 0xb;
+ buffer->__init = 1;
+ }
+
+ /* Do the real work. We choose a data type which contains at least
+ 48 bits. Because we compute the modulus it does not care how
+ many bits really are computed. */
+
+ /* X = X1*base32 + X0 */
+ X1 = xsubi[2];
+ X0 = xsubi[0] | (uint32_t) xsubi[1] << 16;
+
+ result0 = buffer->__a0 * X0;
+ result1 = (result0 > -buffer->__c ); /* Carry */
+ /* If this overflows, the carry is already in result1 */
+ result0 += buffer->__c;
+
+ result1 += buffer->__a1*X0 + buffer->__a0*X1;
+
+ xsubi[0] = result0 & 0xffff;
+ xsubi[1] = result0 >> 16;
+ xsubi[2] = result1 & 0xffff;
+
+ return 0;
+}
+#endif
diff --git a/libc/stdlib/srand48_r.c b/libc/stdlib/srand48_r.c
index c0fa38e90..c7c510864 100644
--- a/libc/stdlib/srand48_r.c
+++ b/libc/stdlib/srand48_r.c
@@ -32,7 +32,13 @@ int srand48_r (seedval, buffer)
buffer->__x[1] = seedval & 0xffffl;
buffer->__x[0] = 0x330e;
+#ifdef __UCLIBC_HAS_LONG_LONG__
buffer->__a = 0x5deece66dull;
+#else
+ buffer->__a1 = 0x5;
+ buffer->__a0 = 0xdeece66d;
+#endif
+
buffer->__c = 0xb;
buffer->__init = 1;