1 /* emacs edit mode for this file is -*- C++ -*- */
2 
3 
4 #include "config.h"
5 
6 
7 #include <string.h>
8 
9 #include "cf_assert.h"
10 
11 #include "cf_defs.h"
12 #include "variable.h"
13 #include "canonicalform.h"
14 #include "cf_factory.h"
15 #include "int_poly.h"
16 #include "cf_iter.h"
17 
18 class ext_entry
19 {
20 private:
21     InternalPoly * _mipo;
22     bool _reduce;
23 public:
ext_entry()24     ext_entry () : _mipo(0), _reduce(false) {}
ext_entry(InternalPoly * mipoly,bool reduce)25     ext_entry ( InternalPoly * mipoly, bool reduce ) : _mipo(mipoly), _reduce(reduce) {};
ext_entry(const ext_entry & e)26     ext_entry ( const ext_entry & e ) : _mipo(e._mipo), _reduce(e._reduce) {}
~ext_entry()27     ~ext_entry () {};
operator =(const ext_entry & e)28     ext_entry & operator= ( const ext_entry & e )
29     {
30         if ( this != &e ) {
31             _mipo = e._mipo;
32             _reduce = e._reduce;
33         }
34         return *this;
35     }
mipo()36     InternalPoly * mipo () { return _mipo; }
setmipo(InternalPoly * p)37     void setmipo( InternalPoly * p ) { _mipo = p; }
reduce()38     bool & reduce () { return _reduce; }
39 };
40 
41 STATIC_VAR ext_entry * algextensions = 0;
42 STATIC_VAR char * var_names = 0;
43 STATIC_VAR char * var_names_ext = 0;
44 STATIC_VAR char default_name = 'v';
45 STATIC_VAR char default_name_ext = 'a';
46 
Variable(int l,bool flag)47 Variable::Variable( int l, bool flag ) : _level(l)
48 {
49     ASSERT( flag, "illegal level" );
50 }
51 
Variable(int l)52 Variable::Variable( int l ) : _level(l)
53 {
54     //ASSERT( l > 0 && l != LEVELQUOT, "illegal level" );
55 }
56 
Variable(char name)57 Variable::Variable( char name )
58 {
59     bool isext = false;
60     int n, i;
61     if ( var_names_ext != 0 ) {
62         n = strlen( var_names_ext );
63         i = 1;
64         while ( i < n && var_names_ext[i] != name ) i++;
65         if ( i < n ) {
66             _level = -i;
67             isext = true;
68         }
69     }
70     if ( ! isext ) {
71         if ( var_names == 0 ) {
72             var_names = new char [3];
73             var_names[0] = '@';
74             var_names[1] = name;
75             var_names[2] = '\0';
76             _level = 1;
77         }
78         else {
79             n = strlen( var_names );
80             i = 1;
81             while ( i < n && var_names[i] != name ) i++;
82             if ( i < n )
83                 _level = i;
84             else {
85                 ASSERT( name != '@', "illegal variable name" );
86                 char * newvarnames = new char [n+2];
87                 for ( i = 0; i < n; i++ )
88                     newvarnames[i] = var_names[i];
89                 newvarnames[n] = name;
90                 newvarnames[n+1] = 0;
91                 delete [] var_names;
92                 var_names = newvarnames;
93                 _level = n;
94             }
95         }
96     }
97 }
98 
Variable(int l,char name)99 Variable::Variable( int l, char name ) : _level(l)
100 {
101     ASSERT( l > 0 && l != LEVELQUOT, "illegal level" );
102     int n;
103     if ( (n = (var_names == 0 ? 0 : strlen( var_names ))) <= l ) {
104         char * newvarnames = new char [l+2];
105         int i;
106         for ( i = 0; i < n; i++ )
107             newvarnames[i] = var_names[i];
108         for ( i = n; i < l; i++ )
109             newvarnames[i] = '@';
110         newvarnames[l] = name;
111         newvarnames[l+1] = 0;
112         delete [] var_names;
113         var_names = newvarnames;
114     }
115     else {
116         ASSERT( var_names[l] == '@', "illegal name" );
117         var_names[l] = name;
118     }
119 }
120 
121 char
name() const122 Variable::name() const
123 {
124     if ( _level > 0 && _level < (int)strlen( var_names ) )
125         return( var_names[_level] );
126     else if ( _level < 0 && -_level < (int)strlen( var_names_ext ) )
127         return( var_names_ext[-_level] );
128     else
129         return '@';
130 }
131 
132 #ifndef NOSTREAMIO
operator <<(OSTREAM & os,const Variable & v)133 OSTREAM & operator << ( OSTREAM & os, const Variable & v )
134 {
135     if ( v._level == LEVELBASE )
136         os << "1";
137     else {
138         char * vn = ( v._level > 0 ) ? var_names : var_names_ext;
139         char dn = ( v._level > 0 ) ? default_name : default_name_ext;
140         int l = v._level;
141 
142         if ( l < 0 ) l = -l;
143         if ( (vn == 0) || ((int)strlen( vn ) <= l) )
144             os << dn << "_" << l;
145         else  if ( vn[l] == '@' )
146             os << dn << "_" << l;
147         else
148             os << vn[l];
149     }
150     return os;
151 }
152 #endif /* NOSTREAMIO */
153 
conv2mipo(const CanonicalForm & mipo,const Variable & alpha)154 static CanonicalForm conv2mipo ( const CanonicalForm & mipo, const Variable & alpha )
155 {
156     CanonicalForm result;
157     for ( CFIterator i = mipo; i.hasTerms(); i++ )
158         result += i.coeff() * power( alpha, i.exp() );
159     return result;
160 }
161 
rootOf(const CanonicalForm & mipo,char name)162 Variable rootOf( const CanonicalForm & mipo, char name )
163 {
164     ASSERT (mipo.isUnivariate(), "not a legal extension");
165 
166     int l;
167     if ( var_names_ext == 0 ) {
168         var_names_ext = new char [3];
169         var_names_ext[0] = '@';
170         var_names_ext[1] = name;
171         var_names_ext[2] = '\0';
172         l = 1;
173         Variable result( -l, true );
174         algextensions = new ext_entry [2];
175         algextensions[1] = ext_entry( 0, false );
176         algextensions[1] = ext_entry( (InternalPoly*)(conv2mipo( mipo, result ).getval()), true );
177         return result;
178     }
179     else {
180         int i, n = strlen( var_names_ext );
181         char * newvarnames = new char [n+2];
182         for ( i = 0; i < n; i++ )
183             newvarnames[i] = var_names_ext[i];
184         newvarnames[n] = name;
185         newvarnames[n+1] = 0;
186         delete [] var_names_ext;
187         var_names_ext = newvarnames;
188         l = n;
189         Variable result( -l, true );
190         ext_entry * newalgext = new ext_entry [n+1];
191         for ( i = 0; i < n; i++ )
192             newalgext[i] = algextensions[i];
193         newalgext[n] = ext_entry( 0, false );
194         delete [] algextensions;
195         algextensions = newalgext;
196         algextensions[n] = ext_entry( (InternalPoly*)(conv2mipo( mipo, result ).getval()), true );
197         return result;
198     }
199 }
200 
getInternalMipo(const Variable & alpha)201 InternalPoly * getInternalMipo ( const Variable & alpha )
202 {
203     ASSERT( alpha.level() < 0 && alpha.level() != LEVELBASE, "illegal extension" );
204     return algextensions[-alpha.level()].mipo();
205 }
206 
getMipo(const Variable & alpha,const Variable & x)207 CanonicalForm getMipo( const Variable & alpha, const Variable & x )
208 {
209     ASSERT( alpha.level() < 0 && alpha.level() != LEVELBASE, "illegal extension" );
210     return CanonicalForm( algextensions[-alpha.level()].mipo()->copyObject() )(x,alpha);
211 }
212 
getMipo(const Variable & alpha)213 CanonicalForm getMipo( const Variable & alpha )
214 {
215     ASSERT( alpha.level() < 0 && alpha.level() != LEVELBASE, "illegal extension" );
216     return CanonicalForm( algextensions[-alpha.level()].mipo()->copyObject() );
217 }
218 
setMipo(const Variable & alpha,const CanonicalForm & mipo)219 void setMipo ( const Variable & alpha, const CanonicalForm & mipo)
220 {
221     ASSERT( alpha.level() < 0 && alpha.level() != LEVELBASE, "illegal extension" );
222     algextensions[-alpha.level()]= ext_entry( 0, false );
223     algextensions[-alpha.level()]= ext_entry((InternalPoly*)(conv2mipo( mipo, alpha ).getval()), true );
224 }
225 
hasMipo(const Variable & alpha)226 bool hasMipo( const Variable & alpha )
227 {
228     ASSERT( alpha.level() < 0, "illegal extension" );
229     return (alpha.level() != LEVELBASE && (algextensions!=NULL) && getReduce(alpha) );
230 }
231 
getReduce(const Variable & alpha)232 bool getReduce( const Variable & alpha )
233 {
234     ASSERT( alpha.level() < 0 && alpha.level() != LEVELBASE, "illegal extension" );
235     return algextensions[-alpha.level()].reduce();
236 }
237 
setReduce(const Variable & alpha,bool reduce)238 void setReduce( const Variable & alpha, bool reduce )
239 {
240     ASSERT( alpha.level() < 0 && alpha.level() != LEVELBASE, "illegal extension" );
241     algextensions[-alpha.level()].reduce() = reduce;
242 }
243 
getDefaultVarName()244 char getDefaultVarName()
245 {
246     return default_name;
247 }
248 
getDefaultExtName()249 char getDefaultExtName()
250 {
251     return default_name_ext;
252 }
253 
ExtensionLevel()254 int ExtensionLevel()
255 {
256   if( var_names_ext == 0)
257     return 0;
258   return strlen( var_names_ext )-1;
259 }
260 
prune(Variable & alpha)261 void prune (Variable& alpha)
262 {
263   if (alpha.level()==LEVELBASE) return;
264   int last_var=-alpha.level();
265   if ((last_var <= 0)||(var_names_ext==NULL)) return;
266   int i, n = strlen( var_names_ext );
267   ASSERT (n+1 >= last_var, "wrong variable");
268   if (last_var == 1)
269   {
270     delete [] var_names_ext;
271     delete [] algextensions;
272     var_names_ext= 0;
273     algextensions= 0;
274     alpha= Variable();
275     return;
276   }
277   char * newvarnames = new char [last_var+1];
278   for ( i = 0; i < last_var; i++ )
279     newvarnames[i] = var_names_ext[i];
280   newvarnames[last_var] = 0;
281   delete [] var_names_ext;
282   var_names_ext = newvarnames;
283   ext_entry * newalgext = new ext_entry [last_var];
284   for ( i = 0; i < last_var; i++ )
285     newalgext[i] = algextensions[i];
286   delete [] algextensions;
287   algextensions = newalgext;
288   alpha= Variable();
289 }
290 
prune1(const Variable & alpha)291 void prune1 (const Variable& alpha)
292 {
293   int i, n = strlen( var_names_ext );
294   ASSERT (n+1 >= -alpha.level(), "wrong variable");
295 
296   char * newvarnames = new char [-alpha.level() + 2];
297   for ( i = 0; i <= -alpha.level(); i++ )
298     newvarnames[i] = var_names_ext[i];
299   newvarnames[-alpha.level()+1] = 0;
300   delete [] var_names_ext;
301   var_names_ext = newvarnames;
302   ext_entry * newalgext = new ext_entry [-alpha.level()+1];
303   for ( i = 0; i <= -alpha.level(); i++ )
304     newalgext[i] = algextensions[i];
305   delete [] algextensions;
306   algextensions = newalgext;
307 }
308 
Reduce(bool on)309 void Reduce( bool on)
310 {
311   int i;
312   for (i=ExtensionLevel(); i>0;i--)
313   {
314     Variable l(-i);
315     setReduce(l,on);
316   }
317 }
318