/* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2004 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU General Public License v.2. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "random.h" #include "log.h" int32_t _a[56]; int32_t *_r; static inline int32_t _mod_diff(int32_t x, int32_t y) { return (x - y) & 0x7fffffff; } static int32_t _flip_cycle(void) { int32_t *ii, *jj; for (ii = _a + 1, jj = _a + 32; jj <= _a + 55; ii++, jj++) *ii = _mod_diff(*ii, *jj); for (jj = _a + 1; ii <= _a + 55; ii++, jj++) *ii = _mod_diff(*ii, *jj); _r = _a + 54; return _a[55]; } static void rand_init(int32_t seed) { int64_t i; int64_t prev = seed, next = 1; seed = prev = _mod_diff(prev, 0); /* strip the sign */ _a[55] = prev; for (i = 21; i; i = (i + 21) % 55) { _a[i] = next; next = _mod_diff(prev, next); if(seed & 1) seed = 0x40000000L + (seed >> 1); else seed >>= 1; next = _mod_diff(next, seed); prev = _a[i]; } _flip_cycle(); _flip_cycle(); _flip_cycle(); _flip_cycle(); _flip_cycle(); } /* * FIXME: move this to be an inline in the * header. */ int32_t rand_get(void) { return (*_r >= 0) ? *_r-- : _flip_cycle(); } /* * just used by rand_check */ #define t31 0x80000000 static int32_t _uniform(int32_t m) { uint32_t t = t31 - (t31 % m); int32_t r; do r = next_rand(sc); while (t <= (uint32_t) r); return r % m; } /* * Checks I've copied the code correctly. */ int rand_check(void) { int j; rand_init(-314159L); if (next_rand(sc) != 119318998) { log_err("Random number generator failed check 1"); return 0; } for(j = 1; j <= 133; j++) rand_get(); if (_uniform(0x55555555L) != 748103812) { log_err("Random number generator failed check 2"); return 0; } return 1; }