source: git/factory/cf_random.cc

spielwiese
Last change on this file was f8d27e1, checked in by Max Horn <max@…>, 4 years ago
Move FLINTrandom into factory to fix test suite crashes Without this, `make check` runs into segfaults in tests that use factory but not the full Singular library, as factory accesses FLINTrandom but does not contain its definition.
  • Property mode set to 100644
File size: 3.5 KB
RevLine 
[493c477]1/* emacs edit mode for this file is -*- C++ -*- */
[2dd068]2
[9f7665]3
[e4fe2b]4#include "config.h"
[9f7665]5
[b973c0]6
[4345a0]7#include <time.h>
[2dd068]8
[650f2d8]9#include "cf_assert.h"
[b973c0]10
[2dd068]11#include "cf_defs.h"
12#include "cf_random.h"
13#include "ffops.h"
14#include "gfops.h"
15#include "imm.h"
16
[f8d27e1]17#ifdef HAVE_FLINT
18extern "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
25GLOBAL_VAR flint_rand_t FLINTrandom;
26}
27#endif
28
[4345a0]29class RandomGenerator {
30private:
[f67df3]31    const int ia, im, iq, ir, deflt;
32    int s;
[4345a0]33
34    // s must not equal zero!
[f67df3]35    void seedInit( int ss ) { s = ((ss == 0) ? deflt : ss); }
[4345a0]36public:
[553daf]37    RandomGenerator();
[f67df3]38    RandomGenerator( int ss );
[4345a0]39    ~RandomGenerator() {}
[f67df3]40    int generate();
41    void seed( int ss ) { seedInit( ss ); }
[4345a0]42};
43
[9c9e2a4]44RandomGenerator::RandomGenerator() : ia(16807), im(2147483647), iq(127773), ir(2836), deflt(123459876)
[553daf]45{
[f67df3]46  seedInit( (int)time( 0 ) );
[553daf]47}
48
[f67df3]49RandomGenerator::RandomGenerator( int ss ) : ia(16807), im(2147483647), iq(127773), ir(2836), deflt(123459876)
[553daf]50{
51  seedInit( ss );
52}
53
[f67df3]54int
[4345a0]55RandomGenerator::generate()
56{
[f67df3]57    int k;
[4345a0]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
[a3f0fea]66INST_VAR RandomGenerator ranGen;
[2dd068]67
68CanonicalForm FFRandom::generate () const
69{
70    return CanonicalForm( int2imm_p( factoryrandom( ff_prime ) ) );
71}
72
73CFRandom * FFRandom::clone () const
74{
75    return new FFRandom();
76}
77
78CanonicalForm GFRandom::generate () const
79{
[08daea]80    int i= factoryrandom( gf_q );
81    if ( i == gf_q1 ) i++;
82    return CanonicalForm( int2imm_gf( i ) );
[2dd068]83}
84
85CFRandom * GFRandom::clone () const
86{
87    return new GFRandom();
88}
89
90
91IntRandom::IntRandom()
92{
[afd067]93    max = 50;
[2dd068]94}
95
96IntRandom::IntRandom( int m )
97{
98    max = m;
99}
100
101IntRandom::~IntRandom() {}
102
103CanonicalForm IntRandom::generate() const
104{
[afd067]105    return factoryrandom( 2*max )-max;
[2dd068]106}
[b973c0]107
[2dd068]108CFRandom * IntRandom::clone() const
109{
110    return new IntRandom( max );
111}
112
113AlgExtRandomF::AlgExtRandomF()
114{
115    ASSERT( 0, "not a valid random generator" );
116}
117
118AlgExtRandomF::AlgExtRandomF( const AlgExtRandomF & )
119{
120    ASSERT( 0, "not a valid random generator" );
121}
122
123AlgExtRandomF& AlgExtRandomF::operator= ( const AlgExtRandomF & )
124{
125    ASSERT( 0, "not a valid random generator" );
126    return *this;
127}
128
129AlgExtRandomF::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
137AlgExtRandomF::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
145AlgExtRandomF::AlgExtRandomF( const Variable & v, CFRandom * g, int nn )
146{
147    algext = v;
148    n = nn;
149    gen = g;
150}
151
152AlgExtRandomF::~AlgExtRandomF()
153{
154    delete gen;
155}
156
157CanonicalForm AlgExtRandomF::generate() const
158{
159    CanonicalForm result;
160    for ( int i = 0; i < n; i++ )
[806c18]161      result += power( algext, i ) * gen->generate();
[2dd068]162    return result;
[e76d7a6]163}
[2dd068]164
165CFRandom * AlgExtRandomF::clone () const
166{
167    return new AlgExtRandomF( algext, gen->clone(), n );
168}
169
170CFRandom * CFRandomFactory::generate()
171{
172    if ( getCharacteristic() == 0 )
[806c18]173        return new IntRandom();
[2dd068]174    if ( getGFDegree() > 1 )
[806c18]175        return new GFRandom();
[2dd068]176    else
[806c18]177        return new FFRandom();
[2dd068]178}
179
180int factoryrandom( int n )
181{
[3aca31]182    if ( n == 0 )
[806c18]183        return (int)ranGen.generate();
[3aca31]184    else
[806c18]185        return ranGen.generate() % n;
[2dd068]186}
187
[f8d27e1]188
[2dd068]189void factoryseed ( int s )
190{
[4345a0]191    ranGen.seed( s );
[f8d27e1]192
193#ifdef HAVE_FLINT
194    flint_randinit(FLINTrandom);
195#endif
[2dd068]196}
Note: See TracBrowser for help on using the repository browser.