source: git/factory/cf_map.cc @ 16f511

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