diff --git a/bin/tools/pre-commit-hook b/bin/tools/pre-commit-hook index b0ca86f0202a82db0fa2b32c12ef314ae9bb202a..b06ddd50b6bf83fbc5af17ed00f4dfdcb4a186f1 100755 --- a/bin/tools/pre-commit-hook +++ b/bin/tools/pre-commit-hook @@ -49,9 +49,10 @@ # test the specified files/directories for standards conformance. # #------------------------------------------------------------------------------ +hookName="pre-commit" die() { - echo 'pre-commit hook failure' 1>&2 + echo '$hookName hook failure' 1>&2 echo '-----------------------' 1>&2 echo '' 1>&2 echo "$@" 1>&2 @@ -104,7 +105,7 @@ dieOnBadFiles() { if [ -n "$badFiles" ] then - echo 'pre-commit hook failure' 1>&2 + echo '$hookName hook failure' 1>&2 echo '-----------------------' 1>&2 echo "$@" 1>&2 echo '' 1>&2 @@ -116,22 +117,38 @@ dieOnBadFiles() } +# +# qualify 'git grep' to check cached value or from a specific commit +# +gitScope() +{ + if [ "$#" -gt 0 ] + then + echo "$1:" + else + echo "--cached -- " + fi +} + + # # check for bad strings, characters, etc # checkIllegalCode() { - echo "pre-commit: check bad strings/characters etc ..." 1>&2 + echo "$hookName: check bad strings/characters etc ..." 1>&2 reBad="(N""abla|"$'\t'")" msgBad="N""abla or <TAB>" + scope=$(gitScope $@) + badFiles=$( for f in $fileList do # parse line numbers from grep output: # <lineNr>: contents - lines=$(git grep --cached -E -hn -e "$reBad" -- "$f" | + lines=$(git grep -E -hn -e "$reBad" $scope"$f" | sed -e 's@:.*@@' | tr '\n' ' ' ) @@ -149,7 +166,9 @@ checkIllegalCode() checkCopyright() { year=$(date +%Y) - echo "pre-commit: check copyright ..." 1>&2 + echo "$hookName: check copyright ..." 1>&2 + + scope=$(gitScope $@) badFiles=$( for f in $fileList @@ -160,10 +179,10 @@ checkCopyright() # parse line numbers from grep output: # <lineNr>: contents # - lines=$(git grep --cached -F -hn -e Copyright \ + lines=$(git grep -F -hn -e Copyright \ --and -e OpenCFD \ --and --not -e "$year" \ - -- "$f" | + $scope"$f" | sed -e 's@:.*@@' | tr '\n' ' ' ) @@ -180,7 +199,9 @@ checkCopyright() # checkLineLength() { - echo "pre-commit: check line lengths ..." 1>&2 + echo "$hookName: check line lengths ..." 1>&2 + + scope=$(gitScope $@) badFiles=$( for f in $fileList @@ -190,7 +211,7 @@ checkLineLength() (*.[CH]) # parse line numbers from grep output: # <lineNr>: contents - lines=$(git grep --cached -hn -e '^.\{81,\}' -- "$f" | + lines=$(git grep -hn -e '^.\{81,\}' $scope"$f" | sed -e 's@:.*@@' | tr '\n' ' ' ) @@ -209,7 +230,9 @@ checkLineLength() # checkLineLengthNonComments() { - echo "pre-commit: check line lengths ..." 1>&2 + echo "$hookName: check line lengths ..." 1>&2 + + scope=$(gitScope $@) badFiles=$( for f in $fileList @@ -219,9 +242,9 @@ checkLineLengthNonComments() (*.[CH]) # parse line numbers from grep output: # <lineNr>: contents - lines=$(git grep --cached -hn -e '^.\{81,\}' \ + lines=$(git grep -hn -e '^.\{81,\}' \ --and --not -e "^ *//" \ - -- "$f" | + $scope"$f" | sed -e 's@:.*@@' | tr '\n' ' ' ) @@ -234,12 +257,15 @@ checkLineLengthNonComments() dieOnBadFiles "Limit code to 80 columns before pushing" } + # # limit line length to 80-columns, except #directive lines # checkLineLengthNonDirective() { - echo "pre-commit: check line lengths ..." 1>&2 + echo "$hookName: check line lengths ..." 1>&2 + + scope=$(gitScope $@) badFiles=$( for f in $fileList @@ -249,9 +275,9 @@ checkLineLengthNonDirective() (*.[CH]) # parse line numbers from grep output: # <lineNr>: contents - lines=$(git grep --cached -hn -e '^.\{81,\}' \ + lines=$(git grep -hn -e '^.\{81,\}' \ --and --not -e "^ *#" \ - -- "$f" | + $scope"$f" | sed -e 's@:.*@@' | tr '\n' ' ' ) @@ -265,9 +291,9 @@ checkLineLengthNonDirective() } - -# do all checks -# ~~~~~~~~~~~~~ +#------------------------------------------------------------------------------ +# Main code : do all checks +# # builtin whitespace check to avoid trailing space, including CR-LF endings bad=$(git diff-index --cached --check $against --) || die "$bad" diff --git a/bin/tools/pre-receive-hook b/bin/tools/pre-receive-hook new file mode 100755 index 0000000000000000000000000000000000000000..f289b99be702a3b94179713f069751ed09a2bd27 --- /dev/null +++ b/bin/tools/pre-receive-hook @@ -0,0 +1,303 @@ +#!/bin/bash +#---------------------------------*- sh -*------------------------------------- +# ========= | +# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox +# \\ / O peration | +# \\ / A nd | Copyright (C) 2010-2010 OpenCFD Ltd. +# \\/ M anipulation | +#------------------------------------------------------------------------------ +# License +# This file is part of OpenFOAM. +# +# OpenFOAM is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OpenFOAM is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License +# along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. +# +# Script +# pre-receive-hook +# +# Description +# pre-receive hook for git. +# Copy or link this file as ".git/hooks/pre-receive" +# +# Eg, +# ( +# cd $WM_PROJECT_DIR/.git/hooks && +# ln -sf ../../bin/tools/pre-receive-hook pre-receive +# ) +# +# Hook receives: <old-sha1> <new-sha1> <ref-name> +# +# Checks for +# - illegal code, e.g. <TAB> +# - copyright is current, e.g. if present, contains XXX-<current-year> +# - columns greater than 80 for *.[CH] files +# +#------------------------------------------------------------------------------ +hookName="pre-receive" +die() +{ + echo '$hookName hook failure' 1>&2 + echo '-----------------------' 1>&2 + echo '' 1>&2 + echo "$@" 1>&2 + echo '' 1>&2 + exit 1 +} + +#----------------------------------------------------------------------------- + +unset fileList +unset badFiles +# join list of files with this amount of space +Indent=" " + +# +# report bad files and die if there are any +# +dieOnBadFiles() +{ + if [ -n "$badFiles" ] + then + echo '$hookName hook failure' 1>&2 + echo '-----------------------' 1>&2 + echo "$@" 1>&2 + echo '' 1>&2 + echo "File(s):" 1>&2 + echo "$badFiles" 1>&2 + echo '' 1>&2 + exit 1 + fi +} + + +# +# qualify 'git grep' to check cached value or from a specific commit +# +gitScope() +{ + if [ "$#" -gt 0 ] + then + echo "$1:" + else + echo "--cached -- " + fi +} + + +# +# check for bad strings, characters, etc +# +checkIllegalCode() +{ + echo "$hookName: check bad strings/characters etc ..." 1>&2 + + reBad="(N""abla|"$'\t'"|"$'\r\n'")" + msgBad="N""abla, <TAB> or DOS-line-endings" + + scope=$(gitScope $@) + + badFiles=$( + for f in $fileList + do + # parse line numbers from grep output: + # <lineNr>: contents + lines=$(git grep -E -hn -e "$reBad" $scope"$f" | + sed -e 's@:.*@@' | + tr '\n' ' ' + ) + [ -n "$lines" ] && echo "$Indent$f -- lines: $lines" + done + ) + + dieOnBadFiles "Remove/correct bad '$msgBad' references" +} + + +# +# check that OpenCFD copyright is current +# +checkCopyright() +{ + year=$(date +%Y) + echo "$hookName: check copyright ..." 1>&2 + + scope=$(gitScope $@) + + badFiles=$( + for f in $fileList + do + # NB: need to have OpenCFD on a separate line to prevent + # this check being caught by itself! + # + # parse line numbers from grep output: + # <lineNr>: contents + # + lines=$(git grep -F -hn -e Copyright \ + --and -e OpenCFD \ + --and --not -e "$year" \ + $scope"$f" | + sed -e 's@:.*@@' | + tr '\n' ' ' + ) + [ -n "$lines" ] && echo "$Indent$f -- lines: $lines" + done + ) + + dieOnBadFiles "Update copyright year, e.g. XXXX-$year" +} + + +# +# limit line length to 80-columns +# +checkLineLength() +{ + echo "$hookName: check line lengths ..." 1>&2 + + scope=$(gitScope $@) + + badFiles=$( + for f in $fileList + do + # limit to *.[CH] files + case "$f" in + (*.[CH]) + # parse line numbers from grep output: + # <lineNr>: contents + lines=$(git grep -hn -e '^.\{81,\}' $scope"$f" | + sed -e 's@:.*@@' | + tr '\n' ' ' + ) + [ -n "$lines" ] && echo "$Indent$f -- lines: $lines" + ;; + esac + done + ) + + dieOnBadFiles "Limit code to 80 columns before pushing" +} + + +# +# limit line length to 80-columns, except C++ comment lines +# +checkLineLengthNonComments() +{ + echo "$hookName: check line lengths ..." 1>&2 + + scope=$(gitScope $@) + + badFiles=$( + for f in $fileList + do + # limit to *.[CH] files + case "$f" in + (*.[CH]) + # parse line numbers from grep output: + # <lineNr>: contents + lines=$(git grep -hn -e '^.\{81,\}' \ + --and --not -e "^ *//" \ + $scope"$f" | + sed -e 's@:.*@@' | + tr '\n' ' ' + ) + [ -n "$lines" ] && echo "$Indent$f -- lines: $lines" + ;; + esac + done + ) + + dieOnBadFiles "Limit code to 80 columns before pushing" +} + + +# +# limit line length to 80-columns, except #directive lines +# +checkLineLengthNonDirective() +{ + echo "$hookName: check line lengths ..." 1>&2 + + scope=$(gitScope $@) + + badFiles=$( + for f in $fileList + do + # limit to *.[CH] files + case "$f" in + (*.[CH]) + # parse line numbers from grep output: + # <lineNr>: contents + lines=$(git grep -hn -e '^.\{81,\}' \ + --and --not -e "^ *#" \ + $scope"$f" | + sed -e 's@:.*@@' | + tr '\n' ' ' + ) + [ -n "$lines" ] && echo "$Indent$f -- lines: $lines" + ;; + esac + done + ) + + dieOnBadFiles "Limit code to 80 columns before pushing" +} + + +#------------------------------------------------------------------------------ +# Main code : do all checks +# + +while read oldSHA1 newSHA1 refName +do + unset fileList rawFileList + + if [ "$newSHA1" = 0 ] + then + # ref to be deleted + continue + elif [ "$oldSHA1" = 0 ] + then + # ref to be created + rawFileList=$(git diff-tree --root $newSHA1) + else + # normal changes + rawFileList=$(git diff --name-only $oldSHA1..$newSHA1) + fi + + # + # no files changed: can skip all the checks + # + [ -n "$rawFileList" ] || continue + + fileList=$( + for f in $rawFileList + do + git cat-file -e $newSHA1:$f > /dev/null 2>&1 && echo "$f" + done + ) + + # check for illegal code, e.g. <TAB>, etc + checkIllegalCode $newSHA1 + + # ensure OpenCFD copyright contains correct year + checkCopyright $newSHA1 + + # ensure code conforms to 80 columns max + checkLineLengthNonDirective $newSHA1 + +done + + +exit 0 +#------------------------------------------------------------------------------ diff --git a/src/OpenFOAM/primitives/random/Random/random.3 b/src/OpenFOAM/primitives/random/Random/random.3 deleted file mode 100644 index 8a0af2ca4f41ac30c56726ad5d12c89ad5079a8c..0000000000000000000000000000000000000000 --- a/src/OpenFOAM/primitives/random/Random/random.3 +++ /dev/null @@ -1,168 +0,0 @@ -.\" $NetBSD: random.3,v 1.4 1995/12/28 08:52:42 thorpej Exp $ -.\" -.\" Copyright (c) 1983, 1991 The Regents of the University of California. -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" from: @(#)random.3 6.5 (Berkeley) 4/19/91 -.\" -.Dd April 19, 1991 -.Dt RANDOM 3 -.Os BSD 4.2 -.Sh NAME -.Nm random , -.Nm srandom , -.Nm initstate , -.Nm setstate -.Nd better random number generator; routines for changing generators -.Sh SYNOPSIS -.Fd #include <stdlib.h> -.Ft long -.Fn random void -.Ft void -.Fn srandom "unsigned seed" -.Ft char * -.Fn initstate "unsigned seed" "char *state" "int n" -.Ft char * -.Fn setstate "char *state" -.Sh DESCRIPTION -The -.Fn random -function -uses a non-linear additive feedback random number generator employing a -default table of size 31 long integers to return successive pseudo-random -numbers in the range from 0 to -.if t 2\u\s731\s10\d\(mi1. -.if n (2**31)\(mi1. -The period of this random number generator is very large, approximately -.if t 16\(mu(2\u\s731\s10\d\(mi1). -.if n 16*((2**31)\(mi1). -.Pp -The -.Fn random Ns / Fn srandom -have (almost) the same calling sequence and initialization properties as -.Xr rand 3 Ns / Xr srand 3 . -The difference is that -.Xr rand -produces a much less random sequence \(em in fact, the low dozen bits -generated by rand go through a cyclic pattern. All the bits generated by -.Fn random -are usable. For example, -.Sq Li random()&01 -will produce a random binary -value. -.Pp -Unlike -.Xr srand , -.Fn srandom -does not return the old seed; the reason for this is that the amount of -state information used is much more than a single word. (Two other -routines are provided to deal with restarting/changing random -number generators). Like -.Xr rand 3 , -however, -.Fn random -will by default produce a sequence of numbers that can be duplicated -by calling -.Fn srandom -with -.Ql 1 -as the seed. -.Pp -The -.Fn initstate -routine allows a state array, passed in as an argument, to be initialized -for future use. The size of the state array (in bytes) is used by -.Fn initstate -to decide how sophisticated a random number generator it should use \(em the -more state, the better the random numbers will be. -(Current "optimal" values for the amount of state information are -8, 32, 64, 128, and 256 bytes; other amounts will be rounded down to -the nearest known amount. Using less than 8 bytes will cause an error.) -The seed for the initialization (which specifies a starting point for -the random number sequence, and provides for restarting at the same -point) is also an argument. -The -.Fn initstate -function -returns a pointer to the previous state information array. -.Pp -Once a state has been initialized, the -.Fn setstate -routine provides for rapid switching between states. -The -.Fn setstate -function -returns a pointer to the previous state array; its -argument state array is used for further random number generation -until the next call to -.Fn initstate -or -.Fn setstate . -.Pp -Once a state array has been initialized, it may be restarted at a -different point either by calling -.Fn initstate -(with the desired seed, the state array, and its size) or by calling -both -.Fn setstate -(with the state array) and -.Fn srandom -(with the desired seed). -The advantage of calling both -.Fn setstate -and -.Fn srandom -is that the size of the state array does not have to be remembered after -it is initialized. -.Pp -With 256 bytes of state information, the period of the random number -generator is greater than -.if t 2\u\s769\s10\d, -.if n 2**69 -which should be sufficient for most purposes. -.Sh AUTHOR -Earl T. Cohen -.Sh DIAGNOSTICS -If -.Fn initstate -is called with less than 8 bytes of state information, or if -.Fn setstate -detects that the state information has been garbled, error -messages are printed on the standard error output. -.Sh SEE ALSO -.Xr rand 3 -.Sh HISTORY -These -functions appeared in -.Bx 4.2 . -.Sh BUGS -About 2/3 the speed of -.Xr rand 3 . diff --git a/src/OpenFOAM/primitives/random/Random/random.c b/src/OpenFOAM/primitives/random/Random/random.c deleted file mode 100644 index a2d6ac021a249e2fafdd6791ada6c4ade32edc64..0000000000000000000000000000000000000000 --- a/src/OpenFOAM/primitives/random/Random/random.c +++ /dev/null @@ -1,369 +0,0 @@ -/* $NetBSD: random.c,v 1.4 1995/12/28 08:52:43 thorpej Exp $ */ - -/* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -#if 0 -static char *sccsid = "from: @(#)random.c 5.9 (Berkeley) 2/23/91"; -#else -static char *rcsid = "$NetBSD: random.c,v 1.4 1995/12/28 08:52:43 thorpej Exp $"; -#endif -#endif /* LIBC_SCCS and not lint */ - -#include <stdio.h> -#include <stdlib.h> - -/* - * random.c: - * - * An improved random number generation package. In addition to the standard - * rand()/srand() like interface, this package also has a special state info - * interface. The initstate() routine is called with a seed, an array of - * bytes, and a count of how many bytes are being passed in; this array is - * then initialized to contain information for random number generation with - * that much state information. Good sizes for the amount of state - * information are 32, 64, 128, and 256 bytes. The state can be switched by - * calling the setstate() routine with the same array as was initiallized - * with initstate(). By default, the package runs with 128 bytes of state - * information and generates far better random numbers than a linear - * congruential generator. If the amount of state information is less than - * 32 bytes, a simple linear congruential R.N.G. is used. - * - * Internally, the state information is treated as an array of longs; the - * zeroeth element of the array is the type of R.N.G. being used (small - * integer); the remainder of the array is the state information for the - * R.N.G. Thus, 32 bytes of state information will give 7 longs worth of - * state information, which will allow a degree seven polynomial. (Note: - * the zeroeth word of state information also has some other information - * stored in it -- see setstate() for details). - * - * The random number generation technique is a linear feedback shift register - * approach, employing trinomials (since there are fewer terms to sum up that - * way). In this approach, the least significant bit of all the numbers in - * the state table will act as a linear feedback shift register, and will - * have period 2^deg - 1 (where deg is the degree of the polynomial being - * used, assuming that the polynomial is irreducible and primitive). The - * higher order bits will have longer periods, since their values are also - * influenced by pseudo-random carries out of the lower bits. The total - * period of the generator is approximately deg*(2**deg - 1); thus doubling - * the amount of state information has a vast influence on the period of the - * generator. Note: the deg*(2**deg - 1) is an approximation only good for - * large deg, when the period of the shift register is the dominant factor. - * With deg equal to seven, the period is actually much longer than the - * 7*(2**7 - 1) predicted by this formula. - */ - -/* - * For each of the currently supported random number generators, we have a - * break value on the amount of state information (you need at least this - * many bytes of state info to support this random number generator), a degree - * for the polynomial (actually a trinomial) that the R.N.G. is based on, and - * the separation between the two lower order coefficients of the trinomial. - */ -#define TYPE_0 0 /* linear congruential */ -#define BREAK_0 8 -#define DEG_0 0 -#define SEP_0 0 - -#define TYPE_1 1 /* x**7 + x**3 + 1 */ -#define BREAK_1 32 -#define DEG_1 7 -#define SEP_1 3 - -#define TYPE_2 2 /* x**15 + x + 1 */ -#define BREAK_2 64 -#define DEG_2 15 -#define SEP_2 1 - -#define TYPE_3 3 /* x**31 + x**3 + 1 */ -#define BREAK_3 128 -#define DEG_3 31 -#define SEP_3 3 - -#define TYPE_4 4 /* x**63 + x + 1 */ -#define BREAK_4 256 -#define DEG_4 63 -#define SEP_4 1 - -/* - * Array versions of the above information to make code run faster -- - * relies on fact that TYPE_i == i. - */ -#define MAX_TYPES 5 /* max number of types above */ - -static int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 }; -static int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 }; - -/* - * Initially, everything is set up as if from: - * - * initstate(1, &randtbl, 128); - * - * Note that this initialization takes advantage of the fact that srandom() - * advances the front and rear pointers 10*rand_deg times, and hence the - * rear pointer which starts at 0 will also end up at zero; thus the zeroeth - * element of the state information, which contains info about the current - * position of the rear pointer is just - * - * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3. - */ - -static long randtbl[DEG_3 + 1] = { - TYPE_3, - 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5, - 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, - 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88, - 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, - 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b, - 0x27fb47b9, -}; - -/* - * fptr and rptr are two pointers into the state info, a front and a rear - * pointer. These two pointers are always rand_sep places aparts, as they - * cycle cyclically through the state information. (Yes, this does mean we - * could get away with just one pointer, but the code for random() is more - * efficient this way). The pointers are left positioned as they would be - * from the call - * - * initstate(1, randtbl, 128); - * - * (The position of the rear pointer, rptr, is really 0 (as explained above - * in the initialization of randtbl) because the state table pointer is set - * to point to randtbl[1] (as explained below). - */ -static long *fptr = &randtbl[SEP_3 + 1]; -static long *rptr = &randtbl[1]; - -/* - * The following things are the pointer to the state information table, the - * type of the current generator, the degree of the current polynomial being - * used, and the separation between the two pointers. Note that for efficiency - * of random(), we remember the first location of the state information, not - * the zeroeth. Hence it is valid to access state[-1], which is used to - * store the type of the R.N.G. Also, we remember the last location, since - * this is more efficient than indexing every time to find the address of - * the last element to see if the front and rear pointers have wrapped. - */ -static long *state = &randtbl[1]; -static int rand_type = TYPE_3; -static int rand_deg = DEG_3; -static int rand_sep = SEP_3; -static long *end_ptr = &randtbl[DEG_3 + 1]; - -/* - * srandom: - * - * Initialize the random number generator based on the given seed. If the - * type is the trivial no-state-information type, just remember the seed. - * Otherwise, initializes state[] based on the given "seed" via a linear - * congruential generator. Then, the pointers are set to known locations - * that are exactly rand_sep places apart. Lastly, it cycles the state - * information a given number of times to get rid of any initial dependencies - * introduced by the L.C.R.N.G. Note that the initialization of randtbl[] - * for default usage relies on values produced by this routine. - */ -void -srandom(x) - u_int x; -{ - register int i, j; - - if (rand_type == TYPE_0) - state[0] = x; - else { - j = 1; - state[0] = x; - for (i = 1; i < rand_deg; i++) - state[i] = 1103515245 * state[i - 1] + 12345; - fptr = &state[rand_sep]; - rptr = &state[0]; - for (i = 0; i < 10 * rand_deg; i++) - (void)random(); - } -} - -/* - * initstate: - * - * Initialize the state information in the given array of n bytes for future - * random number generation. Based on the number of bytes we are given, and - * the break values for the different R.N.G.'s, we choose the best (largest) - * one we can and set things up for it. srandom() is then called to - * initialize the state information. - * - * Note that on return from srandom(), we set state[-1] to be the type - * multiplexed with the current value of the rear pointer; this is so - * successive calls to initstate() won't lose this information and will be - * able to restart with setstate(). - * - * Note: the first thing we do is save the current state, if any, just like - * setstate() so that it doesn't matter when initstate is called. - * - * Returns a pointer to the old state. - */ -char * -initstate(seed, arg_state, n) - u_int seed; /* seed for R.N.G. */ - char *arg_state; /* pointer to state array */ - int n; /* # bytes of state info */ -{ - register char *ostate = (char *)(&state[-1]); - - if (rand_type == TYPE_0) - state[-1] = rand_type; - else - state[-1] = MAX_TYPES * (rptr - state) + rand_type; - if (n < BREAK_0) { - (void)fprintf(stderr, - "random: not enough state (%d bytes); ignored.\n", n); - return 0; - } - if (n < BREAK_1) { - rand_type = TYPE_0; - rand_deg = DEG_0; - rand_sep = SEP_0; - } else if (n < BREAK_2) { - rand_type = TYPE_1; - rand_deg = DEG_1; - rand_sep = SEP_1; - } else if (n < BREAK_3) { - rand_type = TYPE_2; - rand_deg = DEG_2; - rand_sep = SEP_2; - } else if (n < BREAK_4) { - rand_type = TYPE_3; - rand_deg = DEG_3; - rand_sep = SEP_3; - } else { - rand_type = TYPE_4; - rand_deg = DEG_4; - rand_sep = SEP_4; - } - state = &(((long *)arg_state)[1]); /* first location */ - end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */ - srandom(seed); - if (rand_type == TYPE_0) - state[-1] = rand_type; - else - state[-1] = MAX_TYPES*(rptr - state) + rand_type; - return(ostate); -} - -/* - * setstate: - * - * Restore the state from the given state array. - * - * Note: it is important that we also remember the locations of the pointers - * in the current state information, and restore the locations of the pointers - * from the old state information. This is done by multiplexing the pointer - * location into the zeroeth word of the state information. - * - * Note that due to the order in which things are done, it is OK to call - * setstate() with the same state as the current state. - * - * Returns a pointer to the old state information. - */ -char * -setstate(arg_state) - char *arg_state; -{ - register long *new_state = (long *)arg_state; - register int type = new_state[0] % MAX_TYPES; - register int rear = new_state[0] / MAX_TYPES; - char *ostate = (char *)(&state[-1]); - - if (rand_type == TYPE_0) - state[-1] = rand_type; - else - state[-1] = MAX_TYPES * (rptr - state) + rand_type; - switch(type) { - case TYPE_0: - case TYPE_1: - case TYPE_2: - case TYPE_3: - case TYPE_4: - rand_type = type; - rand_deg = degrees[type]; - rand_sep = seps[type]; - break; - default: - (void)fprintf(stderr, - "random: state info corrupted; not changed.\n"); - } - state = &new_state[1]; - if (rand_type != TYPE_0) { - rptr = &state[rear]; - fptr = &state[(rear + rand_sep) % rand_deg]; - } - end_ptr = &state[rand_deg]; /* set end_ptr too */ - return(ostate); -} - -/* - * random: - * - * If we are using the trivial TYPE_0 R.N.G., just do the old linear - * congruential bit. Otherwise, we do our fancy trinomial stuff, which is - * the same in all the other cases due to all the global variables that have - * been set up. The basic operation is to add the number at the rear pointer - * into the one at the front pointer. Then both pointers are advanced to - * the next location cyclically in the table. The value returned is the sum - * generated, reduced to 31 bits by throwing away the "least random" low bit. - * - * Note: the code takes advantage of the fact that both the front and - * rear pointers can't wrap on the same call by not testing the rear - * pointer if the front one has wrapped. - * - * Returns a 31-bit random number. - */ -long -random() -{ - long i; - - if (rand_type == TYPE_0) - i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff; - else { - *fptr += *rptr; - i = (*fptr >> 1) & 0x7fffffff; /* chucking least random bit */ - if (++fptr >= end_ptr) { - fptr = state; - ++rptr; - } else if (++rptr >= end_ptr) - rptr = state; - } - return(i); -}