source: git/factory/cf_map.cc @ d38762

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