This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Part 5 of a big cleanup action based on the upcoming dist-4.0
[metaconfig.git] / U / compline / randfunc.U
1 ?RCS: $Id: randfunc.U,v 3.0 1993/08/18 12:09:39 ram Exp $
2 ?RCS:
3 ?RCS: Copyright (c) 1991-1993, Raphael Manfredi
4 ?RCS: 
5 ?RCS: You may redistribute only under the terms of the Artistic Licence,
6 ?RCS: as specified in the README file that comes with the distribution.
7 ?RCS: You may reuse parts of this distribution only within the terms of
8 ?RCS: that same Artistic Licence; a copy of which may be found at the root
9 ?RCS: of the source tree for dist 3.0.
10 ?RCS:
11 ?RCS: $Log: randfunc.U,v $
12 ?RCS: Revision 3.0  1993/08/18  12:09:39  ram
13 ?RCS: Baseline for dist 3.0 netwide release.
14 ?RCS:
15 ?X:
16 ?X:     This is the new unit that should be used when random
17 ?X:     functions are to be used. It thus makes randbits.U obsolete.
18 ?X:
19 ?X:     This unit gives a simple #define for Drand01, which produces
20 ?X:     doubles in the range [0,1) using the "best" random number
21 ?X:     generator available.  The source should just call Drand01
22 ?X:     and not worry about the underlying implementation.
23 ?X:         Andy Dougherty  July 1998
24 ?X:
25 ?MAKE:randfunc drand01 seedfunc randbits randseedtype: \
26         cat rm_try test i_stdlib i_unistd Compile Myread Csym ccflags
27 ?MAKE:  -pick add $@ %<
28 ?S:randfunc:
29 ?S:     Indicates the name of the random number function to use.
30 ?S:     Values include drand48, random, and rand. In C programs,
31 ?S:     the 'Drand01' macro is defined to generate uniformly distributed
32 ?S:     random numbers over the range [0., 1.[ (see drand01 and nrand).
33 ?S:.
34 ?S:drand01:
35 ?S:     Indicates the macro to be used to generate normalized
36 ?S:     random numbers.  Uses randfunc, often divided by
37 ?S:     (double) (((unsigned long) 1 << randbits)) in order to
38 ?S:     normalize the result.
39 ?S:     In C programs, the macro 'Drand01' is mapped to drand01.
40 ?S:.
41 ?S:randseedtype:
42 ?S:     Indicates the type of the argument of the seedfunc.
43 ?S:.
44 ?S:seedfunc:
45 ?S:     Indicates the random number generating seed function.
46 ?S:     Values include srand48, srandom, and srand.
47 ?S:.
48 ?S:randbits:
49 ?S:     Indicates how many bits are produced by the function used to
50 ?S:     generate normalized random numbers.
51 ?S:.
52 ?C:RANDFUNC:
53 ?C:     This symbol defines the random function used to define Drand01().
54 ?C:.
55 ?C:Drand01:
56 ?C:     This macro is to be used to generate uniformly distributed
57 ?C:     random numbers over the range [0., 1.[.  You may have to supply
58 ?C:     an 'extern double drand48();' in your program since SunOS 4.1.3
59 ?C:     doesn't provide you with anything relevant in its headers.
60 ?C:     See HAS_DRAND48_PROTO.
61 ?C:.
62 ?C:Rand_seed_t:
63 ?C:     This symbol defines the type of the argument of the
64 ?C:     random seed function.
65 ?C:.
66 ?C:seedDrand01:
67 ?C:     This symbol defines the macro to be used in seeding the
68 ?C:     random number generator (see Drand01).
69 ?C:.
70 ?C:RANDBITS:
71 ?C:     This symbol indicates how many bits are produced by the
72 ?C:     function used to generate normalized random numbers.
73 ?C:     Values include 15, 16, 31, and 48.
74 ?C:.
75 ?H:#define RANDFUNC             $randfunc               /**/
76 ?H:#define Drand01()            $drand01                /**/
77 ?H:#define Rand_seed_t          $randseedtype           /**/
78 ?H:#define seedDrand01(x)       $seedfunc((Rand_seed_t)x)       /**/
79 ?H:#define RANDBITS             $randbits               /**/
80 ?H:.
81 ?T:cont val
82 ?LINT:change ccflags
83 ?LINT:unclosed $randbits))"
84 : How can we generate normalized random numbers ?
85 echo " "
86 echo "Looking for a random number function..." >&4
87 case "$randfunc" in
88 '')
89         if set drand48 val -f; eval $csym; $val; then
90                 dflt="drand48"
91                 echo "Good, found drand48()." >&4
92         elif set random val -f; eval $csym; $val; then
93                 dflt="random"
94                 echo "OK, found random()." >&4
95         else
96                 dflt="rand"
97                 echo "Yick, looks like I have to use rand()." >&4
98         fi
99         echo " "
100         ;;
101 *)
102         dflt="$randfunc"
103         ;;
104 esac
105 cont=true
106
107 case "$ccflags" in
108 *-Dmy_rand=*|*-Dmy_srand=*)
109         echo "Removing obsolete -Dmy_rand, -Dmy_srand, and -Drandbits from ccflags." >&4
110         ccflags="`echo $ccflags | sed -e 's/-Dmy_rand=random/ /'`"
111         ccflags="`echo $ccflags | sed -e 's/-Dmy_srand=srandom/ /'`"
112         ccflags="`echo $ccflags | sed -e 's/-Drandbits=[0-9][0-9]*/ /'`"
113         ;;
114 esac
115
116 while $test "$cont"; do
117         rp="Use which function to generate random numbers?"
118         . ./myread
119 ?X:     Invalidate randbits if the answer is not the default so
120 ?X:     that the value stored in config.sh will not be used when
121 ?X:     we change our random function.
122         if $test "$ans" = "$dflt"; then
123                 : null
124         else
125                 randbits=''
126         fi
127         randfunc="$ans"
128         if set $ans val -f; eval $csym; $val; then
129                 cont=''
130         else
131                 dflt=y
132                 rp="I cannot find function $ans. Use that name anyway?"
133                 . ./myread
134                 dflt=rand
135                 case "$ans" in
136                         [yY]*) cont='';;
137                 esac
138         fi
139         case "$cont" in
140         '')
141                 case "$randfunc" in
142                 drand48)
143                         drand01="drand48()"
144                         seedfunc="srand48"
145                         randbits=48
146                         randseedtype=long
147                         ;;
148                 rand|random)
149                         case "$randbits" in
150                         '')
151 echo "Checking to see how many bits your $randfunc() function produces..." >&4
152                                 $cat >try.c <<EOCP
153 #$i_unistd I_UNISTD
154 #$i_stdlib I_STDLIB
155 #include <stdio.h>
156 #ifdef I_UNISTD
157 #  include <unistd.h>
158 #endif
159 #ifdef I_STDLIB
160 #  include <stdlib.h>
161 #endif
162 int main()
163 {
164         register int i;
165         register unsigned long tmp;
166         register unsigned long max = 0L;
167
168         for (i = 1000; i; i--) {
169                 tmp = (unsigned long) $randfunc();
170                 if (tmp > max) max = tmp;
171         }
172         for (i = 0; max; i++)
173                 max /= 2;
174         printf("%d\n",i);
175 }
176 EOCP
177                                 set try
178                                 if eval $compile_ok; then
179                                         dflt=`try`
180                                 else
181                                         dflt='?'
182                                         echo "(I can't seem to compile the test program...)"
183                                 fi
184                                 ;;
185                         *)
186                                 dflt="$randbits"
187                                 ;;
188                         esac
189                         rp="How many bits does your $randfunc() function produce?"
190                         . ./myread
191                         randbits="$ans"
192                         $rm_try
193                         drand01="($randfunc() / (double) ((unsigned long)1 << $randbits))"
194                         seedfunc="s$randfunc"
195                         randseedtype=unsigned
196                         ;;
197 ?X:     The following is provided just in case...
198                 *)
199                         dflt="31"
200                         rp="How many bits does your $randfunc() function produce?"
201                         . ./myread
202                         randbits="$ans"
203                         seedfunc="s$randfunc"
204                         drand01="($randfunc() / (double) ((unsigned long)1 << $randbits))"
205                         if set $seedfunc val -f; eval $csym; $val; then
206                                 echo "(Using $seedfunc() to seed random generator)"
207                         else
208                                 echo "(Warning: no $seedfunc() to seed random generator)"
209                                 seedfunc=rand
210                         fi
211                         randseedtype=unsigned
212                         ;;
213                 esac
214                 ;;
215         esac
216 done
217