random.c 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * $RANDOM support.
  4. *
  5. * Copyright (C) 2009 Denys Vlasenko
  6. *
  7. * Licensed under GPLv2, see file LICENSE in this tarball for details.
  8. */
  9. #include "libbb.h"
  10. #include "random.h"
  11. uint32_t FAST_FUNC
  12. next_random(random_t *rnd)
  13. {
  14. /* Galois LFSR parameter */
  15. /* Taps at 32 31 29 1: */
  16. enum { MASK = 0x8000000b };
  17. /* Another example - taps at 32 31 30 10: */
  18. /* MASK = 0x00400007 */
  19. uint32_t t;
  20. if (UNINITED_RANDOM_T(rnd)) {
  21. /* Can use monotonic_ns() for better randomness but for now
  22. * it is not used anywhere else in busybox... so avoid bloat
  23. */
  24. INIT_RANDOM_T(rnd, getpid(), monotonic_us());
  25. }
  26. /* LCG has period of 2^32 and alternating lowest bit */
  27. rnd->LCG = 1664525 * rnd->LCG + 1013904223;
  28. /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
  29. t = (rnd->galois_LFSR << 1);
  30. if (rnd->galois_LFSR < 0) /* if we just shifted 1 out of msb... */
  31. t ^= MASK;
  32. rnd->galois_LFSR = t;
  33. /* Both are weak, combining them gives better randomness
  34. * and ~2^64 period. & 0x7fff is probably bash compat
  35. * for $RANDOM range. Combining with subtraction is
  36. * just for fun. + and ^ would work equally well. */
  37. t = (t - rnd->LCG) & 0x7fff;
  38. return t;
  39. }