source: git/factory/cf_map.cc @ 8d1432e

spielwiese
Last change on this file since 8d1432e was abddbe, checked in by Martin Lee <martinlee84@…>, 10 years ago
chg: added brief descriptions to some files
  • Property mode set to 100644
File size: 9.8 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2
3/**
4 *
5 * @file cf_map.cc
6 *
7 * definition of class CFMap.
8 *
9 * Used by: cf_gcd.cc, fac_multivar.cc
10 *
11**/
12
13
14#include "config.h"
15
16
17#include "canonicalform.h"
18#include "cf_map.h"
19#include "cf_iter.h"
20#include "templates/ftmpl_functions.h"
21
22/** MapPair & MapPair::operator = ( const MapPair & p )
23 *
24 * MapPair::operator = - assignment operator.
25 *
26**/
27MapPair &
28MapPair::operator = ( const MapPair & p )
29{
30    if ( this != &p ) {
31        V = p.V;
32        S = p.S;
33    }
34    return *this;
35}
36
37#ifndef NOSTREAMIO
38/** OSTREAM & operator << ( OSTREAM & s, const MapPair & p )
39 *
40 * operator << - print a map pair ("V -> S").
41 *
42**/
43OSTREAM &
44operator << ( OSTREAM & s, const MapPair & p )
45{
46    s << p.var() << " -> " << p.subst();
47    return s;
48}
49
50void MapPair::print( OSTREAM&) const
51{
52}
53#endif /* NOSTREAMIO */
54
55/** CFMap::CFMap ( const CFList & L )
56 *
57 * CFMap::CFMap() - construct a CFMap from a CFList.
58 *
59 * Variable[i] will be mapped to CFList[i] under the resulting
60 * map.
61 *
62**/
63CFMap::CFMap ( const CFList & L )
64{
65    CFListIterator i;
66    int j;
67    for ( i = L, j = 1; i.hasItem(); i++, j++ )
68        P.insert( MapPair( Variable(j), i.getItem() ) );
69}
70
71/** CFMap & CFMap::operator = ( const CFMap & m )
72 *
73 * CFMap::operator = - assignment operator.
74 *
75**/
76CFMap &
77CFMap::operator = ( const CFMap & m )
78{
79    if ( this != &m )
80        P = m.P;
81    return *this;
82}
83
84/** static int cmpfunc ( const MapPair & p1, const MapPair & p2 )
85 *
86 * cmpfunc() - compare two map pairs.
87 *
88 * Return -1 if p2's variable is less than p1's, 0 if they are
89 * equal, 1 if p2's level is greater than p1's.
90 *
91**/
92static int
93cmpfunc ( const MapPair & p1, const MapPair & p2 )
94{
95    if ( p1.var() > p2.var() ) return -1;
96    else if ( p1.var() == p2.var() ) return 0;
97    else return 1;
98}
99
100/** static void insfunc ( MapPair & orgp, const MapPair & newp )
101 *
102 * insfunc() - assign newp to orgp.
103 *
104 * cmpfunc() and insfunc() are used as functions for inserting a
105 * map pair into a map by CFMap::newpair().
106 *
107**/
108static void
109insfunc ( MapPair & orgp, const MapPair & newp )
110{
111    orgp = newp;
112}
113
114/** void CFMap::newpair ( const Variable & v, const CanonicalForm & s )
115 *
116 * CFMap::newpair() - insert a MapPair into a CFMap.
117 *
118**/
119void
120CFMap::newpair ( const Variable & v, const CanonicalForm & s )
121{
122    P.insert( MapPair( v, s ), cmpfunc, insfunc );
123}
124
125/** static CanonicalForm subsrec ( const CanonicalForm & f, const MPListIterator & i )
126 *
127 * subsrec() - recursively apply the substitutions in i to f.
128 *
129 * Substitutes algebraic variables, too.  The substituted
130 * expression are not subject to further substitutions.
131 *
132 * Used by: CFMap::operator ()().
133 *
134**/
135static CanonicalForm
136subsrec ( const CanonicalForm & f, const MPListIterator & i )
137{
138    if ( f.inBaseDomain() ) return f;
139    MPListIterator j = i;
140
141    // skip MapPairs larger than the main variable of f
142    while ( j.hasItem() && j.getItem().var() > f.mvar() ) j++;
143
144    if ( j.hasItem() )
145        if ( j.getItem().var() != f.mvar() ) {
146            // simply descend if the current MapPair variable is
147            // not the main variable of f
148            CanonicalForm result = 0;
149            CFIterator I;
150            for ( I = f; I.hasTerms(); I++ )
151                result += power( f.mvar(), I.exp() ) * subsrec( I.coeff(), j );
152            return result;
153        }
154        else {
155            // replace the main variable of f with the image of
156            // the current variable under MapPair
157            CanonicalForm result = 0;
158            CanonicalForm s = j.getItem().subst();
159            CFIterator I;
160            // move on to the next MapPair
161            j++;
162            for ( I = f; I.hasTerms(); I++ )
163                result += subsrec( I.coeff(), j ) * power( s, I.exp() );
164            return result;
165        }
166    else
167        return f;
168}
169
170/** CanonicalForm CFMap::operator () ( const CanonicalForm & f ) const
171 *
172 * CFMap::operator () - apply CO to f.
173 *
174 * See subsrec() for more detailed information.
175 *
176**/
177CanonicalForm
178CFMap::operator () ( const CanonicalForm & f ) const
179{
180    MPListIterator i = P;
181    return subsrec( f, i );
182}
183
184#ifndef NOSTREAMIO
185/** OSTREAM & operator << ( OSTREAM & s, const CFMap & m )
186 *
187 * operator << - print a CFMap ("( V[1] -> S[1], ..., V[n] ->  * S[n] )".
188 *
189**/
190OSTREAM &
191operator << ( OSTREAM & s, const CFMap & m )
192{
193    m.P.print(s);
194    return s;
195}
196#endif /* NOSTREAMIO */
197
198/** CanonicalForm compress ( const CanonicalForm & f, CFMap & m )
199 *
200 * compress() - compress the canonical form f.
201 *
202 * Compress the polynomial f such that the levels of its
203 * polynomial variables are ordered without any gaps starting
204 * from level 1.  Return the compressed polynomial and a map m to
205 * undo the compression.  That is, if f' = compress(f, m), than f
206 * = m(f').
207 *
208**/
209CanonicalForm
210compress ( const CanonicalForm & f, CFMap & m )
211{
212    CanonicalForm result = f;
213    int i, n;
214    int * degs = degrees( f );
215
216    m = CFMap();
217    n = i = 1;
218    while ( i <= level( f ) ) {
219        while( degs[i] == 0 ) i++;
220        if ( i != n ) {
221            // swap variables and remember the swap in the map
222            m.newpair( Variable( n ), Variable( i ) );
223            result = swapvar( result, Variable( i ), Variable( n ) );
224        }
225        n++; i++;
226    }
227    delete [] degs;
228    return result;
229}
230
231/** void compress ( const CFArray & a, CFMap & M, CFMap & N )
232 *
233 * compress() - compress the variables occuring in an a.
234 *
235 * Compress the polynomial variables occuring in a so that their
236 * levels are ordered without any gaps starting from level 1.
237 * Return the CFMap M to realize the compression and its inverse,
238 * the CFMap N.  Note that if you compress a member of a using M
239 * the result of the compression is not necessarily compressed,
240 * since the map is constructed using all variables occuring in
241 * a.
242 *
243**/
244void
245compress ( const CFArray & a, CFMap & M, CFMap & N )
246{
247    M = N = CFMap();
248    if ( a.size() == 0 )
249        return;
250    int maxlevel = level( a[a.min()] );
251    int i, j;
252
253    // get the maximum of levels in a
254    for ( i = a.min() + 1; i <= a.max(); i++ )
255        if ( level( a[i] ) > maxlevel )
256            maxlevel = level( a[i] );
257    if ( maxlevel <= 0 )
258        return;
259
260    int * degs = new int[maxlevel+1];
261    int * tmp = new int[maxlevel+1];
262    for ( i = 1; i <= maxlevel; i++ )
263        degs[i] = 0;
264
265    // calculate the union of all levels occuring in a
266    for ( i = a.min(); i <= a.max(); i++ ) {
267        tmp = degrees( a[i], tmp );
268        for ( j = 1; j <= level( a[i] ); j++ )
269            if ( tmp[j] != 0 )
270                degs[j] = 1;
271    }
272
273    // create the maps
274    i = 1; j = 1;
275    while ( i <= maxlevel ) {
276        if ( degs[i] != 0 ) {
277            M.newpair( Variable(i), Variable(j) );
278            N.newpair( Variable(j), Variable(i) );
279            j++;
280        }
281        i++;
282    }
283    delete [] tmp;
284    delete [] degs;
285}
286
287/*
288*  compute positions p1 and pe of optimal variables:
289*    pe is used in "ezgcd" and
290*    p1 in "gcd_poly1"
291*/
292static
293void optvalues ( const int * df, const int * dg, const int n, int & p1, int &pe )
294{
295    int i, o1, oe;
296    i = p1 = pe = 0;
297    do
298    {
299        i++;
300        if ( i > n ) return;
301    } while ( ( df[i] == 0 ) || ( dg[i] == 0 ) );
302    p1 = pe = i;
303    if ( df[i] > dg[i] )
304    {
305        o1 = df[i]; oe = dg[i];
306    }
307    else
308    {
309        o1 = dg[i]; oe = df[i];
310    }
311    while ( i < n )
312    {
313        i++;
314        if ( ( df[i] != 0 ) && ( dg[i] != 0 ) )
315        {
316            if ( df[i] > dg[i] )
317            {
318                if ( o1 >= df[i]) { o1 = df[i]; p1 = i; }
319                if ( oe < dg[i]) { oe = dg[i]; pe = i; }
320            }
321            else
322            {
323                if ( o1 >= dg[i]) { o1 = dg[i]; p1 = i; }
324                if ( oe < df[i]) { oe = df[i]; pe = i; }
325            }
326        }
327    }
328}
329
330
331/** void compress ( const CanonicalForm & f, const CanonicalForm & g, CFMap & M, CFMap & N )
332 *
333 * compress() - compress the variables occurring in f and g with respect
334 * to optimal variables
335 *
336 * Compress the polynomial variables occurring in f and g so that
337 * the levels of variables common to f and g are ordered without
338 * any gaps starting from level 1, whereas the variables occuring
339 * in only one of f or g are moved to levels higher than the
340 * levels of the common variables.  Return the CFMap M to realize
341 * the compression and its inverse, the CFMap N.
342 * N needs only variables common to f and g.
343 *
344**/
345void
346compress ( const CanonicalForm & f, const CanonicalForm & g, CFMap & M, CFMap & N )
347{
348    int n = tmax( f.level(), g.level() );
349    int i, k, p1, pe;
350    int * degsf = new int[n+1];
351    int * degsg = new int[n+1];
352
353    for ( i = 0; i <= n; i++ )
354    {
355        degsf[i] = degsg[i] = 0;
356    }
357
358    degsf = degrees( f, degsf );
359    degsg = degrees( g, degsg );
360    optvalues( degsf, degsg, n, p1, pe );
361
362    i = 1; k = 1;
363    if ( pe > 1 )
364    {
365        M.newpair( Variable(pe), Variable(k) );
366        N.newpair( Variable(k), Variable(pe) );
367        k++;
368    }
369    while ( i <= n )
370    {
371        if ( degsf[i] > 0 && degsg[i] > 0 )
372        {
373            if ( ( i != k ) && ( i != pe ) && ( i != p1 ) )
374            {
375                M.newpair( Variable(i), Variable(k) );
376                N.newpair( Variable(k), Variable(i) );
377            }
378            k++;
379        }
380        i++;
381    }
382    if ( p1 != pe )
383    {
384        M.newpair( Variable(p1), Variable(k) );
385        N.newpair( Variable(k), Variable(p1) );
386        k++;
387    }
388    i = 1;
389    while ( i <= n )
390    {
391        if ( degsf[i] > 0 && degsg[i] == 0 ) {
392            if ( i != k )
393            {
394                M.newpair( Variable(i), Variable(k) );
395                k++;
396            }
397        }
398        else if ( degsf[i] == 0 && degsg[i] > 0 )
399        {
400            if ( i != k )
401            {
402                M.newpair( Variable(i), Variable(k) );
403                k++;
404            }
405        }
406        i++;
407    }
408
409    delete [] degsf;
410    delete [] degsg;
411}
Note: See TracBrowser for help on using the repository browser.