source: git/Singular/dyn_modules/syzextra/syzextra.cc @ da86b61

fieker-DuValspielwiese
Last change on this file since da86b61 was da86b61, checked in by Oleksandr Motsak <motsak@…>, 10 years ago
Revert "fix: qsort_r" This reverts commit 50a6c59553a4e9ed5c3b72c3937a614ffbeac4f5.
  • Property mode set to 100644
File size: 56.3 KB
Line 
1// -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2/*****************************************************************************\
3 * Computer Algebra System SINGULAR
4\*****************************************************************************/
5/** @file syzextra.cc
6 *
7 * Here we implement the Computation of Syzygies
8 *
9 * ABSTRACT: Computation of Syzygies due to Schreyer
10 *
11 * @author Oleksandr Motsak
12 *
13 **/
14/*****************************************************************************/
15
16// include header file
17#include <kernel/mod2.h>
18
19#include "syzextra.h"
20
21#include "DebugPrint.h"
22
23#include <omalloc/omalloc.h>
24
25#include <misc/intvec.h>
26#include <misc/options.h>
27
28#include <coeffs/coeffs.h>
29
30#include <polys/monomials/p_polys.h>
31#include <polys/monomials/ring.h>
32#include <polys/simpleideals.h>
33
34#include <polys/kbuckets.h> // for kBucket*
35#include <polys/sbuckets.h> // for sBucket*
36//#include <polys/nc/summator.h> // for CPolynomialSummator
37#include <polys/operations/p_Mult_q.h> // for MIN_LENGTH_BUCKET
38
39#include <kernel/GBEngine/kstd1.h>
40#include <kernel/polys.h>
41#include <kernel/GBEngine/syz.h>
42#include <kernel/ideals.h>
43
44#include <kernel/oswrapper/timer.h>
45
46
47#include <Singular/tok.h>
48#include <Singular/ipid.h>
49#include <Singular/lists.h>
50#include <Singular/attrib.h>
51
52#include <Singular/ipid.h>
53#include <Singular/ipshell.h> // For iiAddCproc
54
55#include <stdio.h>
56#include <stdlib.h>
57#include <string.h>
58
59// USING_NAMESPACE_SINGULARXX;
60USING_NAMESPACE( SINGULARXXNAME :: DEBUG )
61
62
63BEGIN_NAMESPACE_SINGULARXX     BEGIN_NAMESPACE(SYZEXTRA)
64
65
66BEGIN_NAMESPACE(SORT_c_ds)
67
68#if (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || defined __FREEBSD__ || defined __BSD__ || defined OpenBSD3_1 || defined OpenBSD3_9)
69static int cmp_c_ds(void *R, const void *p1, const void *p2){
70#elif (defined _GNU_SOURCE || defined __GNU__ || defined __linux__)
71static int cmp_c_ds(const void *p1, const void *p2, void *R){
72#else
73static int cmp_c_ds(const void *p1, const void *p2){ void *R = currRing;
74#endif
75  assume(R != NULL);
76  const int YES = 1;
77  const int NO = -1;
78
79  const ring r =  (const ring) R; // TODO/NOTE: the structure is known: C, lp!!!
80
81  assume( r == currRing ); // for now...
82
83  const poly a = *(const poly*)p1;
84  const poly b = *(const poly*)p2;
85
86  assume( a != NULL );
87  assume( b != NULL );
88
89  assume( p_LmTest(a, r) );
90  assume( p_LmTest(b, r) );
91
92
93  const signed long iCompDiff = p_GetComp(a, r) - p_GetComp(b, r);
94
95  // TODO: test this!!!!!!!!!!!!!!!!
96
97  //return -( compare (c, qsorts) )
98
99#ifndef NDEBUG
100  const int __DEBUG__ = 0;
101  if( __DEBUG__ )
102  {
103    PrintS("cmp_c_ds: a, b: \np1: "); dPrint(a, r, r, 2);
104    PrintS("b: "); dPrint(b, r, r, 2);
105    PrintLn();
106  }
107#endif
108
109
110  if( iCompDiff > 0 )
111    return YES;
112
113  if( iCompDiff < 0 )
114    return  NO;
115
116  assume( iCompDiff == 0 );
117
118  const signed long iDegDiff = p_Totaldegree(a, r) - p_Totaldegree(b, r);
119
120  if( iDegDiff > 0 )
121    return YES;
122
123  if( iDegDiff < 0 )
124    return  NO;
125
126  assume( iDegDiff == 0 );
127
128#ifndef NDEBUG
129  if( __DEBUG__ )
130  {
131    PrintS("cmp_c_ds: a & b have the same comp & deg! "); PrintLn();
132  }
133#endif
134
135  for (int v = rVar(r); v > 0; v--)
136  {
137    assume( v > 0 );
138    assume( v <= rVar(r) );
139
140    const signed int d = p_GetExp(a, v, r) - p_GetExp(b, v, r);
141
142    if( d > 0 )
143      return YES;
144
145    if( d < 0 )
146      return NO;
147
148    assume( d == 0 );
149  }
150
151  return 0;
152}
153
154/*
155static int cmp_poly(const poly &a, const poly &b)
156{
157  const int YES = 1;
158  const int NO = -1;
159
160  const ring r =  (const ring) currRing; // TODO/NOTE: the structure is known: C, lp!!!
161
162  assume( r == currRing );
163
164  assume( a != NULL );
165  assume( b != NULL );
166
167  assume( p_LmTest(a, r) );
168  assume( p_LmTest(b, r) );
169  assume( p_GetComp(a, r) == 0 );
170  assume( p_GetComp(b, r) == 0 );
171
172#ifndef NDEBUG
173  const int __DEBUG__ = 0;
174  if( __DEBUG__ )
175  {
176    PrintS("cmp_lex: a, b: \np1: "); dPrint(a, r, r, 2);
177    PrintS("b: "); dPrint(b, r, r, 2);
178    PrintLn();
179  }
180#endif
181
182  for (int v = rVar(r); v > 0; v--)
183  {
184    assume( v > 0 );
185    assume( v <= rVar(r) );
186
187    const signed int d = p_GetExp(a, v, r) - p_GetExp(b, v, r);
188
189    if( d > 0 )
190      return YES;
191
192    if( d < 0 )
193      return NO;
194
195    assume( d == 0 );
196  }
197
198  return 0;
199}
200*/
201
202END_NAMESPACE
203/* namespace SORT_c_ds */
204
205/// writes a monomial (p),
206/// uses form x*gen(.) if ko != coloumn number of p
207static void writeLatexTerm(const poly t, const ring r, const bool bCurrSyz = true, const bool bLTonly = true)
208{
209  if( t == NULL )
210  {
211    PrintS(" 0 ");
212    return;
213  }
214
215  assume( r != NULL );
216  const coeffs C = r->cf; assume(C != NULL);
217
218  poly p = t;
219  BOOLEAN writePlus = FALSE;
220
221  do {
222  assume( p != NULL );
223
224  // write coef...
225  number& n = p_GetCoeff(p, r);
226
227  n_Normalize(n, C);
228
229  BOOLEAN writeMult = FALSE; ///< needs * before pp or module generator
230
231  BOOLEAN writeOne = FALSE; ///< need to write something after '-'!
232
233  if( n_IsZero(n, C) )
234  {
235    PrintS( writePlus? " + 0" : " 0 " ); writePlus = TRUE; writeMult = TRUE;
236//    return; // yes?
237  }
238
239  if (n_IsMOne(n, C))
240  {
241    PrintS(" - "); writeOne = TRUE; writePlus = FALSE;
242  }
243  else if (!n_IsOne(n, C))
244  {
245    if( writePlus && n_GreaterZero(n, C) )
246      PrintS(" + ");
247
248    StringSetS(""); n_WriteLong(n, C);
249    if (true)
250    {
251      char *s = StringEndS(); PrintS(s); omFree(s);
252    }
253
254
255    writeMult = TRUE;
256    writePlus = TRUE;
257  } else
258     writeOne = TRUE;
259
260  // missing '1' if no PP and gen...!?
261  // write monom...
262  const short N = rVar(r);
263
264  BOOLEAN wrotePP = FALSE; ///< needs * before module generator?
265
266  for (short i = 0; i < N; i++)
267  {
268    const long ee = p_GetExp(p, i+1, r);
269
270    if (ee!=0L)
271    {
272      if (writeMult)
273      {
274        PrintS(" \\\\cdot ");
275        writeMult = FALSE;
276      } else
277      if( writePlus )
278        PrintS(" + ");
279
280      writePlus = FALSE;
281
282      if (ee != 1L)
283        Print(" %s^{%ld} ", rRingVar(i, r), ee);
284      else
285        Print(" %s ", rRingVar(i, r));
286
287      writeOne = FALSE;
288      wrotePP = TRUE;
289    }
290  }
291
292  writePlus = writePlus || wrotePP;
293  writeMult = writeMult || wrotePP;
294
295  // write module gen...
296  const long comp = p_GetComp(p, r);
297
298  if (comp > 0 )
299  {
300    if (writeMult)
301      PrintS(" \\\\cdot ");
302     else
303      if( writePlus )
304        PrintS(" + ");
305
306    if (bCurrSyz)
307      Print(" \\\\GEN{%ld} ", comp);
308    else
309      Print(" \\\\GENP{%ld} ", comp);
310
311      writeOne = FALSE;
312  }
313
314  if ( writeOne )
315    PrintS( writePlus? " + 1 " : " 1 " );
316
317
318  pIter(p);
319
320  writePlus = TRUE;
321  } while( (!bLTonly) && (p != NULL) );
322
323}
324
325
326
327
328
329/// return a new term: leading coeff * leading monomial of p
330/// with 0 leading component!
331poly leadmonom(const poly p, const ring r, const bool bSetZeroComp)
332{
333  poly m = NULL;
334
335  if( p != NULL )
336  {
337    assume( p != NULL );
338    assume( p_LmTest(p, r) );
339
340    m = p_LmInit(p, r);
341    p_SetCoeff0(m, n_Copy(p_GetCoeff(p, r), r), r);
342
343    if( bSetZeroComp )
344      p_SetComp(m, 0, r);
345    p_Setm(m, r);
346
347
348    assume( m != NULL );
349    assume( pNext(m) == NULL );
350    assume( p_LmTest(m, r) );
351
352    if( bSetZeroComp )
353      assume( p_GetComp(m, r) == 0 );
354  }
355
356  return m;
357}
358
359
360
361poly p_Tail(const poly p, const ring r)
362{
363  if( p == NULL)
364    return NULL;
365  else
366    return p_Copy( pNext(p), r );
367}
368
369
370ideal id_Tail(const ideal id, const ring r)
371{
372  if( id == NULL)
373    return NULL;
374
375  const ideal newid = idInit(IDELEMS(id),id->rank);
376
377  for (int i=IDELEMS(id) - 1; i >= 0; i--)
378    newid->m[i] = p_Tail( id->m[i], r );
379
380  newid->rank = id_RankFreeModule(newid, currRing);
381
382  return newid;
383}
384
385
386
387void Sort_c_ds(const ideal id, const ring r)
388{
389  const int sizeNew = IDELEMS(id);
390
391#if (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || defined __FREEBSD__ || defined __BSD__ || defined OpenBSD3_1 || defined OpenBSD3_9)
392#define qsort_my(m, s, ss, r, cmp) qsort_r(m, s, ss, r, cmp)
393#elif (defined _GNU_SOURCE || defined __GNU__ || defined __linux__)
394#define qsort_my(m, s, ss, r, cmp) qsort_r(m, s, ss, cmp, r)
395#else
396#define qsort_my(m, s, ss, r, cmp) qsort(m, s, ss, cmp)
397#endif
398
399  if( sizeNew >= 2 )
400    qsort_my(id->m, sizeNew, sizeof(poly), r, FROM_NAMESPACE(SORT_c_ds, cmp_c_ds));
401
402#undef qsort_my
403
404  id->rank = id_RankFreeModule(id, r);
405}
406
407/// Clean up all the accumulated data
408void SchreyerSyzygyComputation::CleanUp()
409{
410  extern void id_Delete (ideal*, const ring);
411
412  id_Delete(const_cast<ideal*>(&m_idTails), m_rBaseRing); // TODO!!!
413
414  if( m_sum_bucket != NULL )
415  {
416    sBucketDestroy(&m_sum_bucket);
417    m_sum_bucket = NULL;
418  }
419
420  if( m_spoly_bucket != NULL )
421  {
422    kBucketDestroy(&m_spoly_bucket);
423    m_spoly_bucket = NULL;
424  }
425
426  for( TCache::iterator it = m_cache.begin(); it != m_cache.end(); it++ )
427  {
428    TP2PCache& T = it->second;
429
430    for(TP2PCache::iterator vit = T.begin(); vit != T.end(); vit++ )
431    {
432      p_Delete( (&(vit->second)), m_rBaseRing);
433      p_Delete( const_cast<poly*>(&(vit->first)), m_rBaseRing);
434    }
435  }
436}
437  /*
438  for( TTailTerms::const_iterator it = m_idTailTerms.begin(); it != m_idTailTerms.end(); it++ )
439  {
440    const TTail& v = *it;
441    for(TTail::const_iterator vit = v.begin(); vit != v.end(); vit++ )
442      delete const_cast<CTailTerm*>(*vit);
443  }
444  */
445
446
447
448int CReducerFinder::PreProcessTerm(const poly t, CReducerFinder& syzChecker) const
449{
450  assume( t != NULL );
451
452  if( __DEBUG__ & __TAILREDSYZ__ )
453    assume( !IsDivisible(t) ); // each input term should NOT be in <L>
454
455  const ring r = m_rBaseRing;
456
457
458  if( __TAILREDSYZ__ )
459    if( p_LmIsConstant(t, r) ) // most basic case of baing coprime with L, whatever that is...
460      return 1; // TODO: prove this...?
461
462  //   return false; // appears to be fine
463
464  const long comp = p_GetComp(t, r);
465
466  CReducersHash::const_iterator itr = m_hash.find(comp);
467
468  if ( itr == m_hash.end() )
469    return 2; // no such leading component!!!
470
471  assume( itr->first == comp );
472
473  const bool bIdealCase = (comp == 0);
474  const bool bSyzCheck = syzChecker.IsNonempty(); // need to check even in ideal case????? proof?  "&& !bIdealCase"
475
476  if( __TAILREDSYZ__ && (bIdealCase || bSyzCheck) )
477  {
478    const TReducers& v = itr->second;
479    const int N = rVar(r);
480    // TODO: extract exps of t beforehand?!
481    bool coprime = true;
482    for(TReducers::const_iterator vit = v.begin(); (vit != v.end()) && coprime; ++vit )
483    {
484      assume( m_L->m[(*vit)->m_label] == (*vit)->m_lt );
485
486      const poly p = (*vit)->m_lt;
487
488      assume( p_GetComp(p, r) == comp );
489
490      // TODO: check if coprime with Leads... if __TAILREDSYZ__ !
491      for( int var = N; var > 0; --var )
492        if( (p_GetExp(p, var, r) != 0) && (p_GetExp(t, var, r) != 0) )
493        {
494#ifndef NDEBUG
495          if( __DEBUG__ | 0)
496          {
497            PrintS("CReducerFinder::PreProcessTerm, 't' is NOT co-prime with the following leading term: \n");
498            dPrint(p, r, r, 1);
499          }
500#endif
501          coprime = false; // t not coprime with p!
502          break;
503        }
504
505      if( bSyzCheck && coprime )
506      {
507        poly ss = p_LmInit(t, r);
508        p_SetCoeff0(ss, n_Init(1, r), r); // for delete & printout only!...
509        p_SetComp(ss, (*vit)->m_label + 1, r); // coeff?
510        p_Setm(ss, r);
511
512        coprime = ( syzChecker.IsDivisible(ss) );
513
514#ifndef NDEBUG
515        if( __DEBUG__ && !coprime)
516        {
517          PrintS("CReducerFinder::PreProcessTerm, 't' is co-prime with p but may lead to NOT divisible syz.term: \n");
518          dPrint(ss, r, r, 1);
519        }
520#endif
521
522        p_LmDelete(&ss, r); // deletes coeff as well???
523      }
524
525    }
526
527#ifndef NDEBUG
528    if( __DEBUG__ && coprime )
529      PrintS("CReducerFinder::PreProcessTerm, the following 't' is 'co-prime' with all of leading terms! \n");
530#endif
531
532    return coprime? 3: 0; // t was coprime with all of leading terms!!!
533
534  }
535  //   return true; // delete the term
536
537  return 0;
538}
539
540
541void SchreyerSyzygyComputation::SetUpTailTerms()
542{
543  const ideal idTails = m_idTails;
544  assume( idTails != NULL );
545  assume( idTails->m != NULL );
546  const ring r = m_rBaseRing;
547
548#ifndef NDEBUG
549  if( __DEBUG__ | 0)
550  {
551    PrintS("SchreyerSyzygyComputation::SetUpTailTerms(): Tails: \n");
552    dPrint(idTails, r, r, 0);
553  }
554
555  unsigned long pp[4] = {0,0,0,0}; // count preprocessed terms...
556#endif
557
558  for( int p = IDELEMS(idTails) - 1; p >= 0; --p )
559    for( poly* tt = &(idTails->m[p]); (*tt) != NULL;  )
560    {
561      const poly t = *tt;
562      const int k = m_div.PreProcessTerm(t, m_checker); // 0..3
563      assume( 0 <= k && k <= 3 );
564
565#ifndef NDEBUG
566      pp[k]++;
567#endif
568
569      if( k )
570      {
571#ifndef NDEBUG
572        if( __DEBUG__)
573        {
574          Print("SchreyerSyzygyComputation::SetUpTailTerms(): PP (%d) the following TT: \n", k);
575          dPrint(t, r, r, 1);
576        }
577#endif
578
579        (*tt) = p_LmDeleteAndNext(t, r); // delete the lead and next...
580      }
581      else
582        tt = &pNext(t); // go next?
583
584    }
585
586#ifndef NDEBUG
587  if( !__TREEOUTPUT__ )
588  if( TEST_OPT_PROT | 1)
589    Print("%%      **!!**      SchreyerSyzygyComputation::SetUpTailTerms()::PreProcessing(): X: {c: %lu, C: %lu, P: %lu} + %lu\n", pp[1], pp[2], pp[3], pp[0]);
590#endif
591
592#ifndef NDEBUG
593  if( !__TREEOUTPUT__ )
594  if( __DEBUG__ | 0)
595  {
596    PrintS("SchreyerSyzygyComputation::SetUpTailTerms(): Preprocessed Tails: \n");
597    dPrint(idTails, r, r, 0);
598  }
599#endif
600
601}
602/*
603  m_idTailTerms.resize( IDELEMS(idTails) );
604
605  for( unsigned int p = IDELEMS(idTails) - 1; p >= 0; p -- )
606  {
607    TTail& v = m_idTailTerms[p];
608    poly t = idTails->m[p];
609    v.resize( pLength(t) );
610
611    unsigned int pp = 0;
612
613    while( t != NULL )
614    {
615      assume( t != NULL );
616      // TODO: compute L:t!
617//      ideal reducers;
618//      CReducerFinder m_reducers
619
620      CTailTerm* d = v[pp] = new CTailTerm();
621
622      ++pp; pIter(t);
623    }
624  }
625*/
626
627
628
629ideal SchreyerSyzygyComputation::Compute1LeadingSyzygyTerms()
630{
631  const ideal& id = m_idLeads;
632  const ring& r = m_rBaseRing;
633//  const SchreyerSyzygyComputationFlags& attributes = m_atttributes;
634
635//   const BOOLEAN __DEBUG__      = attributes.__DEBUG__;
636//   const BOOLEAN __SYZCHECK__   = attributes.__SYZCHECK__;
637//   const BOOLEAN __LEAD2SYZ__   = attributes.__LEAD2SYZ__;
638//   const BOOLEAN __HYBRIDNF__   = attributes.__HYBRIDNF__;
639//   const BOOLEAN __TAILREDSYZ__ = attributes.__TAILREDSYZ__;
640
641  assume(!__LEAD2SYZ__);
642
643  // 1. set of components S?
644  // 2. for each component c from S: set of indices of leading terms
645  // with this component?
646  // 3. short exp. vectors for each leading term?
647
648  const int size = IDELEMS(id);
649
650  if( size < 2 )
651  {
652    const ideal newid = idInit(1, 0); newid->m[0] = NULL; // zero ideal...
653    return newid;
654  }
655
656  // TODO/NOTE: input is supposed to be (reverse-) sorted wrt "(c,ds)"!??
657
658  // components should come in groups: count elements in each group
659  // && estimate the real size!!!
660
661
662  // use just a vector instead???
663  const ideal newid = idInit( (size * (size-1))/2, size); // maximal size: ideal case!
664
665  int k = 0;
666
667  for (int j = 0; j < size; j++)
668  {
669    const poly p = id->m[j];
670    assume( p != NULL );
671    const int  c = p_GetComp(p, r);
672
673    for (int i = j - 1; i >= 0; i--)
674    {
675      const poly pp = id->m[i];
676      assume( pp != NULL );
677      const int  cc = p_GetComp(pp, r);
678
679      if( c != cc )
680        continue;
681
682      const poly m = p_Init(r); // p_New???
683
684      // m = LCM(p, pp) / p! // TODO: optimize: knowing the ring structure: (C/lp)!
685      for (int v = rVar(r); v > 0; v--)
686      {
687        assume( v > 0 );
688        assume( v <= rVar(r) );
689
690        const short e1 = p_GetExp(p , v, r);
691        const short e2 = p_GetExp(pp, v, r);
692
693        if( e1 >= e2 )
694          p_SetExp(m, v, 0, r);
695        else
696          p_SetExp(m, v, e2 - e1, r);
697
698      }
699
700      assume( (j > i) && (i >= 0) );
701
702      p_SetComp(m, j + 1, r);
703      pNext(m) = NULL;
704      p_SetCoeff0(m, n_Init(1, r->cf), r); // for later...
705
706      p_Setm(m, r); // should not do anything!!!
707
708      newid->m[k++] = m;
709    }
710  }
711
712//   if( __DEBUG__ && FALSE )
713//   {
714//     PrintS("ComputeLeadingSyzygyTerms::Temp0: \n");
715//     dPrint(newid, r, r, 1);
716//   }
717
718  // the rest of newid is assumed to be zeroes...
719
720  // simplify(newid, 2 + 32)??
721  // sort(newid, "C,ds")[1]???
722  id_DelDiv(newid, r); // #define SIMPL_LMDIV 32
723
724//   if( __DEBUG__ && FALSE )
725//   {
726//     PrintS("ComputeLeadingSyzygyTerms::Temp1: \n");
727//     dPrint(newid, r, r, 1);
728//   }
729
730  idSkipZeroes(newid); // #define SIMPL_NULL 2
731
732//   if( __DEBUG__ )
733//   {
734//     PrintS("ComputeLeadingSyzygyTerms::Output: \n");
735//     dPrint(newid, r, r, 1);
736//   }
737
738  Sort_c_ds(newid, r);
739
740  return newid;
741}
742
743ideal SchreyerSyzygyComputation::Compute2LeadingSyzygyTerms()
744{
745  const ideal& id = m_idLeads;
746  const ring& r = m_rBaseRing;
747//  const SchreyerSyzygyComputationFlags& attributes = m_atttributes;
748
749//   const BOOLEAN __DEBUG__      = attributes.__DEBUG__;
750//   const BOOLEAN __SYZCHECK__   = attributes.__SYZCHECK__;
751//   const BOOLEAN __LEAD2SYZ__   = attributes.__LEAD2SYZ__;
752//   const BOOLEAN __HYBRIDNF__   = attributes.__HYBRIDNF__;
753//  const BOOLEAN __TAILREDSYZ__ = attributes.__TAILREDSYZ__;
754
755
756  // 1. set of components S?
757  // 2. for each component c from S: set of indices of leading terms
758  // with this component?
759  // 3. short exp. vectors for each leading term?
760
761  const int size = IDELEMS(id);
762
763  if( size < 2 )
764  {
765    const ideal newid = idInit(1, 1); newid->m[0] = NULL; // zero module...
766    return newid;
767  }
768
769
770  // TODO/NOTE: input is supposed to be sorted wrt "C,ds"!??
771
772  // components should come in groups: count elements in each group
773  // && estimate the real size!!!
774
775
776  // use just a vector instead???
777  ideal newid = idInit( (size * (size-1))/2, size); // maximal size: ideal case!
778
779  int k = 0;
780
781  for (int j = 0; j < size; j++)
782  {
783    const poly p = id->m[j];
784    assume( p != NULL );
785    const int  c = p_GetComp(p, r);
786
787    for (int i = j - 1; i >= 0; i--)
788    {
789      const poly pp = id->m[i];
790      assume( pp != NULL );
791      const int  cc = p_GetComp(pp, r);
792
793      if( c != cc )
794        continue;
795
796        // allocate memory & zero it out!
797      const poly m = p_Init(r); const poly mm = p_Init(r);
798
799
800        // m = LCM(p, pp) / p! mm = LCM(p, pp) / pp!
801        // TODO: optimize: knowing the ring structure: (C/lp)!
802
803      for (int v = rVar(r); v > 0; v--)
804      {
805        assume( v > 0 );
806        assume( v <= rVar(r) );
807
808        const short e1 = p_GetExp(p , v, r);
809        const short e2 = p_GetExp(pp, v, r);
810
811        if( e1 >= e2 )
812          p_SetExp(mm, v, e1 - e2, r); //            p_SetExp(m, v, 0, r);
813        else
814          p_SetExp(m, v, e2 - e1, r); //            p_SetExp(mm, v, 0, r);
815
816      }
817
818      assume( (j > i) && (i >= 0) );
819
820      p_SetComp(m, j + 1, r);
821      p_SetComp(mm, i + 1, r);
822
823      const number& lc1 = p_GetCoeff(p , r);
824      const number& lc2 = p_GetCoeff(pp, r);
825
826      number g = n_Lcm( lc1, lc2, r );
827
828      p_SetCoeff0(m ,       n_Div(g, lc1, r), r);
829      p_SetCoeff0(mm, n_InpNeg(n_Div(g, lc2, r), r), r);
830
831      n_Delete(&g, r);
832
833      p_Setm(m, r); // should not do anything!!!
834      p_Setm(mm, r); // should not do anything!!!
835
836      pNext(m) = mm; //        pNext(mm) = NULL;
837
838      newid->m[k++] = m;
839    }
840  }
841
842//   if( __DEBUG__ && FALSE )
843//   {
844//     PrintS("Compute2LeadingSyzygyTerms::Temp0: \n");
845//     dPrint(newid, r, r, 1);
846//   }
847
848  if( !__TAILREDSYZ__ )
849  {
850      // simplify(newid, 2 + 32)??
851      // sort(newid, "C,ds")[1]???
852    id_DelDiv(newid, r); // #define SIMPL_LMDIV 32
853
854//     if( __DEBUG__ && FALSE )
855//     {
856//       PrintS("Compute2LeadingSyzygyTerms::Temp1 (deldiv): \n");
857//       dPrint(newid, r, r, 1);
858//     }
859  }
860  else
861  {
862      //      option(redSB); option(redTail);
863      //      TEST_OPT_REDSB
864      //      TEST_OPT_REDTAIL
865    assume( r == currRing );
866
867    BITSET _save_test; SI_SAVE_OPT1(_save_test);
868    SI_RESTORE_OPT1(Sy_bit(OPT_REDTAIL) | Sy_bit(OPT_REDSB) | _save_test);
869
870    intvec* w=new intvec(IDELEMS(newid));
871    ideal tmp = kStd(newid, currRing->qideal, isHomog, &w);
872    delete w;
873
874    SI_RESTORE_OPT1(_save_test)
875
876    id_Delete(&newid, r);
877    newid = tmp;
878
879//     if( __DEBUG__ && FALSE )
880//     {
881//       PrintS("Compute2LeadingSyzygyTerms::Temp1 (std): \n");
882//       dPrint(newid, r, r, 1);
883//     }
884
885  }
886
887  idSkipZeroes(newid);
888
889  Sort_c_ds(newid, r);
890
891  return newid;
892}
893
894poly SchreyerSyzygyComputation::TraverseNF(const poly a, const poly a2) const
895{
896  const ideal& L = m_idLeads;
897  const ideal& T = m_idTails;
898
899  const ring& R = m_rBaseRing;
900
901  const int r = p_GetComp(a, R) - 1;
902
903  assume( r >= 0 && r < IDELEMS(T) );
904  assume( r >= 0 && r < IDELEMS(L) );
905
906  assume( a != NULL );
907
908  if( __TREEOUTPUT__ )
909  {
910     PrintS("{ \"nodelabel\": \""); writeLatexTerm(a, R); PrintS("\", \"children\": [");
911  }
912
913
914  poly aa = leadmonom(a, R); assume( aa != NULL); // :(
915
916  poly t = TraverseTail(aa, r);
917
918  if( a2 != NULL )
919  {
920    assume( __LEAD2SYZ__ );
921
922    if( __TREEOUTPUT__ )
923    {
924       PrintS("{ \"nodelabel\": \""); writeLatexTerm(a2, R); PrintS("\", \"children\": [");
925    }
926
927    // replace the following... ?
928    const int r2 = p_GetComp(a2, R) - 1; poly aa2 = leadmonom(a2, R); // :(
929
930    assume( r2 >= 0 && r2 < IDELEMS(T) );
931
932    t = p_Add_q(a2, p_Add_q(t, TraverseTail(aa2, r2), R), R);
933
934    p_Delete(&aa2, R);
935
936    if( __TREEOUTPUT__ )
937       PrintS("]},");
938
939  } else
940    t = p_Add_q(t, ReduceTerm(aa, L->m[r], a), R);
941
942  p_Delete(&aa, R);
943
944  // TODO: print t???
945
946  if( __TREEOUTPUT__ )
947  {
948     PrintS("], \"noderesult\": \""); writeLatexTerm(t, R, true, false); PrintS("\" },");
949  }
950  return t;
951}
952
953
954void SchreyerSyzygyComputation::ComputeSyzygy()
955{
956  assume( m_idLeads != NULL );
957  assume( m_idTails != NULL );
958
959  const ideal& L = m_idLeads;
960  const ideal& T = m_idTails;
961
962  ideal& TT = m_syzTails;
963  const ring& R = m_rBaseRing;
964
965  if( m_sum_bucket == NULL )
966    m_sum_bucket = sBucketCreate(R);
967
968  if( m_spoly_bucket == NULL )
969    m_spoly_bucket = kBucketCreate(R);
970
971
972  assume( IDELEMS(L) == IDELEMS(T) );
973#ifndef NDEBUG
974  int t, r;
975#endif
976
977  if( __TREEOUTPUT__ )
978  {
979    Print("\n{ \"syzygylayer\": \"%d\", \"hybridnf\": \"%d\", \"diagrams\": \n[", __SYZNUMBER__, __HYBRIDNF__ );
980  }
981
982  if( m_syzLeads == NULL )
983  {
984#ifndef NDEBUG
985    if( !__TREEOUTPUT__ )
986    if( TEST_OPT_PROT | 1)
987    {
988      t = getTimer(); r = getRTimer();
989      Print("%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::ComputeLeadingSyzygyTerms: t: %d, r: %d\n", r, t, r);
990    }
991#endif
992    ComputeLeadingSyzygyTerms( __LEAD2SYZ__ && !__IGNORETAILS__ ); // 2 terms OR 1 term!
993#ifndef NDEBUG
994    if( !__TREEOUTPUT__ )
995    if( TEST_OPT_PROT | 1)
996    {
997      t = getTimer() - t; r = getRTimer() - r;
998      Print("%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::ComputeLeadingSyzygyTerms: dt: %d, dr: %d\n", getRTimer(), t, r);
999    }
1000#endif
1001
1002  }
1003
1004  assume( m_syzLeads != NULL );
1005  ideal& LL = m_syzLeads;
1006  const int size = IDELEMS(LL);
1007
1008  TT = idInit(size, 0);
1009
1010  if( size == 1 && LL->m[0] == NULL )
1011  {
1012     if( __TREEOUTPUT__ )
1013       PrintS("]},");
1014     return;
1015  }
1016
1017
1018  // use hybrid method?
1019  const bool method = (__HYBRIDNF__  == 1) || (__HYBRIDNF__ == 2 && __SYZNUMBER__ < 3);
1020
1021  if(  !__IGNORETAILS__)
1022  {
1023    if( T != NULL )
1024    {
1025#ifndef NDEBUG
1026      if( !__TREEOUTPUT__ )
1027      if( TEST_OPT_PROT | 1 )
1028      {
1029        t = getTimer(); r = getRTimer();
1030        Print("%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::SetUpTailTerms(): t: %d, r: %d\n", r, t, r);
1031      }
1032#endif
1033
1034      SetUpTailTerms();
1035#ifndef NDEBUG
1036      if( !__TREEOUTPUT__ )
1037      if( TEST_OPT_PROT | 1)
1038      {
1039        t = getTimer() - t; r = getRTimer() - r;
1040        Print("%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::SetUpTailTerms(): dt: %d, dr: %d\n", getRTimer(), t, r);
1041      }
1042#endif
1043    }
1044  }
1045
1046#ifndef NDEBUG
1047  if( !__TREEOUTPUT__ )
1048  if( TEST_OPT_PROT | 1)
1049  {
1050    t = getTimer(); r = getRTimer();
1051    Print("%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::SyzygyLift: t: %d, r: %d\n", r, t, r);
1052  }
1053#endif
1054
1055  for( int k = size - 1; k >= 0; k-- )
1056  {
1057    const poly a = LL->m[k]; assume( a != NULL );
1058
1059    poly a2 = pNext(a);
1060
1061    // Splitting 2-terms Leading syzygy module
1062    if( a2 != NULL )
1063      pNext(a) = NULL;
1064
1065    if( __IGNORETAILS__ )
1066    {
1067      TT->m[k] = NULL;
1068
1069      assume( a2 != NULL );
1070
1071      if( a2 != NULL )
1072        p_Delete(&a2, R);
1073
1074      continue;
1075    }
1076
1077    //    TT->m[k] = a2;
1078
1079    if( method )
1080      TT->m[k] = SchreyerSyzygyNF(a, a2);
1081    else
1082      TT->m[k] = TraverseNF(a, a2);
1083  }
1084
1085#ifndef NDEBUG
1086  if( !__TREEOUTPUT__ )
1087  if( TEST_OPT_PROT | 1)
1088  {
1089    t = getTimer() - t; r = getRTimer() - r;
1090    Print("%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::SyzygyLift: dt: %d, dr: %d\n", getRTimer(), t, r);
1091  }
1092#endif
1093
1094  TT->rank = id_RankFreeModule(TT, R);
1095
1096  if( __TREEOUTPUT__ )
1097    PrintS("\n]},");
1098}
1099
1100void SchreyerSyzygyComputation::ComputeLeadingSyzygyTerms(bool bComputeSecondTerms)
1101{
1102//  const SchreyerSyzygyComputationFlags& attributes = m_atttributes;
1103
1104//  const BOOLEAN __LEAD2SYZ__   = attributes.__LEAD2SYZ__;
1105//  const BOOLEAN __TAILREDSYZ__ = attributes.__TAILREDSYZ__;
1106
1107  assume( m_syzLeads == NULL );
1108
1109  if( bComputeSecondTerms )
1110  {
1111    assume( __LEAD2SYZ__ );
1112//    m_syzLeads = FROM_NAMESPACE(INTERNAL, _Compute2LeadingSyzygyTerms(m_idLeads, m_rBaseRing, m_atttributes));
1113    m_syzLeads = Compute2LeadingSyzygyTerms();
1114  }
1115  else
1116  {
1117    assume( !__LEAD2SYZ__ );
1118
1119    m_syzLeads = Compute1LeadingSyzygyTerms();
1120  }
1121//    m_syzLeads = FROM_NAMESPACE(INTERNAL, _ComputeLeadingSyzygyTerms(m_idLeads, m_rBaseRing, m_atttributes));
1122
1123  // NOTE: set m_LS if tails are to be reduced!
1124  assume( m_syzLeads!= NULL );
1125
1126  if (__TAILREDSYZ__ && !__IGNORETAILS__ && (IDELEMS(m_syzLeads) > 0) && !((IDELEMS(m_syzLeads) == 1) && (m_syzLeads->m[0] == NULL)))
1127  {
1128    m_LS = m_syzLeads;
1129    m_checker.Initialize(m_syzLeads);
1130#ifndef NDEBUG
1131    if( __DEBUG__ )
1132    {
1133      const ring& r = m_rBaseRing;
1134      PrintS("SchreyerSyzygyComputation::ComputeLeadingSyzygyTerms: \n");
1135      PrintS("m_syzLeads: \n");
1136      dPrint(m_syzLeads, r, r, 1);
1137      PrintS("m_checker.Initialize(m_syzLeads) => \n");
1138      m_checker.DebugPrint();
1139    }
1140#endif
1141    assume( m_checker.IsNonempty() ); // TODO: this always fails... BUG????
1142  }
1143}
1144
1145#define NOPRODUCT 1
1146
1147poly SchreyerSyzygyComputation::SchreyerSyzygyNF(const poly syz_lead, poly syz_2) const
1148{
1149
1150  assume( !__IGNORETAILS__ );
1151
1152  const ideal& L = m_idLeads;
1153  const ideal& T = m_idTails;
1154  const ring& r = m_rBaseRing;
1155
1156  assume( syz_lead != NULL );
1157
1158  if( __TREEOUTPUT__ )
1159  {
1160//     PrintS("%%%% BEGIN LIFTHYBRID DIAGRAMM\n");
1161    PrintS("{   \"nodelabel\": \""); writeLatexTerm(syz_lead, r); PrintS("\", \"children\": [");
1162  }
1163
1164  if( syz_2 == NULL )
1165  {
1166    const int rr = p_GetComp(syz_lead, r) - 1;
1167
1168    assume( rr >= 0 && rr < IDELEMS(T) );
1169    assume( rr >= 0 && rr < IDELEMS(L) );
1170
1171#if NOPRODUCT
1172    syz_2 = m_div.FindReducer(syz_lead, L->m[rr], syz_lead, m_checker);
1173
1174    if( __TREEOUTPUT__ )
1175    {
1176      PrintS("{ \"nodelabel\": \""); writeLatexTerm(syz_2, r); PrintS("\" },");
1177    }
1178#else
1179    poly aa = leadmonom(syz_lead, r); assume( aa != NULL); // :(
1180    aa = p_Mult_mm(aa, L->m[rr], r);
1181
1182    if( __TREEOUTPUT__ )
1183    {
1184      PrintS("{ \"nodelabel\": \""); writeLatexTerm(syz_2, r); PrintS("\", \"edgelable\": \""); writeLatexTerm(aa, r, false); PrintS("\" },");
1185    }
1186
1187    syz_2 = m_div.FindReducer(aa, syz_lead, m_checker);
1188
1189    p_Delete(&aa, r);
1190#endif
1191
1192  }
1193
1194  assume( syz_2 != NULL ); // by construction of S-Polynomial
1195
1196  assume( L != NULL );
1197  assume( T != NULL );
1198
1199  assume( IDELEMS(L) == IDELEMS(T) );
1200
1201  int  c = p_GetComp(syz_lead, r) - 1;
1202
1203  assume( c >= 0 && c < IDELEMS(T) );
1204
1205  if( m_sum_bucket == NULL )
1206    m_sum_bucket = sBucketCreate(r);
1207
1208  if( m_spoly_bucket == NULL )
1209    m_spoly_bucket = kBucketCreate(r);
1210
1211  sBucket_pt& tail   = m_sum_bucket; assume( tail != NULL );
1212  kBucket_pt& bucket = m_spoly_bucket; assume( bucket != NULL ); kbTest(bucket);
1213
1214
1215//  kBucketInit(bucket, NULL, 0); // not needed!?
1216
1217  poly p = leadmonom(syz_lead, r); // :(
1218//  poly spoly = pp_Mult_qq(p, T->m[c], r);
1219  kBucket_Plus_mm_Mult_pp(bucket, p, T->m[c], 0); // TODO: store pLength(T->m[c]) separately!?
1220  p_Delete(&p, r);
1221
1222  kbTest(bucket);
1223
1224  c = p_GetComp(syz_2, r) - 1;
1225  assume( c >= 0 && c < IDELEMS(T) );
1226
1227  p = leadmonom(syz_2, r); // :(
1228//  spoly = p_Add_q(spoly, pp_Mult_qq(p, T->m[c], r), r);
1229  kBucket_Plus_mm_Mult_pp(bucket, p, T->m[c], 0); // pLength(T->m[c])?!
1230  kbTest(bucket);
1231  p_Delete(&p, r);
1232
1233  // TODO: use bucket!?
1234//  const bool bUsePolynomial = TEST_OPT_NOT_BUCKETS; //  || (pLength(spoly) < MIN_LENGTH_BUCKET);
1235//  CPolynomialSummator tail(r, bUsePolynomial);
1236  sBucket_Add_p(tail, syz_2, 1); // tail.AddAndDelete(syz_2, 1);
1237
1238  kbTest(bucket);
1239  for( poly spoly = kBucketExtractLm(bucket); spoly != NULL; p_LmDelete(&spoly, r), spoly = kBucketExtractLm(bucket))
1240  {
1241    kbTest(bucket);
1242    poly t = m_div.FindReducer(spoly, NULL, m_checker);
1243
1244    if( t != NULL )
1245    {
1246      p = leadmonom(t, r); // :(
1247      c = p_GetComp(t, r) - 1;
1248
1249      assume( c >= 0 && c < IDELEMS(T) );
1250
1251      if( __TREEOUTPUT__ )
1252      {
1253        PrintS("{ \"nodelabel\": \""); writeLatexTerm(t, r); PrintS("\", \"edgelable\": \""); writeLatexTerm(spoly, r, false); PrintS("\" },");
1254      }
1255
1256      kBucket_Plus_mm_Mult_pp(bucket, p, T->m[c], 0); // pLength(T->m[c])?
1257//      spoly = p_Add_q(spoly, pp_Mult_qq(p, T->m[c], r), r);
1258
1259      p_Delete(&p, r);
1260
1261      sBucket_Add_p(tail, t, 1); // tail.AddAndDelete(t, 1);
1262    } // otherwise discard that leading term altogether!
1263    kbTest(bucket);
1264  }
1265
1266  // now bucket must be empty!
1267  kbTest(bucket);
1268  assume( kBucketClear(bucket) == NULL );
1269
1270  poly result; int len;
1271  sBucketClearAdd(tail, &result, &len); // TODO: use Merge with sBucket???
1272  assume( pLength(result) == len );
1273
1274  if( __TREEOUTPUT__ )
1275  {
1276    PrintS("]},");
1277  }
1278
1279
1280  return result;
1281}
1282
1283// namespace     {
1284
1285// };
1286
1287bool my_p_LmCmp (poly a, poly b, const ring r) { return p_LmCmp(a, b, r) == -1; } // TODO: change to simple lex. memory compare!
1288
1289// NOTE: need p_Copy?????? for image + multiplier!!???
1290// NOTE: better store complete syz. terms!!?
1291poly SchreyerSyzygyComputation::TraverseTail(poly multiplier, const int tail) const
1292{
1293  const ring& r = m_rBaseRing;
1294
1295  assume(m_idTails !=  NULL && m_idTails->m != NULL);
1296  assume( tail >= 0 && tail < IDELEMS(m_idTails) );
1297
1298/*  return ComputeImage(multiplier, tail); */
1299
1300  // TODO: store (multiplier, tail) -.-^-.-^-.--> !
1301  TCache::iterator top_itr = m_cache.find(tail);
1302
1303  if ( top_itr != m_cache.end() )
1304  {
1305     assume( top_itr->first == tail );
1306
1307     TP2PCache& T = top_itr->second;
1308
1309     TP2PCache::iterator itr = T.find(multiplier);
1310
1311     if( itr != T.end() ) // Yey - Reuse!!!
1312     {
1313       assume( p_LmEqual(itr->first, multiplier, r) );
1314
1315       if( itr->second == NULL )
1316         return (NULL);
1317
1318       poly p = p_Copy(itr->second, r); // no copy???
1319
1320       if( __TREEOUTPUT__ )
1321       {
1322//         PrintS("{ \"nodelabel\": \""); writeLatexTerm(multiplier, r, false);
1323//         Print(" \\\\cdot \\\\GEN{%d}\", \"children\": [ ", tail + 1);
1324          Print("{ \"lookedupnode\": \"1\", \"nodelabel\": \"");
1325          writeLatexTerm(p, r, true, false);
1326       }
1327
1328       if( !n_Equal( pGetCoeff(multiplier), pGetCoeff(itr->first), r) ) // normalize coeffs!?
1329       {
1330         number n = n_Div( pGetCoeff(multiplier), pGetCoeff(itr->first), r);
1331         p = p_Mult_nn(p, n, r);
1332         n_Delete(&n, r);
1333
1334         if( __TREEOUTPUT__ )
1335           Print("\", \"RESCALEDRESULT\": \"1\" },");
1336       } else
1337       {
1338         if( __TREEOUTPUT__ )
1339           Print("\", \"RESCALEDRESULT\": \"0\" },");
1340       }
1341
1342       return p;
1343     }
1344
1345     if( __TREEOUTPUT__ )
1346     {
1347//        PrintS("{ \"nodelabel\": \""); writeLatexTerm(multiplier, r, false); Print(" \\\\cdot \\\\GEN{%d}\", \"children\": [", tail + 1);
1348     }
1349
1350     const poly p = ComputeImage(multiplier, tail);
1351     T.insert( TP2PCache::value_type(p_Copy(multiplier, r), p) ); //     T[ multiplier ] = p;
1352
1353//     if( p == NULL )
1354//        return (NULL);
1355
1356     if( __TREEOUTPUT__ )
1357     {
1358//        PrintS("], \"storedResult\": \""); writeLatexTerm(p, r, true, false); PrintS("\" },");
1359     }
1360
1361     return p_Copy(p, r);
1362  }
1363
1364  CCacheCompare o(r); TP2PCache T(o);
1365
1366  if( __TREEOUTPUT__ )
1367  {
1368//     PrintS("{ \"nodelabel\": \""); writeLatexTerm(multiplier, r, false); Print(" \\\\cdot \\\\GEN{%d}\", \"children\": [", tail + 1);
1369  }
1370
1371
1372  const poly p = ComputeImage(multiplier, tail);
1373
1374  T.insert( TP2PCache::value_type(p_Copy(multiplier, r), p) );
1375
1376  m_cache.insert( TCache::value_type(tail, T) );
1377
1378//  if( p == NULL )
1379//    return (NULL);
1380
1381  if( __TREEOUTPUT__ )
1382  {
1383//     PrintS("], \"storedResult\": \""); writeLatexTerm(p, r, true, false); PrintS("\" },");
1384  }
1385
1386  return p_Copy(p, r);
1387}
1388
1389poly SchreyerSyzygyComputation::ComputeImage(poly multiplier, const int tail) const
1390{
1391  const poly t = m_idTails->m[tail]; // !!!
1392
1393  if(t != NULL)
1394    return TraverseTail(multiplier, t);
1395
1396  return NULL;
1397}
1398
1399
1400poly SchreyerSyzygyComputation::TraverseTail(poly multiplier, poly tail) const
1401{
1402  assume( !__IGNORETAILS__ );
1403
1404  const ideal& L = m_idLeads;
1405  const ideal& T = m_idTails;
1406  const ring& r = m_rBaseRing;
1407
1408  assume( multiplier != NULL );
1409
1410  assume( L != NULL );
1411  assume( T != NULL );
1412
1413
1414  if( (!__TAILREDSYZ__) || m_lcm.Check(multiplier) )
1415  {
1416//    const bool bUsePolynomial = TEST_OPT_NOT_BUCKETS; //  || (pLength(tail) < MIN_LENGTH_BUCKET);
1417    if( m_sum_bucket == NULL )
1418      m_sum_bucket = sBucketCreate(r);
1419
1420    sBucket_pt& sum   = m_sum_bucket; assume( sum != NULL );
1421    poly s; int len;
1422
1423//    CPolynomialSummator sum(r, bUsePolynomial);
1424//    poly s = NULL;
1425    for(poly p = tail; p != NULL; p = pNext(p))   // iterate over the tail
1426    {
1427      // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1428      // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1429      // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1430      const poly rt = ReduceTerm(multiplier, p, NULL); // TODO: also return/store length?
1431      // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1432      // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1433      // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1434
1435      const int lp = pLength(rt);
1436      if( rt != NULL && lp != 0 )
1437        sBucket_Add_p(sum, rt, lp);
1438    }
1439
1440    sBucketClearAdd(sum, &s, &len);
1441    assume( pLength(s) == len );
1442    return s;
1443  }
1444
1445  return NULL;
1446
1447}
1448
1449
1450
1451
1452poly SchreyerSyzygyComputation::ReduceTerm(poly multiplier, poly term4reduction, poly syztermCheck) const
1453{
1454  assume( !__IGNORETAILS__ );
1455
1456  const ideal& L = m_idLeads;
1457  const ideal& T = m_idTails;
1458  const ring& r = m_rBaseRing;
1459
1460  assume( multiplier != NULL );
1461  assume( term4reduction != NULL );
1462
1463
1464  assume( L != NULL );
1465  assume( T != NULL );
1466
1467  // simple implementation with FindReducer:
1468  poly s = NULL;
1469
1470  if( (!__TAILREDSYZ__) || m_lcm.Check(multiplier) )
1471  {
1472#if NOPRODUCT
1473    s = m_div.FindReducer(multiplier, term4reduction, syztermCheck, m_checker);
1474
1475    if( s == NULL ) // No Reducer?
1476     return s;
1477
1478    if( __TREEOUTPUT__ )
1479    {
1480      PrintS("{ \"nodelabel\": \""); writeLatexTerm(s, r);
1481    }
1482
1483#else
1484    // NOTE: only LT(term4reduction) should be used in the following:
1485    poly product = pp_Mult_mm(multiplier, term4reduction, r);
1486    s = m_div.FindReducer(product, syztermCheck, m_checker);
1487
1488    if( s == NULL ) // No Reducer?
1489     return s;
1490
1491    if( __TREEOUTPUT__ )
1492    {
1493      PrintS("{ \"nodelabel\": \""); writeLatexTerm(s, r); PrintS("\", \"edgelable\": \""); writeLatexTerm(product, r, false);
1494    }
1495
1496    p_Delete(&product, r);
1497#endif
1498  }
1499
1500  if( s == NULL ) // No Reducer?
1501    return s;
1502
1503
1504  poly b = leadmonom(s, r);
1505
1506  const int c = p_GetComp(s, r) - 1;
1507  assume( c >= 0 && c < IDELEMS(T) );
1508
1509
1510  if( __TREEOUTPUT__ )
1511     PrintS("\", \"children\": [");
1512
1513  const poly t = TraverseTail(b, c); // T->m[c];
1514
1515  if( t != NULL )
1516    s = p_Add_q(s, t, r);
1517
1518  if( __TREEOUTPUT__ )
1519  {
1520
1521    PrintS("], \"noderesult\": \"");
1522    writeLatexTerm(s, r, true, false);
1523    PrintS("\" },");
1524  }
1525
1526  return s;
1527}
1528
1529
1530
1531
1532
1533BEGIN_NAMESPACE_NONAME
1534
1535static inline int atGetInt(idhdl rootRingHdl, const char* attribute, long def)
1536{
1537  return ((int)(long)(atGet(rootRingHdl, attribute, INT_CMD, (void*)def)));
1538}
1539
1540END_NAMESPACE
1541
1542
1543SchreyerSyzygyComputationFlags::SchreyerSyzygyComputationFlags(idhdl rootRingHdl):
1544#ifndef NDEBUG
1545     __DEBUG__( atGetInt(rootRingHdl,"DEBUG", 0) ),
1546#else
1547    __DEBUG__( atGetInt(rootRingHdl,"DEBUG", 0) ),
1548#endif
1549//    __SYZCHECK__( (BOOLEAN)atGetInt(rootRingHdl, "SYZCHECK", __DEBUG__) ),
1550    __LEAD2SYZ__( atGetInt(rootRingHdl, "LEAD2SYZ", 1) ),
1551    __TAILREDSYZ__( atGetInt(rootRingHdl, "TAILREDSYZ", 1) ),
1552    __HYBRIDNF__( atGetInt(rootRingHdl, "HYBRIDNF", 2) ),
1553    __IGNORETAILS__( atGetInt(rootRingHdl, "IGNORETAILS", 0) ),
1554    __SYZNUMBER__( atGetInt(rootRingHdl, "SYZNUMBER", 0) ),
1555    __TREEOUTPUT__( atGetInt(rootRingHdl, "TREEOUTPUT", 0) ),
1556    m_rBaseRing( rootRingHdl->data.uring )
1557{
1558#ifndef NDEBUG
1559  if( __DEBUG__ )
1560  {
1561    PrintS("SchreyerSyzygyComputationFlags: \n");
1562    Print("        DEBUG: \t%d\n", __DEBUG__);
1563//    Print("   SYZCHECK  : \t%d\n", __SYZCHECK__);
1564    Print("     LEAD2SYZ: \t%d\n", __LEAD2SYZ__);
1565    Print("   TAILREDSYZ: \t%d\n", __TAILREDSYZ__);
1566    Print("  IGNORETAILS: \t%d\n", __IGNORETAILS__);
1567    Print("   TREEOUTPUT: \t%d\n", __TREEOUTPUT__);
1568
1569  }
1570#endif
1571
1572  // TODO: just current setting!
1573  assume( rootRingHdl == currRingHdl );
1574  assume( rootRingHdl->typ == RING_CMD );
1575  assume( m_rBaseRing == currRing );
1576  // move the global ring here inside???
1577}
1578
1579
1580
1581CLeadingTerm::CLeadingTerm(unsigned int _label,  const poly _lt, const ring R):
1582    m_sev( p_GetShortExpVector(_lt, R) ),  m_label( _label ),  m_lt( _lt )
1583{ }
1584
1585
1586CReducerFinder::~CReducerFinder()
1587{
1588  for( CReducersHash::const_iterator it = m_hash.begin(); it != m_hash.end(); it++ )
1589  {
1590    const TReducers& v = it->second;
1591    for(TReducers::const_iterator vit = v.begin(); vit != v.end(); vit++ )
1592      delete const_cast<CLeadingTerm*>(*vit);
1593  }
1594}
1595
1596
1597void CReducerFinder::Initialize(const ideal L)
1598{
1599  assume( m_L == NULL || m_L == L );
1600  if( m_L == NULL )
1601    m_L = L;
1602
1603  assume( m_L == L );
1604
1605  if( L != NULL )
1606  {
1607    const ring& R = m_rBaseRing;
1608    assume( R != NULL );
1609
1610    for( int k = IDELEMS(L) - 1; k >= 0; k-- )
1611    {
1612      const poly a = L->m[k]; // assume( a != NULL );
1613
1614      // NOTE: label is k \in 0 ... |L|-1!!!
1615      if( a != NULL )
1616        m_hash[p_GetComp(a, R)].push_back( new CLeadingTerm(k, a, R) );
1617    }
1618  }
1619}
1620
1621CReducerFinder::CReducerFinder(const ideal L, const SchreyerSyzygyComputationFlags& flags):
1622    SchreyerSyzygyComputationFlags(flags),
1623    m_L(const_cast<ideal>(L)), // for debug anyway
1624    m_hash()
1625{
1626  assume( flags.m_rBaseRing == m_rBaseRing );
1627  if( L != NULL )
1628    Initialize(L);
1629}
1630
1631/// _p_LmDivisibleByNoComp for a | b*c
1632static inline BOOLEAN _p_LmDivisibleByNoComp(const poly a, const poly b, const poly c, const ring r)
1633{
1634  int i=r->VarL_Size - 1;
1635  unsigned long divmask = r->divmask;
1636  unsigned long la, lb;
1637
1638  if (r->VarL_LowIndex >= 0)
1639  {
1640    i += r->VarL_LowIndex;
1641    do
1642    {
1643      la = a->exp[i];
1644      lb = b->exp[i] + c->exp[i];
1645      if ((la > lb) ||
1646          (((la & divmask) ^ (lb & divmask)) != ((lb - la) & divmask)))
1647      {
1648        pDivAssume(p_DebugLmDivisibleByNoComp(a, b, r) == FALSE);
1649        return FALSE;
1650      }
1651      i--;
1652    }
1653    while (i>=r->VarL_LowIndex);
1654  }
1655  else
1656  {
1657    do
1658    {
1659      la = a->exp[r->VarL_Offset[i]];
1660      lb = b->exp[r->VarL_Offset[i]] + c->exp[r->VarL_Offset[i]];
1661      if ((la > lb) ||
1662          (((la & divmask) ^ (lb & divmask)) != ((lb - la) & divmask)))
1663      {
1664        pDivAssume(p_DebugLmDivisibleByNoComp(a, b, r) == FALSE);
1665        return FALSE;
1666      }
1667      i--;
1668    }
1669    while (i>=0);
1670  }
1671#ifdef HAVE_RINGS
1672  assume( !rField_is_Ring(r) ); // not implemented for rings...!
1673#endif
1674  return TRUE;
1675}
1676
1677bool CLeadingTerm::DivisibilityCheck(const poly product, const unsigned long not_sev, const ring r) const
1678{
1679  const poly p = m_lt;
1680
1681  assume( p_GetComp(p, r) == p_GetComp(product, r) );
1682
1683//  const int k = m_label;
1684//  assume( m_L->m[k] == p );
1685
1686  const unsigned long p_sev = m_sev;
1687
1688  assume( p_sev == p_GetShortExpVector(p, r) );
1689
1690  return p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r);
1691
1692}
1693
1694/// as DivisibilityCheck(multiplier * t, ...) for monomial 'm'
1695/// and a module term 't'
1696bool CLeadingTerm::DivisibilityCheck(const poly m, const poly t, const unsigned long not_sev, const ring r) const
1697{
1698  const poly p = m_lt;
1699
1700  assume( p_GetComp(p, r) == p_GetComp(t, r) );
1701// assume( p_GetComp(m, r) == 0 );
1702
1703//  const int k = m_label;
1704//  assume( m_L->m[k] == p );
1705
1706  const unsigned long p_sev = m_sev;
1707  assume( p_sev == p_GetShortExpVector(p, r) );
1708
1709  if (p_sev & not_sev)
1710    return false;
1711
1712  return _p_LmDivisibleByNoComp(p, m, t, r);
1713
1714//  return p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r);
1715
1716}
1717
1718
1719
1720/// TODO:
1721class CDivisorEnumerator: public SchreyerSyzygyComputationFlags
1722{
1723  private:
1724    const CReducerFinder& m_reds;
1725    const poly m_product;
1726    const unsigned long m_not_sev;
1727    const long m_comp;
1728
1729    CReducerFinder::CReducersHash::const_iterator m_itr;
1730    CReducerFinder::TReducers::const_iterator m_current, m_finish;
1731
1732    bool m_active;
1733
1734  public:
1735    CDivisorEnumerator(const CReducerFinder& self, const poly product):
1736        SchreyerSyzygyComputationFlags(self),
1737        m_reds(self),
1738        m_product(product),
1739        m_not_sev(~p_GetShortExpVector(product, m_rBaseRing)),
1740        m_comp(p_GetComp(product, m_rBaseRing)),
1741        m_itr(), m_current(), m_finish(),
1742        m_active(false)
1743    {
1744      assume( m_comp >= 0 );
1745      assume( m_reds.m_L != NULL );
1746    }
1747
1748    inline bool Reset()
1749    {
1750      m_active = false;
1751
1752      m_itr = m_reds.m_hash.find(m_comp);
1753
1754      if( m_itr == m_reds.m_hash.end() )
1755        return false;
1756
1757      assume( m_itr->first == m_comp );
1758
1759      m_current = (m_itr->second).begin();
1760      m_finish = (m_itr->second).end();
1761
1762      if (m_current == m_finish)
1763        return false;
1764
1765//      m_active = true;
1766      return true;
1767    }
1768
1769    const CLeadingTerm& Current() const
1770    {
1771      assume( m_active );
1772      assume( m_current != m_finish );
1773
1774      return *(*m_current);
1775    }
1776
1777    inline bool MoveNext()
1778    {
1779      assume( m_current != m_finish );
1780
1781      if( m_active )
1782        ++m_current;
1783      else
1784        m_active = true; // for Current()
1785
1786      // looking for the next good entry
1787      for( ; m_current != m_finish; ++m_current )
1788      {
1789        assume( m_reds.m_L->m[Current().m_label] == Current().m_lt );
1790
1791        if( Current().DivisibilityCheck(m_product, m_not_sev, m_rBaseRing) )
1792        {
1793#ifndef NDEBUG
1794          if( __DEBUG__ )
1795          {
1796            Print("CDivisorEnumerator::MoveNext::est LS: q is divisible by LS[%d] !:((, diviser is: ", 1 + Current().m_label);
1797            dPrint(Current().m_lt, m_rBaseRing, m_rBaseRing, 1);
1798          }
1799#endif
1800//          m_active = true;
1801          return true;
1802        }
1803      }
1804
1805      // the end... :(
1806      assume( m_current == m_finish );
1807
1808      m_active = false;
1809      return false;
1810    }
1811};
1812
1813
1814
1815bool CReducerFinder::IsDivisible(const poly product) const
1816{
1817  CDivisorEnumerator itr(*this, product);
1818  if( !itr.Reset() )
1819    return false;
1820
1821  return itr.MoveNext();
1822
1823/*
1824  const ring& r = m_rBaseRing;
1825
1826  const long comp = p_GetComp(product, r);
1827  const unsigned long not_sev = ~p_GetShortExpVector(product, r);
1828
1829  assume( comp >= 0 );
1830
1831  CReducersHash::const_iterator it = m_hash.find(comp); // same module component
1832
1833  assume( m_L != NULL );
1834
1835  if( it == m_hash.end() )
1836    return false;
1837  // assume comp!
1838
1839  const TReducers& reducers = it->second;
1840
1841  for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ )
1842  {
1843    assume( m_L->m[(*vit)->m_label] == (*vit)->m_lt );
1844
1845    if( (*vit)->DivisibilityCheck(product, not_sev, r) )
1846    {
1847      if( __DEBUG__ )
1848      {
1849        Print("_FindReducer::Test LS: q is divisible by LS[%d] !:((, diviser is: ", 1 + (*vit)->m_label);
1850        dPrint((*vit)->m_lt, r, r, 1);
1851      }
1852
1853      return true;
1854    }
1855  }
1856
1857  return false;
1858*/
1859}
1860
1861
1862#ifndef NDEBUG
1863void CReducerFinder::DebugPrint() const
1864{
1865  const ring& r = m_rBaseRing;
1866
1867  for( CReducersHash::const_iterator it = m_hash.begin(); it != m_hash.end(); it++)
1868  {
1869    Print("Hash Key: %ld, Values: \n", it->first);
1870    const TReducers& reducers = it->second;
1871
1872    for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ )
1873    {
1874      const poly p = (*vit)->m_lt;
1875
1876      assume( p_GetComp(p, r) == it->first );
1877
1878      const int k = (*vit)->m_label;
1879
1880      assume( m_L->m[k] == p );
1881
1882      const unsigned long p_sev = (*vit)->m_sev;
1883
1884      assume( p_sev == p_GetShortExpVector(p, r) );
1885
1886      Print("L[%d]: ", k); dPrint(p, r, r, 0); Print("SEV: %ld\n", p_sev);
1887    }
1888  }
1889}
1890#endif
1891
1892/// TODO:
1893class CDivisorEnumerator2: public SchreyerSyzygyComputationFlags
1894{
1895  private:
1896    const CReducerFinder& m_reds;
1897    const poly m_multiplier, m_term;
1898    const unsigned long m_not_sev;
1899    const long m_comp;
1900
1901    CReducerFinder::CReducersHash::const_iterator m_itr;
1902    CReducerFinder::TReducers::const_iterator m_current, m_finish;
1903
1904    bool m_active;
1905
1906  public:
1907    CDivisorEnumerator2(const CReducerFinder& self, const poly m, const poly t):
1908        SchreyerSyzygyComputationFlags(self),
1909        m_reds(self),
1910        m_multiplier(m), m_term(t),
1911        m_not_sev(~p_GetShortExpVector(m, t, m_rBaseRing)),
1912        m_comp(p_GetComp(t, m_rBaseRing)),
1913        m_itr(), m_current(), m_finish(),
1914        m_active(false)
1915    {
1916      assume( m_comp >= 0 );
1917      assume( m_reds.m_L != NULL );
1918      assume( m_multiplier != NULL );
1919      assume( m_term != NULL );
1920//      assume( p_GetComp(m_multiplier, m_rBaseRing) == 0 );
1921    }
1922
1923    inline bool Reset()
1924    {
1925      m_active = false;
1926
1927      m_itr = m_reds.m_hash.find(m_comp);
1928
1929      if( m_itr == m_reds.m_hash.end() )
1930        return false;
1931
1932      assume( m_itr->first == m_comp );
1933
1934      m_current = (m_itr->second).begin();
1935      m_finish = (m_itr->second).end();
1936
1937      if (m_current == m_finish)
1938        return false;
1939
1940      return true;
1941    }
1942
1943    const CLeadingTerm& Current() const
1944    {
1945      assume( m_active );
1946      assume( m_current != m_finish );
1947
1948      return *(*m_current);
1949    }
1950
1951    inline bool MoveNext()
1952    {
1953      assume( m_current != m_finish );
1954
1955      if( m_active )
1956        ++m_current;
1957      else
1958        m_active = true;
1959
1960
1961      // looking for the next good entry
1962      for( ; m_current != m_finish; ++m_current )
1963      {
1964        assume( m_reds.m_L->m[Current().m_label] == Current().m_lt );
1965
1966        if( Current().DivisibilityCheck(m_multiplier, m_term, m_not_sev, m_rBaseRing) )
1967        {
1968#ifndef NDEBUG
1969          if( __DEBUG__ )
1970          {
1971            Print("CDivisorEnumerator::MoveNext::est LS: q is divisible by LS[%d] !:((, diviser is: ", 1 + Current().m_label);
1972            dPrint(Current().m_lt, m_rBaseRing, m_rBaseRing, 1);
1973          }
1974#endif
1975//          m_active = true;
1976          return true;
1977
1978        }
1979      }
1980
1981      // the end... :(
1982      assume( m_current == m_finish );
1983
1984      m_active = false;
1985      return false;
1986    }
1987};
1988
1989poly CReducerFinder::FindReducer(const poly multiplier, const poly t,
1990                                 const poly syzterm,
1991                                 const CReducerFinder& syz_checker) const
1992{
1993  CDivisorEnumerator2 itr(*this, multiplier, t);
1994  if( !itr.Reset() )
1995    return NULL;
1996
1997  // don't care about the module component of multiplier (as it may be the syzygy term)
1998  // product = multiplier * t?
1999  const ring& r = m_rBaseRing;
2000
2001  assume( multiplier != NULL ); assume( t != NULL );
2002
2003  const ideal& L = m_L; assume( L != NULL ); // for debug/testing only!
2004
2005  long c = 0;
2006
2007  if (syzterm != NULL)
2008    c = p_GetComp(syzterm, r) - 1;
2009
2010  assume( c >= 0 && c < IDELEMS(L) );
2011
2012  if (__DEBUG__ && (syzterm != NULL))
2013  {
2014    const poly m = L->m[c];
2015
2016    assume( m != NULL ); assume( pNext(m) == NULL );
2017
2018    poly lm = p_Mult_mm(leadmonom(syzterm, r), m, r);
2019
2020    poly pr = p_Mult_q( leadmonom(multiplier, r, false), leadmonom(t, r, false), r);
2021
2022    assume( p_EqualPolys(lm, pr, r) );
2023
2024    //  def @@c = leadcomp(syzterm); int @@r = int(@@c);
2025    //  def @@product = leadmonomial(syzterm) * L[@@r];
2026
2027    p_Delete(&lm, r);
2028    p_Delete(&pr, r);
2029  }
2030
2031  const BOOLEAN to_check = (syz_checker.IsNonempty()); // __TAILREDSYZ__ &&
2032
2033  const poly q = p_New(r); pNext(q) = NULL;
2034
2035  if( __DEBUG__ )
2036    p_SetCoeff0(q, 0, r); // for printing q
2037
2038  while( itr.MoveNext() )
2039  {
2040    const poly p = itr.Current().m_lt;
2041    const int k  = itr.Current().m_label;
2042
2043    p_ExpVectorSum(q, multiplier, t, r); // q == product == multiplier * t // TODO: do it once?
2044    p_ExpVectorDiff(q, q, p, r); // (LM(product) / LM(L[k]))
2045
2046    p_SetComp(q, k + 1, r);
2047    p_Setm(q, r);
2048
2049    // cannot allow something like: a*gen(i) - a*gen(i)
2050    if (syzterm != NULL && (k == c))
2051      if (p_ExpVectorEqual(syzterm, q, r))
2052      {
2053#ifndef NDEBUG
2054        if( __DEBUG__ )
2055        {
2056          Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: ");
2057          dPrint(syzterm, r, r, 1);
2058        }
2059#endif
2060        continue;
2061      }
2062
2063    // while the complement (the fraction) is not reducible by leading syzygies
2064    if( to_check && syz_checker.IsDivisible(q) )
2065    {
2066#ifndef NDEBUG
2067      if( __DEBUG__ )
2068      {
2069        PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: ");
2070      }
2071#endif
2072      continue;
2073    }
2074
2075    number n = n_Mult( p_GetCoeff(multiplier, r), p_GetCoeff(t, r), r);
2076    p_SetCoeff0(q, n_InpNeg( n_Div(n, p_GetCoeff(p, r), r), r), r);
2077    n_Delete(&n, r);
2078
2079    return q;
2080  }
2081
2082/*
2083  const long comp = p_GetComp(t, r); assume( comp >= 0 );
2084  const unsigned long not_sev = ~p_GetShortExpVector(multiplier, t, r); // !
2085
2086//   for( int k = IDELEMS(L)-1; k>= 0; k-- )
2087//   {
2088//     const poly p = L->m[k];
2089//
2090//     if ( p_GetComp(p, r) != comp )
2091//       continue;
2092//
2093//     const unsigned long p_sev = p_GetShortExpVector(p, r); // to be stored in m_hash!!!
2094
2095   // looking for an appropriate diviser p = L[k]...
2096  CReducersHash::const_iterator it = m_hash.find(comp); // same module component
2097
2098  if( it == m_hash.end() )
2099    return NULL;
2100
2101  // assume comp!
2102
2103  assume( m_L != NULL );
2104
2105  const TReducers& reducers = it->second;
2106
2107  for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ )
2108  {
2109
2110    const poly p = (*vit)->m_lt;
2111    const int k = (*vit)->m_label;
2112
2113    assume( L->m[k] == p );
2114
2115//    const unsigned long p_sev = (*vit)->m_sev;
2116//    assume( p_sev == p_GetShortExpVector(p, r) );
2117
2118//    if( !p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r) )
2119//      continue;
2120
2121    if( !(*vit)->DivisibilityCheck(multiplier, t, not_sev, r) )
2122      continue;
2123
2124
2125//    if (p_sev & not_sev) continue;
2126//    if( !_p_LmDivisibleByNoComp(p, multiplier, t, r) ) continue;
2127
2128
2129    p_ExpVectorSum(q, multiplier, t, r); // q == product == multiplier * t
2130    p_ExpVectorDiff(q, q, p, r); // (LM(product) / LM(L[k]))
2131
2132    p_SetComp(q, k + 1, r);
2133    p_Setm(q, r);
2134
2135    // cannot allow something like: a*gen(i) - a*gen(i)
2136    if (syzterm != NULL && (k == c))
2137      if (p_ExpVectorEqual(syzterm, q, r))
2138      {
2139        if( __DEBUG__ )
2140        {
2141          Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: ");
2142          dPrint(syzterm, r, r, 1);
2143        }
2144
2145        continue;
2146      }
2147
2148    // while the complement (the fraction) is not reducible by leading syzygies
2149    if( to_check && syz_checker.IsDivisible(q) )
2150    {
2151      if( __DEBUG__ )
2152      {
2153        PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: ");
2154      }
2155
2156      continue;
2157    }
2158
2159    number n = n_Mult( p_GetCoeff(multiplier, r), p_GetCoeff(t, r), r);
2160    p_SetCoeff0(q, n_InpNeg( n_Div(n, p_GetCoeff(p, r), r), r), r);
2161    n_Delete(&n, r);
2162
2163    return q;
2164  }
2165*/
2166
2167  p_LmFree(q, r);
2168
2169  return NULL;
2170
2171}
2172
2173
2174poly CReducerFinder::FindReducer(const poly product, const poly syzterm, const CReducerFinder& syz_checker) const
2175{
2176  CDivisorEnumerator itr(*this, product);
2177  if( !itr.Reset() )
2178    return NULL;
2179
2180
2181  const ring& r = m_rBaseRing;
2182
2183  assume( product != NULL );
2184
2185  const ideal& L = m_L; assume( L != NULL ); // for debug/testing only!
2186
2187  long c = 0;
2188
2189  if (syzterm != NULL)
2190    c = p_GetComp(syzterm, r) - 1;
2191
2192  assume( c >= 0 && c < IDELEMS(L) );
2193
2194  if (__DEBUG__ && (syzterm != NULL))
2195  {
2196    const poly m = L->m[c];
2197
2198    assume( m != NULL ); assume( pNext(m) == NULL );
2199
2200    poly lm = p_Mult_mm(leadmonom(syzterm, r), m, r);
2201    assume( p_EqualPolys(lm, product, r) );
2202
2203    //  def @@c = leadcomp(syzterm); int @@r = int(@@c);
2204    //  def @@product = leadmonomial(syzterm) * L[@@r];
2205
2206    p_Delete(&lm, r);
2207  }
2208
2209
2210  const BOOLEAN to_check = (syz_checker.IsNonempty()); // __TAILREDSYZ__ &&
2211
2212  const poly q = p_New(r); pNext(q) = NULL;
2213
2214  if( __DEBUG__ )
2215    p_SetCoeff0(q, 0, r); // for printing q
2216
2217  while( itr.MoveNext() )
2218  {
2219    const poly p = itr.Current().m_lt;
2220    const int k  = itr.Current().m_label;
2221
2222    p_ExpVectorDiff(q, product, p, r); // (LM(product) / LM(L[k]))
2223    p_SetComp(q, k + 1, r);
2224    p_Setm(q, r);
2225
2226    // cannot allow something like: a*gen(i) - a*gen(i)
2227    if (syzterm != NULL && (k == c))
2228      if (p_ExpVectorEqual(syzterm, q, r))
2229      {
2230#ifndef NDEBUG
2231        if( __DEBUG__ )
2232        {
2233          Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: ");
2234          dPrint(syzterm, r, r, 1);
2235        }
2236#endif
2237        continue;
2238      }
2239
2240    // while the complement (the fraction) is not reducible by leading syzygies
2241    if( to_check && syz_checker.IsDivisible(q) )
2242    {
2243#ifndef NDEBUG
2244      if( __DEBUG__ )
2245      {
2246        PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: ");
2247      }
2248#endif
2249      continue;
2250    }
2251
2252    p_SetCoeff0(q, n_InpNeg( n_Div( p_GetCoeff(product, r), p_GetCoeff(p, r), r), r), r);
2253
2254    return q;
2255  }
2256
2257
2258
2259/*
2260  const long comp = p_GetComp(product, r);
2261  const unsigned long not_sev = ~p_GetShortExpVector(product, r);
2262
2263  assume( comp >= 0 );
2264
2265//   for( int k = IDELEMS(L)-1; k>= 0; k-- )
2266//   {
2267//     const poly p = L->m[k];
2268//
2269//     if ( p_GetComp(p, r) != comp )
2270//       continue;
2271//
2272//     const unsigned long p_sev = p_GetShortExpVector(p, r); // to be stored in m_hash!!!
2273
2274   // looking for an appropriate diviser p = L[k]...
2275  CReducersHash::const_iterator it = m_hash.find(comp); // same module component
2276
2277  if( it == m_hash.end() )
2278    return NULL;
2279
2280  assume( m_L != NULL );
2281
2282  const TReducers& reducers = it->second;
2283
2284  const BOOLEAN to_check = (syz_checker.IsNonempty()); // __TAILREDSYZ__ &&
2285
2286  const poly q = p_New(r); pNext(q) = NULL;
2287
2288  if( __DEBUG__ )
2289    p_SetCoeff0(q, 0, r); // for printing q
2290
2291  for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ )
2292  {
2293    const poly p = (*vit)->m_lt;
2294
2295    assume( p_GetComp(p, r) == comp );
2296
2297    const int k = (*vit)->m_label;
2298
2299    assume( L->m[k] == p );
2300
2301    const unsigned long p_sev = (*vit)->m_sev;
2302
2303    assume( p_sev == p_GetShortExpVector(p, r) );
2304
2305    if( !p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r) )
2306      continue;
2307
2308//     // ... which divides the product, looking for the _1st_ appropriate one!
2309//     if( !p_LmDivisibleByNoComp(p, product, r) ) // included inside  p_LmShortDivisibleBy!
2310//       continue;
2311
2312    p_ExpVectorDiff(q, product, p, r); // (LM(product) / LM(L[k]))
2313    p_SetComp(q, k + 1, r);
2314    p_Setm(q, r);
2315
2316    // cannot allow something like: a*gen(i) - a*gen(i)
2317    if (syzterm != NULL && (k == c))
2318      if (p_ExpVectorEqual(syzterm, q, r))
2319      {
2320        if( __DEBUG__ )
2321        {
2322          Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: ");
2323          dPrint(syzterm, r, r, 1);
2324        }
2325
2326        continue;
2327      }
2328
2329    // while the complement (the fraction) is not reducible by leading syzygies
2330    if( to_check && syz_checker.IsDivisible(q) )
2331    {
2332      if( __DEBUG__ )
2333      {
2334        PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: ");
2335      }
2336
2337      continue;
2338    }
2339
2340    p_SetCoeff0(q, n_InpNeg( n_Div( p_GetCoeff(product, r), p_GetCoeff(p, r), r), r), r);
2341    return q;
2342  }
2343*/
2344
2345  p_LmFree(q, r);
2346
2347  return NULL;
2348}
2349
2350
2351
2352CLCM::CLCM(const ideal& L, const SchreyerSyzygyComputationFlags& flags):
2353    SchreyerSyzygyComputationFlags(flags), std::vector<bool>(),
2354    m_compute(false), m_N(rVar(flags.m_rBaseRing))
2355{
2356  const ring& R = m_rBaseRing;
2357  assume( flags.m_rBaseRing == R );
2358  assume( R != NULL );
2359
2360  assume( L != NULL );
2361
2362  if( __TAILREDSYZ__ && !__HYBRIDNF__ && (L != NULL))
2363  {
2364    const int l = IDELEMS(L);
2365
2366    assume( l > 0 );
2367
2368    resize(l, false);
2369
2370    for( int k = l - 1; k >= 0; k-- )
2371    {
2372      const poly a = L->m[k]; assume( a != NULL );
2373
2374      for (unsigned int j = m_N; j > 0; j--)
2375        if ( !(*this)[j] )
2376          (*this)[j] = (p_GetExp(a, j, R) > 0);
2377    }
2378
2379    m_compute = true;
2380  }
2381}
2382
2383
2384bool CLCM::Check(const poly m) const
2385{
2386  assume( m != NULL );
2387  if( m_compute && (m != NULL))
2388  {
2389    const ring& R = m_rBaseRing;
2390
2391    assume( __TAILREDSYZ__ && !__HYBRIDNF__ );
2392
2393    for (unsigned int j = m_N; j > 0; j--)
2394      if ( (*this)[j] )
2395        if(p_GetExp(m, j, R) > 0)
2396          return true;
2397
2398    return false;
2399
2400  } else return true;
2401}
2402
2403CCacheCompare::CCacheCompare(): m_ring(currRing) {}
2404
2405
2406template class std::vector<bool>;
2407template class std::vector<CLeadingTerm const*>;
2408template class std::map< CReducerFinder::TComponentKey, CReducerFinder::TReducers >;
2409
2410template class std::map<TCacheKey, TCacheValue, struct CCacheCompare>;
2411template class std::map<int, TP2PCache>;
2412
2413
2414
2415END_NAMESPACE               END_NAMESPACE_SINGULARXX
2416
2417
2418// Vi-modeline: vim: filetype=c:syntax:shiftwidth=2:tabstop=8:textwidth=0:expandtab
Note: See TracBrowser for help on using the repository browser.