1 /* emacs edit mode for this file is -*- C++ -*- */
2 
3 
4 #include "config.h"
5 
6 
7 #include <time.h>
8 
9 #include "cf_assert.h"
10 
11 #include "cf_defs.h"
12 #include "cf_random.h"
13 #include "ffops.h"
14 #include "gfops.h"
15 #include "imm.h"
16 
17 #ifdef HAVE_FLINT
18 extern "C"
19 {
20 #ifndef __GMP_BITS_PER_MP_LIMB
21 #define __GMP_BITS_PER_MP_LIMB GMP_LIMB_BITS
22 #endif
23 #include <flint/flint.h>
24 
25 GLOBAL_VAR flint_rand_t FLINTrandom;
26 }
27 #endif
28 
29 class RandomGenerator {
30 private:
31     const int ia, im, iq, ir, deflt;
32     int s;
33 
34     // s must not equal zero!
seedInit(int ss)35     void seedInit( int ss ) { s = ((ss == 0) ? deflt : ss); }
36 public:
37     RandomGenerator();
38     RandomGenerator( int ss );
~RandomGenerator()39     ~RandomGenerator() {}
40     int generate();
seed(int ss)41     void seed( int ss ) { seedInit( ss ); }
42 };
43 
RandomGenerator()44 RandomGenerator::RandomGenerator() : ia(16807), im(2147483647), iq(127773), ir(2836), deflt(123459876)
45 {
46   seedInit( (int)time( 0 ) );
47 }
48 
RandomGenerator(int ss)49 RandomGenerator::RandomGenerator( int ss ) : ia(16807), im(2147483647), iq(127773), ir(2836), deflt(123459876)
50 {
51   seedInit( ss );
52 }
53 
54 int
generate()55 RandomGenerator::generate()
56 {
57     int k;
58 
59     k = s/iq;
60     s = ia*(s-k*iq)-ir*k;
61     if ( s < 0 ) s += im;
62 
63     return s;
64 }
65 
66 INST_VAR RandomGenerator ranGen;
67 
generate() const68 CanonicalForm FFRandom::generate () const
69 {
70     return CanonicalForm( int2imm_p( factoryrandom( ff_prime ) ) );
71 }
72 
clone() const73 CFRandom * FFRandom::clone () const
74 {
75     return new FFRandom();
76 }
77 
generate() const78 CanonicalForm GFRandom::generate () const
79 {
80     int i= factoryrandom( gf_q );
81     if ( i == gf_q1 ) i++;
82     return CanonicalForm( int2imm_gf( i ) );
83 }
84 
clone() const85 CFRandom * GFRandom::clone () const
86 {
87     return new GFRandom();
88 }
89 
90 
IntRandom()91 IntRandom::IntRandom()
92 {
93     max = 50;
94 }
95 
IntRandom(int m)96 IntRandom::IntRandom( int m )
97 {
98     max = m;
99 }
100 
~IntRandom()101 IntRandom::~IntRandom() {}
102 
generate() const103 CanonicalForm IntRandom::generate() const
104 {
105     return factoryrandom( 2*max )-max;
106 }
107 
clone() const108 CFRandom * IntRandom::clone() const
109 {
110     return new IntRandom( max );
111 }
112 
AlgExtRandomF()113 AlgExtRandomF::AlgExtRandomF()
114 {
115     ASSERT( 0, "not a valid random generator" );
116 }
117 
AlgExtRandomF(const AlgExtRandomF &)118 AlgExtRandomF::AlgExtRandomF( const AlgExtRandomF & )
119 {
120     ASSERT( 0, "not a valid random generator" );
121 }
122 
operator =(const AlgExtRandomF &)123 AlgExtRandomF& AlgExtRandomF::operator= ( const AlgExtRandomF & )
124 {
125     ASSERT( 0, "not a valid random generator" );
126     return *this;
127 }
128 
AlgExtRandomF(const Variable & v)129 AlgExtRandomF::AlgExtRandomF( const Variable & v )
130 {
131     ASSERT( v.level() < 0, "not an algebraic extension" );
132     algext = v;
133     n = degree( getMipo( v ) );
134     gen = CFRandomFactory::generate();
135 }
136 
AlgExtRandomF(const Variable & v1,const Variable & v2)137 AlgExtRandomF::AlgExtRandomF( const Variable & v1, const Variable & v2 )
138 {
139     ASSERT( v1.level() < 0 && v2.level() < 0 && v1 != v2, "not an algebraic extension" );
140     algext = v2;
141     n = degree( getMipo( v2 ) );
142     gen = new AlgExtRandomF( v1 );
143 }
144 
AlgExtRandomF(const Variable & v,CFRandom * g,int nn)145 AlgExtRandomF::AlgExtRandomF( const Variable & v, CFRandom * g, int nn )
146 {
147     algext = v;
148     n = nn;
149     gen = g;
150 }
151 
~AlgExtRandomF()152 AlgExtRandomF::~AlgExtRandomF()
153 {
154     delete gen;
155 }
156 
generate() const157 CanonicalForm AlgExtRandomF::generate() const
158 {
159     CanonicalForm result;
160     for ( int i = 0; i < n; i++ )
161       result += power( algext, i ) * gen->generate();
162     return result;
163 }
164 
clone() const165 CFRandom * AlgExtRandomF::clone () const
166 {
167     return new AlgExtRandomF( algext, gen->clone(), n );
168 }
169 
generate()170 CFRandom * CFRandomFactory::generate()
171 {
172     if ( getCharacteristic() == 0 )
173         return new IntRandom();
174     if ( getGFDegree() > 1 )
175         return new GFRandom();
176     else
177         return new FFRandom();
178 }
179 
factoryrandom(int n)180 int factoryrandom( int n )
181 {
182     if ( n == 0 )
183         return (int)ranGen.generate();
184     else
185         return ranGen.generate() % n;
186 }
187 
188 
factoryseed(int s)189 void factoryseed ( int s )
190 {
191     ranGen.seed( s );
192 
193 #ifdef HAVE_FLINT
194     flint_randinit(FLINTrandom);
195 #endif
196 }
197