source: git/libpolys/polys/nc/sca.cc @ 64f0ca

spielwiese
Last change on this file since 64f0ca was 64f0ca, checked in by Oleksandr Motsak <motsak@…>, 11 years ago
proper hack for SCA fix: SCA test + initialization fix: GB over a SCA add: "ring-dependent" wrapper of kNF (for SCA test)
  • Property mode set to 100644
File size: 36.0 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/***************************************************************
5 *  File:    sca.cc
6 *  Purpose: supercommutative kernel procedures
7 *  Author:  motsak (Oleksandr Motsak)
8 *  Created: 2006/12/18
9 *  Version: $Id$
10 *******************************************************************/
11
12// set it here if needed.
13#define OUTPUT 0
14#define MYTEST 0
15
16#if MYTEST
17#define OM_CHECK 4
18#define OM_TRACK 5
19#endif
20
21// #define PDEBUG 2
22#include "config.h"
23#include <misc/auxiliary.h>
24
25#ifdef HAVE_PLURAL
26
27// for
28#define PLURAL_INTERNAL_DECLARATIONS
29
30#include <polys/nc/sca.h>
31#include <polys/nc/nc.h>
32#include <polys/nc/gb_hack.h>
33// #include <polys/gring.h>
34
35
36#include <coeffs/numbers.h>
37#include <polys/coeffrings.h>
38
39
40// #include <polys/febase.h>
41#include <misc/options.h>
42
43#include <polys/monomials/p_polys.h>
44
45// #include <polys/kutil.h>
46#include <polys/simpleideals.h>
47#include <misc/intvec.h>
48
49#include <polys/monomials/ring.h>
50#include <polys/kbuckets.h>
51// #include <polys/kstd1.h>
52#include <polys/sbuckets.h>
53
54#include <polys/prCopy.h>
55
56#include <polys/operations/p_Mult_q.h>
57#include <polys/templates/p_MemAdd.h>
58
59// #include <polys/kutil.h>
60// #include <polys/kstd1.h>
61
62#include <polys/weight.h>
63
64
65// poly functions defined in p_Procs :
66
67// return pPoly * pMonom; preserve pPoly and pMonom.
68poly sca_pp_Mult_mm(const poly pPoly, const poly pMonom, const ring rRing, poly &);
69
70// return pMonom * pPoly; preserve pPoly and pMonom.
71static poly sca_mm_Mult_pp(const poly pMonom, const poly pPoly, const ring rRing);
72
73// return pPoly * pMonom; preserve pMonom, destroy or reuse pPoly.
74poly sca_p_Mult_mm(poly pPoly, const poly pMonom, const ring rRing);
75
76// return pMonom * pPoly; preserve pMonom, destroy or reuse pPoly.
77static poly sca_mm_Mult_p(const poly pMonom, poly pPoly, const ring rRing);
78
79
80// compute the spolynomial of p1 and p2
81poly sca_SPoly(const poly p1, const poly p2, const ring r);
82poly sca_ReduceSpoly(const poly p1, poly p2, const ring r);
83
84
85////////////////////////////////////////////////////////////////////////////////////////////////////
86// Super Commutative Algebra extension by Oleksandr
87////////////////////////////////////////////////////////////////////////////////////////////////////
88
89// returns the sign of: lm(pMonomM) * lm(pMonomMM),
90// preserves input, may return +/-1, 0
91static inline int sca_Sign_mm_Mult_mm( const poly pMonomM, const poly pMonomMM, const ring rRing )
92{
93#ifdef PDEBUG
94    p_Test(pMonomM,  rRing);
95    p_Test(pMonomMM, rRing);
96#endif
97
98    const unsigned int iFirstAltVar = scaFirstAltVar(rRing);
99    const unsigned int iLastAltVar  = scaLastAltVar(rRing);
100
101    register unsigned int tpower = 0;
102    register unsigned int cpower = 0;
103
104    for( register unsigned int j = iLastAltVar; j >= iFirstAltVar; j-- )
105    {
106      const unsigned int iExpM  = p_GetExp(pMonomM,  j, rRing);
107      const unsigned int iExpMM = p_GetExp(pMonomMM, j, rRing);
108
109#ifdef PDEBUG
110      assume( iExpM <= 1);
111      assume( iExpMM <= 1);
112#endif
113
114      if( iExpMM != 0 ) // TODO: think about eliminating there if-s...
115      {
116        if( iExpM != 0 )
117        {
118          return 0; // lm(pMonomM) * lm(pMonomMM) == 0
119        }
120        tpower ^= cpower; // compute degree of (-1).
121      }
122      cpower ^= iExpM;
123    }
124
125#ifdef PDEBUG
126    assume(tpower <= 1);
127#endif
128
129    // 1 => -1  // degree is odd => negate coeff.
130    // 0 =>  1
131
132    return(1 - (tpower << 1) );
133}
134
135
136
137
138// returns and changes pMonomM: lt(pMonomM) = lt(pMonomM) * lt(pMonomMM),
139// preserves pMonomMM. may return NULL!
140// if result != NULL => next(result) = next(pMonomM), lt(result) = lt(pMonomM) * lt(pMonomMM)
141// if result == NULL => pMonomM MUST BE deleted manually!
142static inline poly sca_m_Mult_mm( poly pMonomM, const poly pMonomMM, const ring rRing )
143{
144#ifdef PDEBUG
145    p_Test(pMonomM,  rRing);
146    p_Test(pMonomMM, rRing);
147#endif
148
149    const unsigned int iFirstAltVar = scaFirstAltVar(rRing);
150    const unsigned int iLastAltVar = scaLastAltVar(rRing);
151
152    register unsigned int tpower = 0;
153    register unsigned int cpower = 0;
154
155    for( register unsigned int j = iLastAltVar; j >= iFirstAltVar; j-- )
156    {
157      const unsigned int iExpM  = p_GetExp(pMonomM,  j, rRing);
158      const unsigned int iExpMM = p_GetExp(pMonomMM, j, rRing);
159
160#ifdef PDEBUG
161      assume( iExpM <= 1);
162      assume( iExpMM <= 1);
163#endif
164
165      if( iExpMM != 0 )
166      {
167        if( iExpM != 0 ) // result is zero!
168        {
169          return NULL; // we do nothing with pMonomM in this case!
170        }
171
172        tpower ^= cpower; // compute degree of (-1).
173      }
174
175      cpower ^= iExpM;
176    }
177
178#ifdef PDEBUG
179    assume(tpower <= 1);
180#endif
181
182    p_ExpVectorAdd(pMonomM, pMonomMM, rRing); // "exponents" are additive!!!
183
184    number nCoeffM = p_GetCoeff(pMonomM, rRing); // no new copy! should be deleted!
185
186    if( (tpower) != 0 ) // degree is odd => negate coeff.
187      nCoeffM = n_Neg(nCoeffM, rRing); // negate nCoeff (will destroy the original number)
188
189    const number nCoeffMM = p_GetCoeff(pMonomMM, rRing); // no new copy!
190
191    number nCoeff = n_Mult(nCoeffM, nCoeffMM, rRing); // new number!
192
193    p_SetCoeff(pMonomM, nCoeff, rRing); // delete lc(pMonomM) and set lc(pMonomM) = nCoeff
194
195#ifdef PDEBUG
196    p_LmTest(pMonomM, rRing);
197#endif
198
199    return(pMonomM);
200}
201
202// returns and changes pMonomM: lt(pMonomM) = lt(pMonomMM) * lt(pMonomM),
203// preserves pMonomMM. may return NULL!
204// if result != NULL => next(result) = next(pMonomM), lt(result) = lt(pMonomMM) * lt(pMonomM)
205// if result == NULL => pMonomM MUST BE deleted manually!
206static inline poly sca_mm_Mult_m( const poly pMonomMM, poly pMonomM, const ring rRing )
207{
208#ifdef PDEBUG
209    p_Test(pMonomM,  rRing);
210    p_Test(pMonomMM, rRing);
211#endif
212
213    const unsigned int iFirstAltVar = scaFirstAltVar(rRing);
214    const unsigned int iLastAltVar = scaLastAltVar(rRing);
215
216    register unsigned int tpower = 0;
217    register unsigned int cpower = 0;
218
219    for( register unsigned int j = iLastAltVar; j >= iFirstAltVar; j-- )
220    {
221      const unsigned int iExpMM = p_GetExp(pMonomMM, j, rRing);
222      const unsigned int iExpM  = p_GetExp(pMonomM,  j, rRing);
223
224#ifdef PDEBUG
225      assume( iExpM <= 1);
226      assume( iExpMM <= 1);
227#endif
228
229      if( iExpM != 0 )
230      {
231        if( iExpMM != 0 ) // result is zero!
232        {
233          return NULL; // we do nothing with pMonomM in this case!
234        }
235
236        tpower ^= cpower; // compute degree of (-1).
237      }
238
239      cpower ^= iExpMM;
240    }
241
242#ifdef PDEBUG
243    assume(tpower <= 1);
244#endif
245
246    p_ExpVectorAdd(pMonomM, pMonomMM, rRing); // "exponents" are additive!!!
247
248    number nCoeffM = p_GetCoeff(pMonomM, rRing); // no new copy! should be deleted!
249
250    if( (tpower) != 0 ) // degree is odd => negate coeff.
251      nCoeffM = n_Neg(nCoeffM, rRing); // negate nCoeff (will destroy the original number), creates new number!
252
253    const number nCoeffMM = p_GetCoeff(pMonomMM, rRing); // no new copy!
254
255    number nCoeff = n_Mult(nCoeffM, nCoeffMM, rRing); // new number!
256
257    p_SetCoeff(pMonomM, nCoeff, rRing); // delete lc(pMonomM) and set lc(pMonomM) = nCoeff
258
259#ifdef PDEBUG
260    p_LmTest(pMonomM, rRing);
261#endif
262
263    return(pMonomM);
264}
265
266
267
268// returns: result = lt(pMonom1) * lt(pMonom2),
269// preserves pMonom1, pMonom2. may return NULL!
270// if result != NULL => next(result) = NULL, lt(result) = lt(pMonom1) * lt(pMonom2)
271static inline poly sca_mm_Mult_mm( poly pMonom1, const poly pMonom2, const ring rRing )
272{
273#ifdef PDEBUG
274    p_Test(pMonom1, rRing);
275    p_Test(pMonom2, rRing);
276#endif
277
278    const unsigned int iFirstAltVar = scaFirstAltVar(rRing);
279    const unsigned int iLastAltVar = scaLastAltVar(rRing);
280
281    register unsigned int tpower = 0;
282    register unsigned int cpower = 0;
283
284    for( register unsigned int j = iLastAltVar; j >= iFirstAltVar; j-- )
285    {
286      const unsigned int iExp1 = p_GetExp(pMonom1, j, rRing);
287      const unsigned int iExp2 = p_GetExp(pMonom2, j, rRing);
288
289#ifdef PDEBUG
290      assume( iExp1 <= 1);
291      assume( iExp2 <= 1);
292#endif
293
294      if( iExp2 != 0 )
295      {
296        if( iExp1 != 0 ) // result is zero!
297        {
298          return NULL;
299        }
300        tpower ^= cpower; // compute degree of (-1).
301      }
302      cpower ^= iExp1;
303    }
304
305#ifdef PDEBUG
306    assume(cpower <= 1);
307#endif
308
309    poly pResult;
310    p_AllocBin(pResult,rRing->PolyBin,rRing);
311
312    p_ExpVectorSum(pResult, pMonom1, pMonom2, rRing); // "exponents" are additive!!!
313
314    pNext(pResult) = NULL;
315
316    const number nCoeff1 = p_GetCoeff(pMonom1, rRing); // no new copy!
317    const number nCoeff2 = p_GetCoeff(pMonom2, rRing); // no new copy!
318
319    number nCoeff = n_Mult(nCoeff1, nCoeff2, rRing); // new number!
320
321    if( (tpower) != 0 ) // degree is odd => negate coeff.
322      nCoeff = n_Neg(nCoeff, rRing); // negate nCoeff (will destroy the original number)
323
324    p_SetCoeff0(pResult, nCoeff, rRing); // set lc(pResult) = nCoeff, no destruction!
325
326#ifdef PDEBUG
327    p_LmTest(pResult, rRing);
328#endif
329
330    return(pResult);
331}
332
333// returns: result =  x_i * lt(pMonom),
334// preserves pMonom. may return NULL!
335// if result != NULL => next(result) = NULL, lt(result) = x_i * lt(pMonom)
336static inline poly sca_xi_Mult_mm(unsigned int i, const poly pMonom, const ring rRing)
337{
338#ifdef PDEBUG
339    p_Test(pMonom, rRing);
340#endif
341
342    assume( i <= scaLastAltVar(rRing));
343    assume( scaFirstAltVar(rRing) <= i );
344
345    if( p_GetExp(pMonom, i, rRing) != 0 ) // => result is zero!
346      return NULL;
347
348    const unsigned int iFirstAltVar = scaFirstAltVar(rRing);
349
350    register unsigned int cpower = 0;
351
352    for( register unsigned int j = iFirstAltVar; j < i ; j++ )
353      cpower ^= p_GetExp(pMonom, j, rRing);
354
355#ifdef PDEBUG
356    assume(cpower <= 1);
357#endif
358
359    poly pResult = p_LmInit(pMonom, rRing);
360
361    p_SetExp(pResult, i, 1, rRing); // pResult*=X_i &&
362    p_Setm(pResult, rRing);         // addjust degree after previous step!
363
364    number nCoeff = n_Copy(p_GetCoeff(pMonom, rRing), rRing); // new number!
365
366    if( cpower != 0 ) // degree is odd => negate coeff.
367      nCoeff = n_Neg(nCoeff, rRing); // negate nCoeff (will destroy the original number)
368
369    p_SetCoeff0(pResult, nCoeff, rRing); // set lc(pResult) = nCoeff, no destruction!
370
371#ifdef PDEBUG
372    p_LmTest(pResult, rRing);
373#endif
374
375    return(pResult);
376}
377
378//-----------------------------------------------------------------------------------//
379
380// return poly = pPoly * pMonom; preserve pMonom, destroy or reuse pPoly.
381poly sca_p_Mult_mm(poly pPoly, const poly pMonom, const ring rRing)
382{
383  assume( rIsSCA(rRing) );
384
385#ifdef PDEBUG
386//  Print("sca_p_Mult_mm\n"); // !
387
388  p_Test(pPoly, rRing);
389  p_Test(pMonom, rRing);
390#endif
391
392  if( pPoly == NULL )
393    return NULL;
394
395  assume(pMonom !=NULL);
396  //if( pMonom == NULL )
397  //{
398  //  // pPoly != NULL =>
399  //  p_Delete( &pPoly, rRing );
400  //  return NULL;
401  //}
402
403  const int iComponentMonomM = p_GetComp(pMonom, rRing);
404
405  poly p = pPoly; poly* ppPrev = &pPoly;
406
407  loop
408  {
409#ifdef PDEBUG
410    p_Test(p, rRing);
411#endif
412    const int iComponent = p_GetComp(p, rRing);
413
414    if( iComponent!=0 )
415    {
416      if( iComponentMonomM!=0 ) // TODO: make global if on iComponentMonomM =?= 0
417      {
418        // REPORT_ERROR
419        Werror("sca_p_Mult_mm: exponent mismatch %d and %d\n", iComponent, iComponentMonomM);
420        // what should we do further?!?
421
422        p_Delete( &pPoly, rRing); // delete the result AND rest
423        return NULL;
424      }
425#ifdef PDEBUG
426      if(iComponentMonomM==0 )
427      {
428        dReportError("sca_p_Mult_mm: Multiplication in the left module from the right");
429      }
430#endif
431    }
432
433    // terms will be in the same order because of quasi-ordering!
434    poly v = sca_m_Mult_mm(p, pMonom, rRing);
435
436    if( v != NULL )
437    {
438      ppPrev = &pNext(p); // fixed!
439
440    // *p is changed if v != NULL ( p == v )
441      pIter(p);
442
443      if( p == NULL )
444        break;
445    }
446    else
447    { // Upps! Zero!!! we must kill this term!
448
449      //
450      p = p_LmDeleteAndNext(p, rRing);
451
452      *ppPrev = p;
453
454      if( p == NULL )
455        break;
456    }
457  }
458
459#ifdef PDEBUG
460  p_Test(pPoly,rRing);
461#endif
462
463  return(pPoly);
464}
465
466// return new poly = pPoly * pMonom; preserve pPoly and pMonom.
467poly sca_pp_Mult_mm(const poly pPoly, const poly pMonom, const ring rRing, poly &)
468{
469  assume( rIsSCA(rRing) );
470
471#ifdef PDEBUG
472//  Print("sca_pp_Mult_mm\n"); // !
473
474  p_Test(pPoly, rRing);
475  p_Test(pMonom, rRing);
476#endif
477
478  if( ( pPoly == NULL ) /*|| ( pMonom == NULL )*/ )
479    return NULL;
480
481  const int iComponentMonomM = p_GetComp(pMonom, rRing);
482
483  poly pResult = NULL;
484  poly* ppPrev = &pResult;
485
486  for( poly p = pPoly; p!= NULL; pIter(p) )
487  {
488#ifdef PDEBUG
489    p_Test(p, rRing);
490#endif
491    const int iComponent = p_GetComp(p, rRing);
492
493    if( iComponent!=0 )
494    {
495      if( iComponentMonomM!=0 ) // TODO: make global if on iComponentMonomM =?= 0
496      {
497        // REPORT_ERROR
498        Werror("sca_pp_Mult_mm: exponent mismatch %d and %d\n", iComponent, iComponentMonomM);
499        // what should we do further?!?
500
501        p_Delete( &pResult, rRing); // delete the result
502        return NULL;
503      }
504
505#ifdef PDEBUG
506      if(iComponentMonomM==0 )
507      {
508        dReportError("sca_pp_Mult_mm: Multiplication in the left module from the right");
509      }
510#endif
511    }
512
513    // terms will be in the same order because of quasi-ordering!
514    poly v = sca_mm_Mult_mm(p, pMonom, rRing);
515
516    if( v != NULL )
517    {
518      *ppPrev = v;
519      ppPrev = &pNext(v);
520    }
521  }
522
523#ifdef PDEBUG
524  p_Test(pResult,rRing);
525#endif
526
527  return(pResult);
528}
529
530//-----------------------------------------------------------------------------------//
531
532// return x_i * pPoly; preserve pPoly.
533static inline poly sca_xi_Mult_pp(unsigned int i, const poly pPoly, const ring rRing)
534{
535  assume( rIsSCA(rRing) );
536
537#ifdef PDEBUG
538  p_Test(pPoly, rRing);
539#endif
540
541  assume(i <= scaLastAltVar(rRing));
542  assume(scaFirstAltVar(rRing) <= i);
543
544  if( pPoly == NULL )
545    return NULL;
546
547  poly pResult = NULL;
548  poly* ppPrev = &pResult;
549
550  for( poly p = pPoly; p!= NULL; pIter(p) )
551  {
552
553    // terms will be in the same order because of quasi-ordering!
554    poly v = sca_xi_Mult_mm(i, p, rRing);
555
556#ifdef PDEBUG
557    p_Test(v, rRing);
558#endif
559
560    if( v != NULL )
561    {
562      *ppPrev = v;
563      ppPrev = &pNext(*ppPrev);
564    }
565  }
566
567
568#ifdef PDEBUG
569  p_Test(pResult, rRing);
570#endif
571
572  return(pResult);
573}
574
575
576// return new poly = pMonom * pPoly; preserve pPoly and pMonom.
577static poly sca_mm_Mult_pp(const poly pMonom, const poly pPoly, const ring rRing)
578{
579  assume( rIsSCA(rRing) );
580
581#ifdef PDEBUG
582//  Print("sca_mm_Mult_pp\n"); // !
583
584  p_Test(pPoly, rRing);
585  p_Test(pMonom, rRing);
586#endif
587
588  if ((pPoly==NULL) || (pMonom==NULL)) return NULL;
589
590  assume( (pPoly != NULL) && (pMonom !=NULL));
591
592  const int iComponentMonomM = p_GetComp(pMonom, rRing);
593
594  poly pResult = NULL;
595  poly* ppPrev = &pResult;
596
597  for( poly p = pPoly; p!= NULL; pIter(p) )
598  {
599#ifdef PDEBUG
600    p_Test(p, rRing);
601#endif
602    const int iComponent = p_GetComp(p, rRing);
603
604    if( iComponentMonomM!=0 )
605    {
606      if( iComponent!=0 ) // TODO: make global if on iComponentMonomM =?= 0
607      {
608        // REPORT_ERROR
609        Werror("sca_mm_Mult_pp: exponent mismatch %d and %d\n", iComponent, iComponentMonomM);
610        // what should we do further?!?
611
612        p_Delete( &pResult, rRing); // delete the result
613        return NULL;
614      }
615#ifdef PDEBUG
616      if(iComponent==0 )
617      {
618        dReportError("sca_mm_Mult_pp: Multiplication in the left module from the right!");
619//        PrintS("mm = "); p_Write(pMonom, rRing);
620//        PrintS("pp = "); p_Write(pPoly, rRing);
621//        assume(iComponent!=0);
622      }
623#endif
624    }
625
626    // terms will be in the same order because of quasi-ordering!
627    poly v = sca_mm_Mult_mm(pMonom, p, rRing);
628
629    if( v != NULL )
630    {
631      *ppPrev = v;
632      ppPrev = &pNext(*ppPrev); // nice line ;-)
633    }
634  }
635
636#ifdef PDEBUG
637  p_Test(pResult,rRing);
638#endif
639
640  return(pResult);
641}
642
643
644// return poly = pMonom * pPoly; preserve pMonom, destroy or reuse pPoly.
645static poly sca_mm_Mult_p(const poly pMonom, poly pPoly, const ring rRing) // !!!!! the MOST used procedure !!!!!
646{
647  assume( rIsSCA(rRing) );
648
649#ifdef PDEBUG
650  p_Test(pPoly, rRing);
651  p_Test(pMonom, rRing);
652#endif
653
654  if( pPoly == NULL )
655    return NULL;
656
657  assume(pMonom!=NULL);
658  //if( pMonom == NULL )
659  //{
660  //  // pPoly != NULL =>
661  //  p_Delete( &pPoly, rRing );
662  //  return NULL;
663  //}
664
665  const int iComponentMonomM = p_GetComp(pMonom, rRing);
666
667  poly p = pPoly; poly* ppPrev = &pPoly;
668
669  loop
670  {
671#ifdef PDEBUG
672    if( !p_Test(p, rRing) )
673    {
674      PrintS("p is wrong!");
675      p_Write(p,rRing);
676    }
677#endif
678
679    const int iComponent = p_GetComp(p, rRing);
680
681    if( iComponentMonomM!=0 )
682    {
683      if( iComponent!=0 )
684      {
685        // REPORT_ERROR
686        Werror("sca_mm_Mult_p: exponent mismatch %d and %d\n", iComponent, iComponentMonomM);
687        // what should we do further?!?
688
689        p_Delete( &pPoly, rRing); // delete the result
690        return NULL;
691      }
692#ifdef PDEBUG
693      if(iComponent==0)
694      {
695        dReportError("sca_mm_Mult_p: Multiplication in the left module from the right!");
696//        PrintS("mm = "); p_Write(pMonom, rRing);
697//        PrintS("p = "); p_Write(pPoly, rRing);
698//        assume(iComponent!=0);
699      }
700#endif
701    }
702
703    // terms will be in the same order because of quasi-ordering!
704    poly v = sca_mm_Mult_m(pMonom, p, rRing);
705
706    if( v != NULL )
707    {
708      ppPrev = &pNext(p);
709
710    // *p is changed if v != NULL ( p == v )
711      pIter(p);
712
713      if( p == NULL )
714        break;
715    }
716    else
717    { // Upps! Zero!!! we must kill this term!
718      p = p_LmDeleteAndNext(p, rRing);
719
720      *ppPrev = p;
721
722      if( p == NULL )
723        break;
724    }
725  }
726
727#ifdef PDEBUG
728    if( !p_Test(pPoly, rRing) )
729    {
730      PrintS("pPoly is wrong!");
731      p_Write(pPoly, rRing);
732    }
733#endif
734
735  return(pPoly);
736}
737
738//-----------------------------------------------------------------------------------//
739
740#ifdef PDEBUG
741#endif
742
743
744
745
746//-----------------------------------------------------------------------------------//
747
748// GB computation routines:
749
750/*4
751* creates the S-polynomial of p1 and p2
752* does not destroy p1 and p2
753*/
754poly sca_SPoly( const poly p1, const poly p2, const ring r )
755{
756  assume( rIsSCA(r) );
757
758  const long lCompP1 = p_GetComp(p1,r);
759  const long lCompP2 = p_GetComp(p2,r);
760
761  if ((lCompP1!=lCompP2) && (lCompP1!=0) && (lCompP2!=0))
762  {
763#ifdef PDEBUG
764    dReportError("sca_SPoly: different non-zero components!\n");
765#endif
766    return(NULL);
767  }
768
769  poly pL = p_Lcm(p1, p2, si_max(lCompP1, lCompP2), r);       // pL = lcm( lm(p1), lm(p2) )
770
771  poly m1 = p_One( r);
772  p_ExpVectorDiff(m1, pL, p1, r);                  // m1 = pL / lm(p1)
773
774  //p_SetComp(m1,0,r);
775  //p_Setm(m1,r);
776#ifdef PDEBUG
777  p_Test(m1,r);
778#endif
779
780
781  poly m2 = p_One( r);
782  p_ExpVectorDiff (m2, pL, p2, r);                  // m2 = pL / lm(p2)
783
784  //p_SetComp(m2,0,r);
785  //p_Setm(m2,r);
786#ifdef PDEBUG
787  p_Test(m2,r);
788#endif
789
790  p_Delete(&pL,r);
791
792  number C1  = n_Copy(p_GetCoeff(p1,r),r);      // C1 = lc(p1)
793  number C2  = n_Copy(p_GetCoeff(p2,r),r);      // C2 = lc(p2)
794
795  number C = n_Gcd(C1,C2,r);                     // C = gcd(C1, C2)
796
797  if (!n_IsOne(C, r))                              // if C != 1
798  {
799    C1=n_Div(C1, C, r);                              // C1 = C1 / C
800    C2=n_Div(C2, C, r);                              // C2 = C2 / C
801  }
802
803  n_Delete(&C,r); // destroy the number C
804
805  const int iSignSum = sca_Sign_mm_Mult_mm (m1, p1, r) + sca_Sign_mm_Mult_mm (m2, p2, r);
806  // zero if different signs
807
808  assume( (iSignSum*iSignSum == 0) || (iSignSum*iSignSum == 4) );
809
810  if( iSignSum != 0 ) // the same sign!
811    C2=n_Neg (C2, r);
812
813  p_SetCoeff(m1, C2, r);                           // lc(m1) = C2!!!
814  p_SetCoeff(m2, C1, r);                           // lc(m2) = C1!!!
815
816  poly tmp1 = nc_mm_Mult_pp (m1, pNext(p1), r);    // tmp1 = m1 * tail(p1),
817  p_Delete(&m1,r);  //  => n_Delete(&C1,r);
818
819  poly tmp2 = nc_mm_Mult_pp (m2, pNext(p2), r);    // tmp1 = m2 * tail(p2),
820  p_Delete(&m2,r);  //  => n_Delete(&C1,r);
821
822  poly spoly = p_Add_q (tmp1, tmp2, r); // spoly = spoly(lt(p1), lt(p2)) + m1 * tail(p1), delete tmp1,2
823
824  if (spoly!=NULL) p_Cleardenom (spoly, r);
825//  if (spoly!=NULL) p_Content (spoly); // r?
826
827#ifdef PDEBUG
828  p_Test (spoly, r);
829#endif
830
831  return(spoly);
832}
833
834
835
836
837/*2
838* reduction of p2 with p1
839* do not destroy p1, but p2
840* p1 divides p2 -> for use in NF algorithm
841*/
842poly sca_ReduceSpoly(const poly p1, poly p2, const ring r)
843{
844  assume( rIsSCA(r) );
845
846  assume( p1 != NULL );
847
848  const long lCompP1 = p_GetComp (p1, r);
849  const long lCompP2 = p_GetComp (p2, r);
850
851  if ((lCompP1!=lCompP2) && (lCompP1!=0) && (lCompP2!=0))
852  {
853#ifdef PDEBUG
854    dReportError("sca_ReduceSpoly: different non-zero components!");
855#endif
856    return(NULL);
857  }
858
859  poly m = p_ISet (1, r);
860  p_ExpVectorDiff (m, p2, p1, r);                      // m = lm(p2) / lm(p1)
861  //p_Setm(m,r);
862#ifdef PDEBUG
863  p_Test (m,r);
864#endif
865
866  number C1 = n_Copy( p_GetCoeff(p1, r), r);
867  number C2 = n_Copy( p_GetCoeff(p2, r), r);
868
869  /* GCD stuff */
870  number C = n_Gcd(C1, C2, r);
871
872  if (!n_IsOne(C, r))
873  {
874    C1 = n_Div(C1, C, r);
875    C2 = n_Div(C2, C, r);
876  }
877  n_Delete(&C,r);
878
879  const int iSign = sca_Sign_mm_Mult_mm( m, p1, r );
880
881  if(iSign == 1)
882    C2 = n_Neg(C2,r);
883
884  p_SetCoeff(m, C2, r);
885
886#ifdef PDEBUG
887  p_Test(m,r);
888#endif
889
890  p2 = p_LmDeleteAndNext( p2, r );
891
892  p2 = p_Mult_nn(p2, C1, r); // p2 !!!
893  n_Delete(&C1,r);
894
895  poly T = nc_mm_Mult_pp(m, pNext(p1), r);
896  p_Delete(&m, r);
897
898  p2 = p_Add_q(p2, T, r);
899
900  if ( p2!=NULL ) p_Content(p2,r);
901
902#ifdef PDEBUG
903  p_Test(p2,r);
904#endif
905
906  return(p2);
907}
908
909// should be used only inside nc_SetupQuotient!
910// Check whether this our case:
911//  1. rG is  a commutative polynomial ring \otimes anticommutative algebra
912//  2. factor ideal rGR->qideal contains squares of all alternating variables.
913//
914// if yes, make rGR a super-commutative algebra!
915// NOTE: Factors of SuperCommutative Algebras are supported this way!
916//
917//  rG == NULL means that there is no separate base G-algebra in this case take rGR == rG
918
919// special case: bCopy == true (default value: false)
920// meaning: rGR copies structure from rG
921// (maybe with some minor changes, which don't change the type!)
922bool sca_SetupQuotient(ring rGR, ring rG, bool bCopy)
923{
924
925  //////////////////////////////////////////////////////////////////////////
926  // checks...
927  //////////////////////////////////////////////////////////////////////////
928  if( rG == NULL )
929    rG = rGR;
930
931  assume(rGR != NULL);
932  assume(rG  != NULL);
933  assume(rIsPluralRing(rG));
934
935#if ((defined(PDEBUG) && OUTPUT) || MYTEST)
936  PrintS("sca_SetupQuotient(rGR, rG, bCopy)");
937
938  {
939    PrintS("\nrG: \n"); rWrite(rG);
940    PrintS("\nrGR: \n"); rWrite(rGR);
941    PrintLn();
942  }
943#endif
944
945
946  if(bCopy)
947  {
948    if(rIsSCA(rG) && (rG != rGR))
949      return sca_Force(rGR, scaFirstAltVar(rG), scaLastAltVar(rG));
950    else
951      return false;
952  }
953
954  assume(!bCopy);
955
956  const int N = rG->N;
957
958  if(N < 2)
959    return false;
960
961
962//  if( (ncRingType(rG) != nc_skew) || (ncRingType(rG) != nc_comm) )
963//    return false;
964
965#if OUTPUT
966  PrintS("sca_SetupQuotient: qring?\n");
967#endif
968
969  if(rGR->qideal == NULL) // there should be a factor!
970    return false;
971
972#if OUTPUT
973  PrintS("sca_SetupQuotient: qideal!!!\n");
974#endif
975
976//  if((rG->qideal != NULL) && (rG != rGR) ) // we cannot change from factor to factor at the time, sorry!
977//    return false;
978
979
980  int iAltVarEnd = -1;
981  int iAltVarStart   = N+1;
982
983  const nc_struct* NC = rG->GetNC();
984  const ring rBase = rG; //NC->basering;
985  const matrix C   = NC->C; // live in rBase!
986  const matrix D   = NC->D; // live in rBase!
987
988#if OUTPUT
989  PrintS("sca_SetupQuotient: AltVars?!\n");
990#endif
991
992  for(int i = 1; i < N; i++)
993  {
994    for(int j = i + 1; j <= N; j++)
995    {
996      if( MATELEM(D,i,j) != NULL) // !!!???
997      {
998#if ((defined(PDEBUG) && OUTPUT) || MYTEST)
999        Print("Nonzero D[%d, %d]\n", i, j);
1000#endif
1001        return false;
1002      }
1003
1004
1005      assume(MATELEM(C,i,j) != NULL); // after CallPlural!
1006      number c = p_GetCoeff(MATELEM(C,i,j), rBase);
1007
1008      if( n_IsMOne(c, rBase) ) // !!!???
1009      {
1010        if( i < iAltVarStart)
1011          iAltVarStart = i;
1012
1013        if( j > iAltVarEnd)
1014          iAltVarEnd = j;
1015      } else
1016      {
1017        if( !n_IsOne(c, rBase) )
1018        {
1019#if ((defined(PDEBUG) && OUTPUT) || MYTEST)
1020          Print("Wrong Coeff at: [%d, %d]\n", i, j);
1021#endif
1022          return false;
1023        }
1024      }
1025    }
1026  }
1027
1028#if ((defined(PDEBUG) && OUTPUT) || MYTEST)
1029  Print("AltVars?1: [%d, %d]\n", iAltVarStart, iAltVarEnd);
1030#endif
1031
1032
1033  if( (iAltVarEnd == -1) || (iAltVarStart == (N+1)) )
1034    return false; // either no alternating varables, or a single one => we are in commutative case!
1035
1036
1037  for(int i = 1; i < N; i++)
1038  {
1039    for(int j = i + 1; j <= N; j++)
1040    {
1041      assume(MATELEM(C,i,j) != NULL); // after CallPlural!
1042      number c = p_GetCoeff(MATELEM(C,i,j), rBase);
1043
1044      if( (iAltVarStart <= i) && (j <= iAltVarEnd) ) // S <= i < j <= E
1045      { // anticommutative part
1046        if( !n_IsMOne(c, rBase) )
1047        {
1048#if ((defined(PDEBUG) && OUTPUT) || MYTEST)
1049          Print("Wrong Coeff at: [%d, %d]\n", i, j);
1050#endif
1051          return false;
1052        }
1053      } else
1054      { // should commute
1055        if( !n_IsOne(c, rBase) )
1056        {
1057#if ((defined(PDEBUG) && OUTPUT) || MYTEST)
1058          Print("Wrong Coeff at: [%d, %d]\n", i, j);
1059#endif
1060          return false;
1061        }
1062      }
1063    }
1064  }
1065
1066#if ((defined(PDEBUG) && OUTPUT) || MYTEST)
1067  Print("AltVars!?: [%d, %d]\n", iAltVarStart, iAltVarEnd);
1068#endif
1069
1070  assume( 1            <= iAltVarStart );
1071  assume( iAltVarStart < iAltVarEnd   );
1072  assume( iAltVarEnd   <= N            );
1073
1074
1075//  ring rSaveRing = assureCurrentRing(rG);
1076
1077
1078  assume(rGR->qideal != NULL);
1079  assume(rGR->N == rG->N);
1080//  assume(rG->qideal == NULL); // ?
1081
1082  const ideal idQuotient = rGR->qideal;
1083
1084
1085#if ((defined(PDEBUG) && OUTPUT) || MYTEST)
1086  PrintS("Analyzing quotient ideal:\n");
1087  idPrint(idQuotient); // in rG!!!
1088#endif
1089
1090
1091  // check for
1092  // y_{iAltVarStart}^2, y_{iAltVarStart+1}^2, \ldots, y_{iAltVarEnd}^2  (iAltVarEnd > iAltVarStart)
1093  // to be within quotient ideal.
1094
1095  bool bSCA = true;
1096
1097  int b = N+1;
1098  int e = -1;
1099
1100  if(rIsSCA(rG))
1101  {
1102    b = si_min(b, scaFirstAltVar(rG));
1103    e = si_max(e, scaLastAltVar(rG));
1104
1105#if ((defined(PDEBUG) && OUTPUT) || MYTEST)
1106    Print("AltVars!?: [%d, %d]\n", b, e);
1107#endif
1108  }
1109
1110  for ( int i = iAltVarStart; (i <= iAltVarEnd) && bSCA; i++ )
1111    if( (i < b) || (i > e) ) // otherwise it's ok since rG is an SCA!
1112    {
1113      poly square = p_One( rG);
1114      p_SetExp(square, i, 2, rG); // square = var(i)^2.
1115      p_Setm(square, rG);
1116
1117      // square = NF( var(i)^2 | Q )
1118      // NOTE: there is no better way to check this in general!
1119      square = kNF(idQuotient, NULL, square, 0, 1, rG); // must ran in currRing == rG!
1120
1121      if( square != NULL ) // var(i)^2 is not in Q?
1122      {
1123        p_Delete(&square, rG);
1124        bSCA = false;
1125        break;
1126      }
1127    }
1128 
1129#if ((defined(PDEBUG) && OUTPUT) || MYTEST)
1130  Print("ScaVars!: [%d, %d]\n", iAltVarStart, iAltVarEnd);
1131#endif
1132
1133
1134  //////////////////////////////////////////////////////////////////////////
1135  // ok... here we go. let's setup it!!!
1136  //////////////////////////////////////////////////////////////////////////
1137  ideal tempQ = id_KillSquares(idQuotient, iAltVarStart, iAltVarEnd, rG); // in rG!!!
1138
1139
1140#if ((defined(PDEBUG) && OUTPUT) || MYTEST)
1141  PrintS("Quotient: \n");
1142  iiWriteMatrix((matrix)idQuotient,"__",1);
1143  PrintS("tempSCAQuotient: \n");
1144  iiWriteMatrix((matrix)tempQ,"__",1);
1145#endif
1146
1147  idSkipZeroes( tempQ );
1148
1149  ncRingType( rGR, nc_exterior );
1150
1151  scaFirstAltVar( rGR, iAltVarStart );
1152  scaLastAltVar( rGR, iAltVarEnd );
1153
1154  if( idIs0(tempQ) )
1155    rGR->GetNC()->SCAQuotient() = NULL;
1156  else
1157    rGR->GetNC()->SCAQuotient() = idrMoveR(tempQ, rG, rGR); // deletes tempQ!
1158
1159  nc_p_ProcsSet(rGR, rGR->p_Procs); // !!!!!!!!!!!!!!!!!
1160
1161
1162#if ((defined(PDEBUG) && OUTPUT) || MYTEST)
1163  PrintS("SCAQuotient: \n");
1164  if(tempQ != NULL)
1165    iiWriteMatrix((matrix)tempQ,"__",1);
1166  else
1167    PrintS("(NULL)\n");
1168#endif
1169
1170  return true;
1171}
1172
1173
1174bool sca_Force(ring rGR, int b, int e)
1175{
1176  assume(rGR != NULL);
1177  assume(rIsPluralRing(rGR));
1178  assume(!rIsSCA(rGR));
1179
1180  const int N = rGR->N;
1181
1182//  ring rSaveRing = currRing;
1183//  if(rSaveRing != rGR)
1184//    rChangeCurrRing(rGR);
1185
1186  const ideal idQuotient = rGR->qideal;
1187
1188  ideal tempQ = idQuotient;
1189
1190  if( b <= N && e >= 1 )
1191    tempQ = id_KillSquares(idQuotient, b, e, rGR);
1192
1193  idSkipZeroes( tempQ );
1194
1195  ncRingType( rGR, nc_exterior );
1196
1197  if( idIs0(tempQ) )
1198    rGR->GetNC()->SCAQuotient() = NULL;
1199  else
1200    rGR->GetNC()->SCAQuotient() = tempQ;
1201
1202
1203  scaFirstAltVar( rGR, b );
1204  scaLastAltVar( rGR, e );
1205
1206
1207  nc_p_ProcsSet(rGR, rGR->p_Procs);
1208
1209//  if(rSaveRing != rGR)
1210//    rChangeCurrRing(rSaveRing);
1211
1212  return true;
1213}
1214
1215// return x_i * pPoly; preserve pPoly.
1216poly sca_pp_Mult_xi_pp(unsigned int i, const poly pPoly, const ring rRing)
1217{
1218  assume(1 <= i);
1219  assume(i <= (unsigned int)rRing->N);
1220
1221  if(rIsSCA(rRing))
1222    return sca_xi_Mult_pp(i, pPoly, rRing);
1223
1224
1225
1226  poly xi =  p_One( rRing);
1227  p_SetExp(xi, i, 1, rRing);
1228  p_Setm(xi, rRing);
1229
1230  poly pResult = pp_Mult_qq(xi, pPoly, rRing);
1231
1232  p_Delete( &xi, rRing);
1233
1234  return pResult;
1235
1236}
1237
1238void sca_p_ProcsSet(ring rGR, p_Procs_s* p_Procs)
1239{
1240
1241  // "commutative" procedures:
1242  rGR->p_Procs->p_Mult_mm     = sca_p_Mult_mm;
1243  rGR->p_Procs->pp_Mult_mm    = sca_pp_Mult_mm;
1244
1245  p_Procs->p_Mult_mm          = sca_p_Mult_mm;
1246  p_Procs->pp_Mult_mm         = sca_pp_Mult_mm;
1247
1248  // non-commutaitve
1249  rGR->GetNC()->p_Procs.mm_Mult_p   = sca_mm_Mult_p;
1250  rGR->GetNC()->p_Procs.mm_Mult_pp  = sca_mm_Mult_pp;
1251
1252//   rGR->GetNC()->p_Procs.SPoly         = sca_SPoly;
1253//   rGR->GetNC()->p_Procs.ReduceSPoly   = sca_ReduceSpoly;
1254
1255#if 0
1256
1257        // Multiplication procedures:
1258
1259        p_Procs->p_Mult_mm   = sca_p_Mult_mm;
1260        _p_procs->p_Mult_mm  = sca_p_Mult_mm;
1261
1262        p_Procs->pp_Mult_mm  = sca_pp_Mult_mm;
1263        _p_procs->pp_Mult_mm = sca_pp_Mult_mm;
1264
1265        r->GetNC()->mmMultP()     = sca_mm_Mult_p;
1266        r->GetNC()->mmMultPP()    = sca_mm_Mult_pp;
1267
1268/*
1269        // ??????????????????????????????????????? coefficients swell...
1270        r->GetNC()->SPoly()         = sca_SPoly;
1271        r->GetNC()->ReduceSPoly()   = sca_ReduceSpoly;
1272*/
1273//         r->GetNC()->BucketPolyRed() = gnc_kBucketPolyRed;
1274//         r->GetNC()->BucketPolyRed_Z()= gnc_kBucketPolyRed_Z;
1275#endif
1276
1277  // local ordering => Mora, otherwise - Buchberger!       
1278  if (rHasLocalOrMixedOrdering(rGR))
1279    rGR->GetNC()->p_Procs.GB          = cast_A_to_vptr(sca_mora);
1280  else
1281    rGR->GetNC()->p_Procs.GB          = cast_A_to_vptr(sca_bba); // sca_gr_bba?
1282}
1283
1284
1285// bi-Degree (x, y) of monomial "m"
1286// x-es and y-s are weighted by wx and wy resp.
1287// [optional] components have weights by wCx and wCy.
1288static inline void m_GetBiDegree(const poly m,
1289  const intvec *wx, const intvec *wy,
1290  const intvec *wCx, const intvec *wCy,
1291  int& dx, int& dy, const ring r)
1292{
1293  const unsigned int N  = r->N;
1294
1295  p_Test(m, r);
1296
1297  assume( wx != NULL );
1298  assume( wy != NULL );
1299
1300  assume( wx->cols() == 1 );
1301  assume( wy->cols() == 1 );
1302
1303  assume( (unsigned int)wx->rows() >= N );
1304  assume( (unsigned int)wy->rows() >= N );
1305
1306  int x = 0;
1307  int y = 0;
1308
1309  for(int i = N; i > 0; i--)
1310  {
1311    const int d = p_GetExp(m, i, r);
1312    x += d * (*wx)[i-1];
1313    y += d * (*wy)[i-1];
1314  }
1315
1316  if( (wCx != NULL) && (wCy != NULL) )
1317  {
1318    const int c = p_GetComp(m, r);
1319
1320    if( wCx->range(c) )
1321      x += (*wCx)[c];
1322
1323    if( wCy->range(c) )
1324      x += (*wCy)[c];
1325  }
1326
1327  dx = x;
1328  dy = y;
1329}
1330
1331// returns true if polynom p is bi-homogenous with respect to the given weights
1332// simultaneously sets bi-Degree
1333bool p_IsBiHomogeneous(const poly p,
1334  const intvec *wx, const intvec *wy,
1335  const intvec *wCx, const intvec *wCy,
1336  int &dx, int &dy,
1337  const ring r)
1338{
1339  if( p == NULL )
1340  {
1341    dx = 0;
1342    dy = 0;
1343    return true;
1344  }
1345
1346  poly q = p;
1347
1348
1349  int ddx, ddy;
1350
1351  m_GetBiDegree( q, wx, wy, wCx, wCy, ddx, ddy, r); // get bi degree of lm(p)
1352
1353  pIter(q);
1354
1355  for(; q != NULL; pIter(q) )
1356  {
1357    int x, y;
1358
1359    m_GetBiDegree( q, wx, wy, wCx, wCy, x, y, r); // get bi degree of q
1360
1361    if ( (x != ddx) || (y != ddy) ) return false;
1362  }
1363
1364  dx = ddx;
1365  dy = ddy;
1366
1367  return true;
1368}
1369
1370
1371// returns true if id is bi-homogenous without respect to the given weights
1372bool id_IsBiHomogeneous(const ideal id,
1373  const intvec *wx, const intvec *wy,
1374  const intvec *wCx, const intvec *wCy,
1375  const ring r)
1376{
1377  if (id == NULL) return true; // zero ideal
1378
1379  const int iSize = IDELEMS(id);
1380
1381  if (iSize == 0) return true;
1382
1383  bool b = true;
1384  int x, y;
1385
1386  for(int i = iSize - 1; (i >= 0 ) && b; i--)
1387    b = p_IsBiHomogeneous(id->m[i], wx, wy, wCx, wCy, x, y, r);
1388
1389  return b;
1390}
1391
1392
1393// returns an intvector with [nvars(r)] integers [1/0]
1394// 1 - for commutative variables
1395// 0 - for anticommutative variables
1396intvec *ivGetSCAXVarWeights(const ring r)
1397{
1398  const unsigned int N  = r->N;
1399
1400  const int CommutativeVariable = 0; // bug correction!
1401  const int AntiCommutativeVariable = 0;
1402
1403  intvec* w = new intvec(N, 1, CommutativeVariable);
1404
1405  if(AntiCommutativeVariable != CommutativeVariable)
1406  if( rIsSCA(r) )
1407  {
1408    const unsigned int m_iFirstAltVar = scaFirstAltVar(r);
1409    const unsigned int m_iLastAltVar  = scaLastAltVar(r);
1410
1411    for (unsigned int i = m_iFirstAltVar; i<= m_iLastAltVar; i++)
1412    {
1413      (*w)[i-1] = AntiCommutativeVariable;
1414    }
1415  }
1416
1417  return w;
1418}
1419
1420
1421// returns an intvector with [nvars(r)] integers [1/0]
1422// 0 - for commutative variables
1423// 1 - for anticommutative variables
1424intvec *ivGetSCAYVarWeights(const ring r)
1425{
1426  const unsigned int N  = r->N;
1427
1428  const int CommutativeVariable = 0;
1429  const int AntiCommutativeVariable = 1;
1430
1431  intvec* w = new intvec(N, 1, CommutativeVariable);
1432
1433  if(AntiCommutativeVariable != CommutativeVariable)
1434  if( rIsSCA(r) )
1435  {
1436    const unsigned int m_iFirstAltVar = scaFirstAltVar(r);
1437    const unsigned int m_iLastAltVar  = scaLastAltVar(r);
1438
1439    for (unsigned int i = m_iFirstAltVar; i<= m_iLastAltVar; i++)
1440    {
1441      (*w)[i-1] = AntiCommutativeVariable;
1442    }
1443  }
1444  return w;
1445}
1446
1447
1448
1449
1450// reduce term lt(m) modulo <y_i^2> , i = iFirstAltVar .. iLastAltVar:
1451// either create a copy of m or return NULL
1452static inline poly m_KillSquares(const poly m,
1453  const unsigned int iFirstAltVar, const unsigned int iLastAltVar,
1454  const ring r)
1455{
1456#ifdef PDEBUG
1457  p_Test(m, r);
1458  assume( (iFirstAltVar >= 1) && (iLastAltVar <= r->N) && (iFirstAltVar <= iLastAltVar) );
1459
1460#if 0
1461  Print("m_KillSquares, m = "); // !
1462  p_Write(m, r);
1463#endif
1464#endif
1465
1466  assume( m != NULL );
1467
1468  for(unsigned int k = iFirstAltVar; k <= iLastAltVar; k++)
1469    if( p_GetExp(m, k, r) > 1 )
1470      return NULL;
1471
1472  return p_Head(m, r);
1473}
1474
1475
1476// reduce polynomial p modulo <y_i^2> , i = iFirstAltVar .. iLastAltVar
1477// returns a new poly!
1478poly p_KillSquares(const poly p,
1479  const unsigned int iFirstAltVar, const unsigned int iLastAltVar,
1480  const ring r)
1481{
1482#ifdef PDEBUG
1483  p_Test(p, r);
1484
1485  assume( (iFirstAltVar >= 1) && (iLastAltVar <= r->N) && (iFirstAltVar <= iLastAltVar) );
1486
1487#if 0
1488  Print("p_KillSquares, p = "); // !
1489  p_Write(p, r);
1490#endif
1491#endif
1492
1493
1494  if( p == NULL )
1495    return NULL;
1496
1497  poly pResult = NULL;
1498  poly* ppPrev = &pResult;
1499
1500  for( poly q = p; q!= NULL; pIter(q) )
1501  {
1502#ifdef PDEBUG
1503    p_Test(q, r);
1504#endif
1505
1506    // terms will be in the same order because of quasi-ordering!
1507    poly v = m_KillSquares(q, iFirstAltVar, iLastAltVar, r);
1508
1509    if( v != NULL )
1510    {
1511      *ppPrev = v;
1512      ppPrev = &pNext(v);
1513    }
1514
1515  }
1516
1517#ifdef PDEBUG
1518  p_Test(pResult, r);
1519#if 0
1520  Print("p_KillSquares => "); // !
1521  p_Write(pResult, r);
1522#endif
1523#endif
1524
1525  return(pResult);
1526}
1527
1528
1529
1530
1531// reduces ideal id modulo <y_i^2> , i = iFirstAltVar .. iLastAltVar
1532// returns the reduced ideal or zero ideal.
1533ideal id_KillSquares(const ideal id,
1534  const unsigned int iFirstAltVar, const unsigned int iLastAltVar,
1535  const ring r, const bool bSkipZeroes)
1536{
1537  if (id == NULL) return id; // zero ideal
1538
1539  assume( (iFirstAltVar >= 1) && (iLastAltVar <= r->N) && (iFirstAltVar <= iLastAltVar) );
1540
1541  const int iSize = IDELEMS(id);
1542
1543  if (iSize == 0) return id;
1544
1545  ideal temp = idInit(iSize, id->rank);
1546
1547#if 0
1548   PrintS("<id_KillSquares>\n");
1549  {
1550    PrintS("ideal id: \n");
1551    for (int i = 0; i < IDELEMS(id); i++)
1552    {
1553      Print("; id[%d] = ", i+1);
1554      p_Write(id->m[i], r);
1555    }
1556    PrintS(";\n");
1557    PrintLn();
1558  }
1559#endif
1560
1561
1562  for (int j = 0; j < iSize; j++)
1563    temp->m[j] = p_KillSquares(id->m[j], iFirstAltVar, iLastAltVar, r);
1564
1565  if( bSkipZeroes )
1566    idSkipZeroes(temp);
1567
1568#if 0
1569   PrintS("<id_KillSquares>\n");
1570  {
1571    PrintS("ideal temp: \n");
1572    for (int i = 0; i < IDELEMS(temp); i++)
1573    {
1574      Print("; temp[%d] = ", i+1);
1575      p_Write(temp->m[i], r);
1576    }
1577    PrintS(";\n");
1578    PrintLn();
1579  }
1580   PrintS("</id_KillSquares>\n");
1581#endif
1582
1583//  temp->rank = idRankFreeModule(temp, r);
1584
1585  return temp;
1586}
1587
1588
1589
1590
1591#endif
Note: See TracBrowser for help on using the repository browser.