source: git/dyn_modules/syzextra/syzextra.cc @ 6bfd78

spielwiese
Last change on this file since 6bfd78 was 6bfd78, checked in by Oleksandr Motsak <motsak@…>, 11 years ago
Added CDivisorEnumerator(2) - to be used by CReducerFinder add: FindReducer + multiplier!
  • Property mode set to 100644
File size: 37.7 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
33#include <kernel/kstd1.h>
34#include <kernel/polys.h>
35#include <kernel/syz.h>
36#include <kernel/ideals.h>
37
38
39
40#include <Singular/tok.h>
41#include <Singular/ipid.h>
42#include <Singular/lists.h>
43#include <Singular/attrib.h>
44
45#include <Singular/ipid.h> 
46#include <Singular/ipshell.h> // For iiAddCproc
47
48#include <stdio.h>
49#include <stdlib.h>
50#include <string.h>
51
52// USING_NAMESPACE_SINGULARXX;
53USING_NAMESPACE( SINGULARXXNAME :: DEBUG )
54
55
56BEGIN_NAMESPACE_SINGULARXX     BEGIN_NAMESPACE(SYZEXTRA)
57
58
59BEGIN_NAMESPACE(SORT_c_ds)
60
61
62#ifdef _GNU_SOURCE
63static int cmp_c_ds(const void *p1, const void *p2, void *R)
64{
65#else
66static int cmp_c_ds(const void *p1, const void *p2)
67{
68  void *R = currRing; 
69#endif
70
71  const int YES = 1;
72  const int NO = -1;
73
74  const ring r =  (const ring) R; // TODO/NOTE: the structure is known: C, lp!!!
75
76  assume( r == currRing );
77
78  const poly a = *(const poly*)p1;
79  const poly b = *(const poly*)p2;
80
81  assume( a != NULL );
82  assume( b != NULL );
83
84  assume( p_LmTest(a, r) );
85  assume( p_LmTest(b, r) );
86
87
88  const signed long iCompDiff = p_GetComp(a, r) - p_GetComp(b, r);
89
90  // TODO: test this!!!!!!!!!!!!!!!!
91
92  //return -( compare (c, qsorts) )
93
94#ifndef NDEBUG
95  const int __DEBUG__ = 0;
96  if( __DEBUG__ )
97  {
98    PrintS("cmp_c_ds: a, b: \np1: "); dPrint(a, r, r, 2);
99    PrintS("b: "); dPrint(b, r, r, 2);
100    PrintLn();
101  }
102#endif
103
104
105  if( iCompDiff > 0 )
106    return YES;
107
108  if( iCompDiff < 0 )
109    return  NO;
110
111  assume( iCompDiff == 0 );
112
113  const signed long iDegDiff = p_Totaldegree(a, r) - p_Totaldegree(b, r);
114
115  if( iDegDiff > 0 )
116    return YES;
117
118  if( iDegDiff < 0 )
119    return  NO;
120
121  assume( iDegDiff == 0 );
122
123#ifndef NDEBUG
124  if( __DEBUG__ )
125  {
126    PrintS("cmp_c_ds: a & b have the same comp & deg! "); PrintLn();
127  }
128#endif
129
130  for (int v = rVar(r); v > 0; v--)
131  {
132    assume( v > 0 );
133    assume( v <= rVar(r) );
134
135    const signed int d = p_GetExp(a, v, r) - p_GetExp(b, v, r);
136
137    if( d > 0 )
138      return YES;
139
140    if( d < 0 )
141      return NO;
142
143    assume( d == 0 );
144  }
145
146  return 0; 
147}
148
149END_NAMESPACE
150/* namespace SORT_c_ds */
151
152/// return a new term: leading coeff * leading monomial of p
153/// with 0 leading component!
154poly leadmonom(const poly p, const ring r)
155{
156  poly m = NULL;
157
158  if( p != NULL )
159  {
160    assume( p != NULL );
161    assume( p_LmTest(p, r) );
162
163    m = p_LmInit(p, r);
164    p_SetCoeff0(m, n_Copy(p_GetCoeff(p, r), r), r);
165
166    p_SetComp(m, 0, r);
167    p_Setm(m, r);
168
169    assume( p_GetComp(m, r) == 0 );
170    assume( m != NULL );
171    assume( pNext(m) == NULL );
172    assume( p_LmTest(m, r) );
173  }
174
175  return m;
176}
177
178
179   
180poly p_Tail(const poly p, const ring r)
181{
182  if( p == NULL)
183    return NULL;
184  else
185    return p_Copy( pNext(p), r );
186}
187
188
189ideal id_Tail(const ideal id, const ring r)
190{
191  if( id == NULL)
192    return NULL;
193
194  const ideal newid = idInit(IDELEMS(id),id->rank);
195 
196  for (int i=IDELEMS(id) - 1; i >= 0; i--)
197    newid->m[i] = p_Tail( id->m[i], r );
198
199  newid->rank = id_RankFreeModule(newid, currRing);
200
201  return newid; 
202}
203
204
205
206void Sort_c_ds(const ideal id, const ring r)
207{
208  const int sizeNew = IDELEMS(id);
209
210#ifdef _GNU_SOURCE
211#define qsort_my(m, s, ss, r, cmp) qsort_r(m, s, ss, cmp, r)
212#else
213#define qsort_my(m, s, ss, r, cmp) qsort_r(m, s, ss, cmp)
214#endif
215 
216  if( sizeNew >= 2 )
217    qsort_my(id->m, sizeNew, sizeof(poly), r, FROM_NAMESPACE(SORT_c_ds, cmp_c_ds));
218
219#undef qsort_my
220
221  id->rank = id_RankFreeModule(id, r);
222}
223
224/// Clean up all the accumulated data
225void SchreyerSyzygyComputation::CleanUp()
226{
227  /*
228  for( TTailTerms::const_iterator it = m_idTailTerms.begin(); it != m_idTailTerms.end(); it++ )
229  {
230    const TTail& v = *it;
231    for(TTail::const_iterator vit = v.begin(); vit != v.end(); vit++ )
232      delete const_cast<CTailTerm*>(*vit);
233  }
234  */
235}
236
237
238
239void SchreyerSyzygyComputation::SetUpTailTerms(const ideal idTails)
240{
241  assume( idTails != NULL );
242  assume( idTails->m != NULL );
243/* 
244  m_idTailTerms.resize( IDELEMS(idTails) );
245 
246  for( unsigned int p = IDELEMS(idTails) - 1; p >= 0; p -- )
247  {
248    TTail& v = m_idTailTerms[p];
249    poly t = idTails->m[p];
250    v.resize( pLength(t) );
251
252    unsigned int pp = 0;
253   
254    while( t != NULL )
255    {
256      assume( t != NULL );
257      // TODO: compute L:t!
258//      ideal reducers;     
259//      CReducerFinder m_reducers
260     
261      CTailTerm* d = v[pp] = new CTailTerm();
262     
263      ++pp; pIter(t);
264    }
265  }
266*/
267}
268
269
270
271ideal SchreyerSyzygyComputation::Compute1LeadingSyzygyTerms()
272{
273  const ideal& id = m_idLeads;
274  const ring& r = m_rBaseRing;
275//  const SchreyerSyzygyComputationFlags& attributes = m_atttributes;
276
277//   const BOOLEAN __DEBUG__      = attributes.__DEBUG__;
278//   const BOOLEAN __SYZCHECK__   = attributes.__SYZCHECK__;
279//   const BOOLEAN __LEAD2SYZ__   = attributes.__LEAD2SYZ__;
280//   const BOOLEAN __HYBRIDNF__   = attributes.__HYBRIDNF__;
281//   const BOOLEAN __TAILREDSYZ__ = attributes.__TAILREDSYZ__;
282
283  assume(!__LEAD2SYZ__);
284
285  // 1. set of components S?
286  // 2. for each component c from S: set of indices of leading terms
287  // with this component?
288  // 3. short exp. vectors for each leading term?
289
290  const int size = IDELEMS(id);
291
292  if( size < 2 )
293  {
294    const ideal newid = idInit(1, 0); newid->m[0] = NULL; // zero ideal...       
295    return newid;
296  }
297
298  // TODO/NOTE: input is supposed to be (reverse-) sorted wrt "(c,ds)"!??
299
300  // components should come in groups: count elements in each group
301  // && estimate the real size!!!
302
303
304  // use just a vector instead???
305  const ideal newid = idInit( (size * (size-1))/2, size); // maximal size: ideal case!
306
307  int k = 0;
308
309  for (int j = 0; j < size; j++)
310  {
311    const poly p = id->m[j];
312    assume( p != NULL );
313    const int  c = p_GetComp(p, r);
314
315    for (int i = j - 1; i >= 0; i--)
316    {
317      const poly pp = id->m[i];
318      assume( pp != NULL );
319      const int  cc = p_GetComp(pp, r);
320
321      if( c != cc )
322        continue;
323
324      const poly m = p_Init(r); // p_New???
325
326      // m = LCM(p, pp) / p! // TODO: optimize: knowing the ring structure: (C/lp)!
327      for (int v = rVar(r); v > 0; v--)
328      {
329        assume( v > 0 );
330        assume( v <= rVar(r) );
331
332        const short e1 = p_GetExp(p , v, r);
333        const short e2 = p_GetExp(pp, v, r);
334
335        if( e1 >= e2 )
336          p_SetExp(m, v, 0, r);
337        else
338          p_SetExp(m, v, e2 - e1, r);
339
340      }
341
342      assume( (j > i) && (i >= 0) );
343
344      p_SetComp(m, j + 1, r);
345      pNext(m) = NULL;
346      p_SetCoeff0(m, n_Init(1, r->cf), r); // for later...
347
348      p_Setm(m, r); // should not do anything!!!
349
350      newid->m[k++] = m;
351    }
352  }
353
354//   if( __DEBUG__ && FALSE )
355//   {
356//     PrintS("ComputeLeadingSyzygyTerms::Temp0: \n");
357//     dPrint(newid, r, r, 1);
358//   }
359
360  // the rest of newid is assumed to be zeroes...
361
362  // simplify(newid, 2 + 32)??
363  // sort(newid, "C,ds")[1]???
364  id_DelDiv(newid, r); // #define SIMPL_LMDIV 32
365
366//   if( __DEBUG__ && FALSE )
367//   {
368//     PrintS("ComputeLeadingSyzygyTerms::Temp1: \n");
369//     dPrint(newid, r, r, 1);
370//   }
371
372  idSkipZeroes(newid); // #define SIMPL_NULL 2
373
374//   if( __DEBUG__ )
375//   {
376//     PrintS("ComputeLeadingSyzygyTerms::Output: \n");
377//     dPrint(newid, r, r, 1);
378//   }
379
380  Sort_c_ds(newid, r);
381
382  return newid;
383}
384
385ideal SchreyerSyzygyComputation::Compute2LeadingSyzygyTerms()
386{
387  const ideal& id = m_idLeads;
388  const ring& r = m_rBaseRing;
389//  const SchreyerSyzygyComputationFlags& attributes = m_atttributes;
390 
391//   const BOOLEAN __DEBUG__      = attributes.__DEBUG__;
392//   const BOOLEAN __SYZCHECK__   = attributes.__SYZCHECK__;
393//   const BOOLEAN __LEAD2SYZ__   = attributes.__LEAD2SYZ__;
394//   const BOOLEAN __HYBRIDNF__   = attributes.__HYBRIDNF__;
395//  const BOOLEAN __TAILREDSYZ__ = attributes.__TAILREDSYZ__;
396 
397
398  // 1. set of components S?
399  // 2. for each component c from S: set of indices of leading terms
400  // with this component?
401  // 3. short exp. vectors for each leading term?
402
403  const int size = IDELEMS(id);
404
405  if( size < 2 )
406  {
407    const ideal newid = idInit(1, 1); newid->m[0] = NULL; // zero module...   
408    return newid;
409  }
410
411
412  // TODO/NOTE: input is supposed to be sorted wrt "C,ds"!??
413 
414  // components should come in groups: count elements in each group
415  // && estimate the real size!!!
416
417
418  // use just a vector instead???
419  ideal newid = idInit( (size * (size-1))/2, size); // maximal size: ideal case!
420
421  int k = 0;
422
423  for (int j = 0; j < size; j++)
424  {
425    const poly p = id->m[j];
426    assume( p != NULL );
427    const int  c = p_GetComp(p, r);
428
429    for (int i = j - 1; i >= 0; i--)
430    {
431      const poly pp = id->m[i];
432      assume( pp != NULL );
433      const int  cc = p_GetComp(pp, r);
434
435      if( c != cc )
436        continue;
437
438        // allocate memory & zero it out!
439      const poly m = p_Init(r); const poly mm = p_Init(r);
440
441
442        // m = LCM(p, pp) / p! mm = LCM(p, pp) / pp!
443        // TODO: optimize: knowing the ring structure: (C/lp)!
444
445      for (int v = rVar(r); v > 0; v--)
446      {
447        assume( v > 0 );
448        assume( v <= rVar(r) );
449
450        const short e1 = p_GetExp(p , v, r);
451        const short e2 = p_GetExp(pp, v, r);
452
453        if( e1 >= e2 )
454          p_SetExp(mm, v, e1 - e2, r); //            p_SetExp(m, v, 0, r);
455        else
456          p_SetExp(m, v, e2 - e1, r); //            p_SetExp(mm, v, 0, r);
457
458      }
459
460      assume( (j > i) && (i >= 0) );
461
462      p_SetComp(m, j + 1, r);
463      p_SetComp(mm, i + 1, r);
464
465      const number& lc1 = p_GetCoeff(p , r);
466      const number& lc2 = p_GetCoeff(pp, r);
467
468      number g = n_Lcm( lc1, lc2, r );
469
470      p_SetCoeff0(m ,       n_Div(g, lc1, r), r);
471      p_SetCoeff0(mm, n_Neg(n_Div(g, lc2, r), r), r);
472
473      n_Delete(&g, r);
474
475      p_Setm(m, r); // should not do anything!!!
476      p_Setm(mm, r); // should not do anything!!!
477
478      pNext(m) = mm; //        pNext(mm) = NULL;
479
480      newid->m[k++] = m;
481    }
482  }
483
484//   if( __DEBUG__ && FALSE )
485//   {
486//     PrintS("Compute2LeadingSyzygyTerms::Temp0: \n");
487//     dPrint(newid, r, r, 1);
488//   }
489
490  if( !__TAILREDSYZ__ )
491  {
492      // simplify(newid, 2 + 32)??
493      // sort(newid, "C,ds")[1]???
494    id_DelDiv(newid, r); // #define SIMPL_LMDIV 32
495
496//     if( __DEBUG__ && FALSE )
497//     {
498//       PrintS("Compute2LeadingSyzygyTerms::Temp1 (deldiv): \n");
499//       dPrint(newid, r, r, 1);
500//     }
501  }
502  else
503  {
504      //      option(redSB); option(redTail);
505      //      TEST_OPT_REDSB
506      //      TEST_OPT_REDTAIL
507    assume( r == currRing );
508    BITSET _save_test = test;
509    test |= (Sy_bit(OPT_REDTAIL) | Sy_bit(OPT_REDSB));
510
511    intvec* w=new intvec(IDELEMS(newid));
512    ideal tmp = kStd(newid, currQuotient, isHomog, &w);
513    delete w;
514
515    test = _save_test;
516
517    id_Delete(&newid, r);
518    newid = tmp;
519
520//     if( __DEBUG__ && FALSE )
521//     {
522//       PrintS("Compute2LeadingSyzygyTerms::Temp1 (std): \n");
523//       dPrint(newid, r, r, 1);
524//     }
525
526  }
527
528  idSkipZeroes(newid);
529
530  Sort_c_ds(newid, r);
531 
532  return newid;
533}
534
535poly SchreyerSyzygyComputation::TraverseNF(const poly a, const poly a2) const
536{
537  const ideal& L = m_idLeads;
538  const ideal& T = m_idTails;
539
540  const ring& R = m_rBaseRing;
541
542  const int r = p_GetComp(a, R) - 1; 
543
544  assume( r >= 0 && r < IDELEMS(T) );
545  assume( r >= 0 && r < IDELEMS(L) );
546
547  poly aa = leadmonom(a, R); assume( aa != NULL); // :(
548  poly t = TraverseTail(aa, r);
549
550  if( a2 != NULL )
551  {
552    assume( __LEAD2SYZ__ );
553
554    const int r2 = p_GetComp(a2, R) - 1; poly aa2 = leadmonom(a2, R); // :(
555
556    assume( r2 >= 0 && r2 < IDELEMS(T) );
557
558    t = p_Add_q(a2, p_Add_q(t, TraverseTail(aa2, r2), R), R);
559
560    p_Delete(&aa2, R);
561  } else
562    t = p_Add_q(t, ReduceTerm(aa, L->m[r], a), R);
563
564  p_Delete(&aa, R);
565
566  return t;
567}
568
569
570
571void SchreyerSyzygyComputation::ComputeSyzygy()
572{
573  assume( m_idLeads != NULL );
574  assume( m_idTails != NULL );
575 
576  const ideal& L = m_idLeads;
577  const ideal& T = m_idTails;
578
579  ideal& TT = m_syzTails;
580  const ring& R = m_rBaseRing;
581
582  assume( IDELEMS(L) == IDELEMS(T) );
583
584  if( m_syzLeads == NULL )
585    ComputeLeadingSyzygyTerms( __LEAD2SYZ__ && !__IGNORETAILS__ ); // 2 terms OR 1 term!
586
587  assume( m_syzLeads != NULL );
588
589  ideal& LL = m_syzLeads;
590
591 
592  const int size = IDELEMS(LL);
593
594  TT = idInit(size, 0);
595
596  if( size == 1 && LL->m[0] == NULL )
597    return;
598
599
600  for( int k = size - 1; k >= 0; k-- )
601  {
602    const poly a = LL->m[k]; assume( a != NULL );
603
604    poly a2 = pNext(a);   
605
606    // Splitting 2-terms Leading syzygy module
607    if( a2 != NULL )
608      pNext(a) = NULL;
609
610    if( __IGNORETAILS__ )
611    {
612      TT->m[k] = NULL;
613
614      assume( a2 != NULL );
615
616      if( a2 != NULL )
617        p_Delete(&a2, R);
618
619      continue;
620    }
621   
622//    TT->m[k] = a2;
623
624    if( ! __HYBRIDNF__ )
625    {
626      TT->m[k] = TraverseNF(a, a2);
627    } else
628    {
629      TT->m[k] = SchreyerSyzygyNF(a, a2);
630    }
631
632  }
633
634  TT->rank = id_RankFreeModule(TT, R);
635}
636
637void SchreyerSyzygyComputation::ComputeLeadingSyzygyTerms(bool bComputeSecondTerms)
638{
639//  const SchreyerSyzygyComputationFlags& attributes = m_atttributes;
640
641//  const BOOLEAN __LEAD2SYZ__   = attributes.__LEAD2SYZ__;
642//  const BOOLEAN __TAILREDSYZ__ = attributes.__TAILREDSYZ__;
643
644  assume( m_syzLeads == NULL );
645
646  if( bComputeSecondTerms )
647  {
648    assume( __LEAD2SYZ__ );
649//    m_syzLeads = FROM_NAMESPACE(INTERNAL, _Compute2LeadingSyzygyTerms(m_idLeads, m_rBaseRing, m_atttributes));
650    m_syzLeads = Compute2LeadingSyzygyTerms();
651  }
652  else
653  {
654    assume( !__LEAD2SYZ__ );
655   
656    m_syzLeads = Compute1LeadingSyzygyTerms();
657  }
658//    m_syzLeads = FROM_NAMESPACE(INTERNAL, _ComputeLeadingSyzygyTerms(m_idLeads, m_rBaseRing, m_atttributes));
659 
660  // NOTE: set m_LS if tails are to be reduced!
661  assume( m_syzLeads!= NULL );
662
663  if (__TAILREDSYZ__ && !__IGNORETAILS__ && (IDELEMS(m_syzLeads) > 0) && !((IDELEMS(m_syzLeads) == 1) && (m_syzLeads->m[0] == NULL)))
664  {
665    m_LS = m_syzLeads;
666    m_checker.Initialize(m_syzLeads);
667#ifndef NDEBUG   
668    if( __DEBUG__ )
669    {
670      const ring& r = m_rBaseRing;
671      PrintS("SchreyerSyzygyComputation::ComputeLeadingSyzygyTerms: \n");
672      PrintS("m_syzLeads: \n");
673      dPrint(m_syzLeads, r, r, 1);
674      PrintS("m_checker.Initialize(m_syzLeads) => \n");
675      m_checker.DebugPrint();
676    }
677#endif
678    assume( m_checker.IsNonempty() ); // TODO: this always fails... BUG????
679  }
680}
681
682#define NOPRODUCT 1
683
684poly SchreyerSyzygyComputation::SchreyerSyzygyNF(const poly syz_lead, poly syz_2) const
685{
686 
687  assume( !__IGNORETAILS__ );
688
689  const ideal& L = m_idLeads;
690  const ideal& T = m_idTails;
691  const ring& r = m_rBaseRing;
692
693  assume( syz_lead != NULL );
694
695  if( syz_2 == NULL )
696  {
697    const int rr = p_GetComp(syz_lead, r) - 1; 
698
699    assume( rr >= 0 && rr < IDELEMS(T) );
700    assume( rr >= 0 && rr < IDELEMS(L) );
701
702
703#if NOPRODUCT
704    syz_2 = m_div.FindReducer(syz_lead, L->m[rr], syz_lead, m_checker);
705#else   
706    poly aa = leadmonom(syz_lead, r); assume( aa != NULL); // :(
707    aa = p_Mult_mm(aa, L->m[rr], r);
708
709    syz_2 = m_div.FindReducer(aa, syz_lead, m_checker);
710
711    p_Delete(&aa, r);
712#endif
713   
714    assume( syz_2 != NULL ); // by construction of S-Polynomial   
715  }
716
717
718 
719  assume( syz_2 != NULL );
720
721  assume( L != NULL );
722  assume( T != NULL );
723
724  assume( IDELEMS(L) == IDELEMS(T) );
725
726  int  c = p_GetComp(syz_lead, r) - 1;
727
728  assume( c >= 0 && c < IDELEMS(T) );
729
730  poly p = leadmonom(syz_lead, r); // :( 
731  poly spoly = pp_Mult_qq(p, T->m[c], r);
732  p_Delete(&p, r);
733
734
735  c = p_GetComp(syz_2, r) - 1;
736  assume( c >= 0 && c < IDELEMS(T) );
737
738  p = leadmonom(syz_2, r); // :(
739  spoly = p_Add_q(spoly, pp_Mult_qq(p, T->m[c], r), r);
740  p_Delete(&p, r);
741
742  poly tail = syz_2; // TODO: use bucket!?
743
744  while (spoly != NULL)
745  {
746    poly t = m_div.FindReducer(spoly, NULL, m_checker);
747
748    p_LmDelete(&spoly, r);
749
750    if( t != NULL )
751    {
752      p = leadmonom(t, r); // :(
753      c = p_GetComp(t, r) - 1;
754
755      assume( c >= 0 && c < IDELEMS(T) );
756
757      spoly = p_Add_q(spoly, pp_Mult_qq(p, T->m[c], r), r);
758
759      p_Delete(&p, r);
760
761      tail = p_Add_q(tail, t, r);
762    }   
763  }
764
765  return tail;
766}
767
768poly SchreyerSyzygyComputation::TraverseTail(poly multiplier, const int tail) const
769{
770  // TODO: store (multiplier, tail) -.-^-.-^-.--> !
771  assume(m_idTails !=  NULL && m_idTails->m != NULL);
772  assume( tail >= 0 && tail < IDELEMS(m_idTails) );
773
774  const poly t = m_idTails->m[tail];
775
776  if(t != NULL)
777    return TraverseTail(multiplier, t);
778
779  return NULL;
780}
781
782
783poly SchreyerSyzygyComputation::TraverseTail(poly multiplier, poly tail) const
784{
785  assume( !__IGNORETAILS__ );
786
787  const ideal& L = m_idLeads;
788  const ideal& T = m_idTails;
789  const ring& r = m_rBaseRing;
790
791  assume( multiplier != NULL );
792
793  assume( L != NULL );
794  assume( T != NULL );
795
796  poly s = NULL;
797
798  if( (!__TAILREDSYZ__) || m_lcm.Check(multiplier) )
799    for(poly p = tail; p != NULL; p = pNext(p))   // iterate over the tail
800      s = p_Add_q(s, ReduceTerm(multiplier, p, NULL), r); 
801
802  return s;
803}
804
805
806
807
808poly SchreyerSyzygyComputation::ReduceTerm(poly multiplier, poly term4reduction, poly syztermCheck) const
809{
810  assume( !__IGNORETAILS__ );
811
812  const ideal& L = m_idLeads;
813  const ideal& T = m_idTails;
814  const ring& r = m_rBaseRing;
815
816  assume( multiplier != NULL );
817  assume( term4reduction != NULL );
818
819
820  assume( L != NULL );
821  assume( T != NULL );
822
823  // simple implementation with FindReducer:
824  poly s = NULL;
825
826  if( (!__TAILREDSYZ__) || m_lcm.Check(multiplier) )
827  {
828#if NOPRODUCT
829    s = m_div.FindReducer(multiplier, term4reduction, syztermCheck, m_checker);
830#else   
831    // NOTE: only LT(term4reduction) should be used in the following:
832    poly product = pp_Mult_mm(multiplier, term4reduction, r);
833    s = m_div.FindReducer(product, syztermCheck, m_checker);
834    p_Delete(&product, r);
835#endif
836  }
837
838  if( s == NULL ) // No Reducer?
839    return s;
840
841  poly b = leadmonom(s, r);
842
843  const int c = p_GetComp(s, r) - 1;
844  assume( c >= 0 && c < IDELEMS(T) );
845
846  const poly t = TraverseTail(b, c); // T->m[c];
847
848  if( t != NULL )
849    s = p_Add_q(s, t, r); 
850
851  return s;
852}
853
854
855
856
857
858BEGIN_NAMESPACE_NONAME
859   
860static inline int atGetInt(idhdl rootRingHdl, const char* attribute, long def)
861{
862  return ((int)(long)(atGet(rootRingHdl, attribute, INT_CMD, (void*)def)));
863}
864
865END_NAMESPACE   
866
867SchreyerSyzygyComputationFlags::SchreyerSyzygyComputationFlags(idhdl rootRingHdl):
868#ifndef NDEBUG
869    __DEBUG__( (BOOLEAN)atGetInt(rootRingHdl,"DEBUG", TRUE) ),
870#else
871    __DEBUG__( (BOOLEAN)atGetInt(rootRingHdl,"DEBUG", FALSE) ),
872#endif
873//    __SYZCHECK__( (BOOLEAN)atGetInt(rootRingHdl, "SYZCHECK", __DEBUG__) ),
874    __LEAD2SYZ__( (BOOLEAN)atGetInt(rootRingHdl, "LEAD2SYZ", 1) ), 
875    __TAILREDSYZ__( (BOOLEAN)atGetInt(rootRingHdl, "TAILREDSYZ", 1) ), 
876    __HYBRIDNF__( (BOOLEAN)atGetInt(rootRingHdl, "HYBRIDNF", 0) ),
877    __IGNORETAILS__( (BOOLEAN)atGetInt(rootRingHdl, "IGNORETAILS", 0) ),
878    m_rBaseRing( rootRingHdl->data.uring )
879{   
880  if( __DEBUG__ )
881  {
882    PrintS("SchreyerSyzygyComputationFlags: \n");
883    Print("        DEBUG: \t%d\n", __DEBUG__);
884//    Print("   SYZCHECK  : \t%d\n", __SYZCHECK__);
885    Print("     LEAD2SYZ: \t%d\n", __LEAD2SYZ__);
886    Print("   TAILREDSYZ: \t%d\n", __TAILREDSYZ__);
887    Print("  IGNORETAILS: \t%d\n", __IGNORETAILS__);
888   
889  }
890
891  // TODO: just current setting!
892  assume( rootRingHdl == currRingHdl );
893  assume( rootRingHdl->typ == RING_CMD );
894  assume( m_rBaseRing == currRing );
895  // move the global ring here inside???
896}
897
898   
899
900CLeadingTerm::CLeadingTerm(unsigned int _label,  const poly _lt, const ring R):
901    m_sev( p_GetShortExpVector(_lt, R) ),  m_label( _label ),  m_lt( _lt )
902{ }
903
904
905CReducerFinder::~CReducerFinder()
906{
907  for( CReducersHash::const_iterator it = m_hash.begin(); it != m_hash.end(); it++ )
908  {
909    const TReducers& v = it->second;
910    for(TReducers::const_iterator vit = v.begin(); vit != v.end(); vit++ )
911      delete const_cast<CLeadingTerm*>(*vit);
912  }
913}
914
915
916void CReducerFinder::Initialize(const ideal L)
917{
918  assume( m_L == NULL || m_L == L );
919  if( m_L == NULL )
920    m_L = L;
921
922  assume( m_L == L );
923 
924  if( L != NULL )
925  {
926    const ring& R = m_rBaseRing;
927    assume( R != NULL );
928   
929    for( int k = IDELEMS(L) - 1; k >= 0; k-- )
930    {
931      const poly a = L->m[k]; // assume( a != NULL );
932
933      // NOTE: label is k \in 0 ... |L|-1!!!
934      if( a != NULL )
935        m_hash[p_GetComp(a, R)].push_back( new CLeadingTerm(k, a, R) );
936    }
937  }
938}
939
940CReducerFinder::CReducerFinder(const ideal L, const SchreyerSyzygyComputationFlags& flags):
941    SchreyerSyzygyComputationFlags(flags),
942    m_L(const_cast<ideal>(L)), // for debug anyway
943    m_hash()
944{
945  assume( flags.m_rBaseRing == m_rBaseRing );
946  if( L != NULL )
947    Initialize(L);
948}
949
950/// _p_LmDivisibleByNoComp for a | b*c
951static inline BOOLEAN _p_LmDivisibleByNoComp(const poly a, const poly b, const poly c, const ring r)
952{
953  int i=r->VarL_Size - 1;
954  unsigned long divmask = r->divmask;
955  unsigned long la, lb;
956
957  if (r->VarL_LowIndex >= 0)
958  {
959    i += r->VarL_LowIndex;
960    do
961    {
962      la = a->exp[i];
963      lb = b->exp[i] + c->exp[i];
964      if ((la > lb) ||
965          (((la & divmask) ^ (lb & divmask)) != ((lb - la) & divmask)))
966      {
967        pDivAssume(p_DebugLmDivisibleByNoComp(a, b, r) == FALSE);
968        return FALSE;
969      }
970      i--;
971    }
972    while (i>=r->VarL_LowIndex);
973  }
974  else
975  {
976    do
977    {
978      la = a->exp[r->VarL_Offset[i]];
979      lb = b->exp[r->VarL_Offset[i]] + c->exp[r->VarL_Offset[i]];
980      if ((la > lb) ||
981          (((la & divmask) ^ (lb & divmask)) != ((lb - la) & divmask)))
982      {
983        pDivAssume(p_DebugLmDivisibleByNoComp(a, b, r) == FALSE);
984        return FALSE;
985      }
986      i--;
987    }
988    while (i>=0);
989  }
990#ifdef HAVE_RINGS
991  assume( !rField_is_Ring(r) ); // not implemented for rings...!
992#endif
993  return TRUE;
994}
995
996bool CLeadingTerm::DivisibilityCheck(const poly product, const unsigned long not_sev, const ring r) const
997{
998  const poly p = m_lt;
999
1000  assume( p_GetComp(p, r) == p_GetComp(product, r) );
1001
1002  const int k = m_label;
1003
1004//  assume( m_L->m[k] == p );
1005
1006  const unsigned long p_sev = m_sev;
1007
1008  assume( p_sev == p_GetShortExpVector(p, r) );     
1009
1010  return p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r);
1011
1012}
1013
1014/// as DivisibilityCheck(multiplier * t, ...) for monomial 'm'
1015/// and a module term 't'
1016bool CLeadingTerm::DivisibilityCheck(const poly m, const poly t, const unsigned long not_sev, const ring r) const
1017{
1018  const poly p = m_lt;
1019
1020  assume( p_GetComp(p, r) == p_GetComp(t, r) );
1021// assume( p_GetComp(m, r) == 0 );
1022
1023//  const int k = m_label;
1024//  assume( m_L->m[k] == p );
1025
1026  const unsigned long p_sev = m_sev;
1027  assume( p_sev == p_GetShortExpVector(p, r) );     
1028
1029  if (p_sev & not_sev)
1030    return false;
1031
1032  return _p_LmDivisibleByNoComp(p, m, t, r);
1033
1034//  return p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r);
1035
1036}
1037
1038
1039
1040/// TODO:
1041class CDivisorEnumerator: public SchreyerSyzygyComputationFlags
1042{
1043  private: 
1044    const CReducerFinder& m_reds;
1045    const poly m_product;
1046    const unsigned long m_not_sev;
1047    const unsigned long m_comp;
1048
1049    CReducerFinder::CReducersHash::const_iterator m_itr;
1050    CReducerFinder::TReducers::const_iterator m_current, m_finish;
1051
1052    bool m_active;
1053
1054  public:
1055    CDivisorEnumerator(const CReducerFinder& self, const poly product):
1056        SchreyerSyzygyComputationFlags(self),
1057        m_reds(self),
1058        m_product(product),
1059        m_not_sev(~p_GetShortExpVector(product, m_rBaseRing)),
1060        m_comp(p_GetComp(product, m_rBaseRing)),
1061        m_itr(), m_current(), m_finish(),
1062        m_active(false)
1063    {
1064      assume( m_comp >= 0 );
1065      assume( m_reds.m_L != NULL ); 
1066    }
1067
1068    inline bool Reset()
1069    {
1070      m_active = false;
1071     
1072      m_itr = m_reds.m_hash.find(m_comp);
1073
1074      if( m_itr == m_reds.m_hash.end() )
1075        return false;
1076
1077      assume( m_itr->first == m_comp );
1078
1079      m_current = (m_itr->second).begin();
1080      m_finish = (m_itr->second).end();
1081
1082      if (m_current == m_finish)
1083        return false;
1084
1085//      m_active = true;
1086      return true;     
1087    }
1088
1089    const CLeadingTerm& Current() const
1090    {
1091      assume( m_active );
1092      assume( m_current != m_finish );
1093
1094      return *(*m_current);
1095    }
1096 
1097    inline bool MoveNext()
1098    {
1099      assume( m_current != m_finish );
1100
1101      if( m_active )
1102        ++m_current;
1103      else
1104        m_active = true; // for Current()
1105     
1106      // looking for the next good entry
1107      for( ; m_current != m_finish; ++m_current )
1108      {
1109        assume( m_reds.m_L->m[Current().m_label] == Current().m_lt );
1110
1111        if( Current().DivisibilityCheck(m_product, m_not_sev, m_rBaseRing) )
1112        {
1113          if( __DEBUG__ )
1114          {
1115            Print("CDivisorEnumerator::MoveNext::est LS: q is divisible by LS[%d] !:((, diviser is: ", 1 + Current().m_label);
1116            dPrint(Current().m_lt, m_rBaseRing, m_rBaseRing, 1);
1117          }
1118
1119//          m_active = true;
1120          return true;
1121        }
1122      }
1123
1124      // the end... :(
1125      assume( m_current == m_finish );
1126     
1127      m_active = false;
1128      return false;
1129    }
1130};
1131
1132
1133
1134bool CReducerFinder::IsDivisible(const poly product) const
1135{
1136  CDivisorEnumerator itr(*this, product);
1137  if( !itr.Reset() )
1138    return false;
1139
1140  return itr.MoveNext();
1141 
1142/* 
1143  const ring& r = m_rBaseRing;
1144 
1145  const long comp = p_GetComp(product, r);
1146  const unsigned long not_sev = ~p_GetShortExpVector(product, r);
1147
1148  assume( comp >= 0 );
1149
1150  CReducersHash::const_iterator it = m_hash.find(comp); // same module component
1151
1152  assume( m_L != NULL ); 
1153
1154  if( it == m_hash.end() )
1155    return false;
1156
1157  const TReducers& reducers = it->second;
1158
1159  for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ )
1160  {
1161    assume( m_L->m[(*vit)->m_label] == (*vit)->m_lt );
1162
1163    if( (*vit)->DivisibilityCheck(product, not_sev, r) )
1164    {
1165      if( __DEBUG__ )
1166      {
1167        Print("_FindReducer::Test LS: q is divisible by LS[%d] !:((, diviser is: ", 1 + (*vit)->m_label);
1168        dPrint((*vit)->m_lt, r, r, 1);
1169      }
1170
1171      return true;
1172    }
1173  }
1174
1175  return false;
1176*/ 
1177}
1178
1179
1180#ifndef NDEBUG
1181void CReducerFinder::DebugPrint() const
1182{
1183  const ring& r = m_rBaseRing;
1184
1185  for( CReducersHash::const_iterator it = m_hash.begin(); it != m_hash.end(); it++)
1186  {
1187    Print("Hash Key: %d, Values: \n", it->first);
1188    const TReducers& reducers = it->second;
1189
1190    for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ )
1191    {
1192      const poly p = (*vit)->m_lt;
1193
1194      assume( p_GetComp(p, r) == it->first );
1195
1196      const int k = (*vit)->m_label;
1197
1198      assume( m_L->m[k] == p );
1199
1200      const unsigned long p_sev = (*vit)->m_sev;
1201
1202      assume( p_sev == p_GetShortExpVector(p, r) );
1203
1204      Print("L[%d]: ", k); dPrint(p, r, r, 0); Print("SEV: %dl\n", p_sev);     
1205    }
1206  }
1207}
1208#endif
1209
1210/// TODO:
1211class CDivisorEnumerator2: public SchreyerSyzygyComputationFlags
1212{
1213  private: 
1214    const CReducerFinder& m_reds;
1215    const poly m_multiplier, m_term;
1216    const unsigned long m_not_sev;
1217    const unsigned long m_comp;
1218
1219    CReducerFinder::CReducersHash::const_iterator m_itr;
1220    CReducerFinder::TReducers::const_iterator m_current, m_finish;
1221
1222    bool m_active;
1223
1224  public:
1225    CDivisorEnumerator2(const CReducerFinder& self, const poly m, const poly t):
1226        SchreyerSyzygyComputationFlags(self),
1227        m_reds(self),
1228        m_multiplier(m), m_term(t),
1229        m_not_sev(~p_GetShortExpVector(m, t, m_rBaseRing)),
1230        m_comp(p_GetComp(t, m_rBaseRing)),
1231        m_itr(), m_current(), m_finish(),
1232        m_active(false)
1233    {
1234      assume( m_comp >= 0 );
1235      assume( m_reds.m_L != NULL ); 
1236      assume( m_multiplier != NULL ); 
1237      assume( m_term != NULL );
1238//      assume( p_GetComp(m_multiplier, m_rBaseRing) == 0 );
1239    }
1240
1241    inline bool Reset()
1242    {
1243      m_active = false;
1244     
1245      m_itr = m_reds.m_hash.find(m_comp);
1246
1247      if( m_itr == m_reds.m_hash.end() )
1248        return false;
1249
1250      assume( m_itr->first == m_comp );
1251
1252      m_current = (m_itr->second).begin();
1253      m_finish = (m_itr->second).end();
1254
1255      if (m_current == m_finish)
1256        return false;
1257
1258      return true;     
1259    }
1260
1261    const CLeadingTerm& Current() const
1262    {
1263      assume( m_active );
1264      assume( m_current != m_finish );
1265
1266      return *(*m_current);
1267    }
1268 
1269    inline bool MoveNext()
1270    {
1271      assume( m_current != m_finish );
1272
1273      if( m_active )
1274        ++m_current;
1275      else 
1276        m_active = true;
1277         
1278     
1279      // looking for the next good entry
1280      for( ; m_current != m_finish; ++m_current )
1281      {
1282        assume( m_reds.m_L->m[Current().m_label] == Current().m_lt );
1283
1284        if( Current().DivisibilityCheck(m_multiplier, m_term, m_not_sev, m_rBaseRing) )
1285        {
1286          if( __DEBUG__ )
1287          {
1288            Print("CDivisorEnumerator::MoveNext::est LS: q is divisible by LS[%d] !:((, diviser is: ", 1 + Current().m_label);
1289            dPrint(Current().m_lt, m_rBaseRing, m_rBaseRing, 1);
1290          }
1291
1292//          m_active = true;
1293          return true;
1294         
1295        }
1296      }
1297
1298      // the end... :(
1299      assume( m_current == m_finish );
1300     
1301      m_active = false;
1302      return false;
1303    }
1304};
1305   
1306poly CReducerFinder::FindReducer(const poly multiplier, const poly t,
1307                                 const poly syzterm,
1308                                 const CReducerFinder& syz_checker) const
1309{
1310  CDivisorEnumerator2 itr(*this, multiplier, t);
1311  if( !itr.Reset() )
1312    return NULL;
1313
1314  // don't care about the module component of multiplier (as it may be the syzygy term)
1315  // product = multiplier * t?
1316  const ring& r = m_rBaseRing;
1317
1318  assume( multiplier != NULL ); assume( t != NULL );
1319
1320  const ideal& L = m_L; assume( L != NULL ); // for debug/testing only!
1321
1322  long c = 0;
1323
1324  if (syzterm != NULL)
1325    c = p_GetComp(syzterm, r) - 1;
1326
1327  assume( c >= 0 && c < IDELEMS(L) );
1328
1329  if (__DEBUG__ && (syzterm != NULL))
1330  {
1331    const poly m = L->m[c];
1332
1333    assume( m != NULL ); assume( pNext(m) == NULL );
1334
1335    poly lm = p_Mult_mm(leadmonom(syzterm, r), m, r);
1336
1337    poly pr = p_Mult_q( p_LmInit(multiplier, r), p_LmInit(t, r), r);
1338   
1339    assume( p_EqualPolys(lm, pr, r) );
1340
1341    //  def @@c = leadcomp(syzterm); int @@r = int(@@c);
1342    //  def @@product = leadmonomial(syzterm) * L[@@r];
1343
1344    p_Delete(&lm, r);   
1345    p_Delete(&pr, r);   
1346  }
1347   
1348  const BOOLEAN to_check = (syz_checker.IsNonempty()); // __TAILREDSYZ__ &&
1349
1350  const poly q = p_New(r); pNext(q) = NULL;
1351
1352  if( __DEBUG__ )
1353    p_SetCoeff0(q, 0, r); // for printing q
1354
1355  while( itr.MoveNext() )
1356  {
1357    const poly p = itr.Current().m_lt;
1358    const int k  = itr.Current().m_label;
1359     
1360    p_ExpVectorSum(q, multiplier, t, r); // q == product == multiplier * t // TODO: do it once?
1361    p_ExpVectorDiff(q, q, p, r); // (LM(product) / LM(L[k]))
1362   
1363    p_SetComp(q, k + 1, r);
1364    p_Setm(q, r);
1365
1366    // cannot allow something like: a*gen(i) - a*gen(i)
1367    if (syzterm != NULL && (k == c))
1368      if (p_ExpVectorEqual(syzterm, q, r))
1369      {
1370        if( __DEBUG__ )
1371        {
1372          Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: ");
1373          dPrint(syzterm, r, r, 1);
1374        }   
1375
1376        continue;
1377      }
1378
1379    // while the complement (the fraction) is not reducible by leading syzygies
1380    if( to_check && syz_checker.IsDivisible(q) ) 
1381    {
1382      if( __DEBUG__ )
1383      {
1384        PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: ");
1385      }
1386
1387      continue;
1388    }
1389
1390    number n = n_Mult( p_GetCoeff(multiplier, r), p_GetCoeff(t, r), r);
1391    p_SetCoeff0(q, n_Neg( n_Div(n, p_GetCoeff(p, r), r), r), r);
1392    n_Delete(&n, r);
1393   
1394    return q;
1395  }
1396
1397  p_LmFree(q, r);
1398
1399  return NULL;
1400
1401   
1402 
1403   
1404   
1405#if 0
1406  const long comp = p_GetComp(t, r); assume( comp >= 0 );
1407  const unsigned long not_sev = ~p_GetShortExpVector(multiplier, t, r); // !
1408
1409//   for( int k = IDELEMS(L)-1; k>= 0; k-- )
1410//   {
1411//     const poly p = L->m[k];
1412//
1413//     if ( p_GetComp(p, r) != comp )
1414//       continue;
1415//
1416//     const unsigned long p_sev = p_GetShortExpVector(p, r); // to be stored in m_hash!!!
1417
1418   // looking for an appropriate diviser p = L[k]...
1419  CReducersHash::const_iterator it = m_hash.find(comp); // same module component
1420
1421  if( it == m_hash.end() )
1422    return NULL;
1423
1424  assume( m_L != NULL );
1425
1426  const TReducers& reducers = it->second;
1427
1428  for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ )
1429  {
1430
1431    const poly p = (*vit)->m_lt;
1432    const int k = (*vit)->m_label;
1433
1434    assume( L->m[k] == p );
1435
1436//    const unsigned long p_sev = (*vit)->m_sev;
1437//    assume( p_sev == p_GetShortExpVector(p, r) );     
1438
1439//    if( !p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r) )
1440//      continue;     
1441
1442    if( !(*vit)->DivisibilityCheck(multiplier, t, not_sev, r) )
1443      continue;
1444   
1445   
1446//    if (p_sev & not_sev) continue;
1447//    if( !_p_LmDivisibleByNoComp(p, multiplier, t, r) ) continue;     
1448
1449
1450    p_ExpVectorSum(q, multiplier, t, r); // q == product == multiplier * t       
1451    p_ExpVectorDiff(q, q, p, r); // (LM(product) / LM(L[k]))
1452   
1453    p_SetComp(q, k + 1, r);
1454    p_Setm(q, r);
1455
1456    // cannot allow something like: a*gen(i) - a*gen(i)
1457    if (syzterm != NULL && (k == c))
1458      if (p_ExpVectorEqual(syzterm, q, r))
1459      {
1460        if( __DEBUG__ )
1461        {
1462          Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: ");
1463          dPrint(syzterm, r, r, 1);
1464        }   
1465
1466        continue;
1467      }
1468
1469    // while the complement (the fraction) is not reducible by leading syzygies
1470    if( to_check && syz_checker.IsDivisible(q) )
1471    {
1472      if( __DEBUG__ )
1473      {
1474        PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: ");
1475      }
1476
1477      continue;
1478    }
1479
1480    number n = n_Mult( p_GetCoeff(multiplier, r), p_GetCoeff(t, r), r);
1481    p_SetCoeff0(q, n_Neg( n_Div(n, p_GetCoeff(p, r), r), r), r);
1482    n_Delete(&n, r);
1483   
1484    return q;
1485  }
1486
1487  p_LmFree(q, r);
1488
1489  return NULL;
1490#endif
1491}
1492
1493
1494poly CReducerFinder::FindReducer(const poly product, const poly syzterm, const CReducerFinder& syz_checker) const
1495{
1496  const ring& r = m_rBaseRing;
1497
1498  assume( product != NULL );
1499
1500  const ideal& L = m_L; assume( L != NULL ); // for debug/testing only!
1501
1502  long c = 0;
1503
1504  if (syzterm != NULL)
1505    c = p_GetComp(syzterm, r) - 1;
1506
1507  assume( c >= 0 && c < IDELEMS(L) );
1508
1509  if (__DEBUG__ && (syzterm != NULL))
1510  {
1511    const poly m = L->m[c];
1512
1513    assume( m != NULL ); assume( pNext(m) == NULL );
1514
1515    poly lm = p_Mult_mm(leadmonom(syzterm, r), m, r);
1516    assume( p_EqualPolys(lm, product, r) );
1517
1518    //  def @@c = leadcomp(syzterm); int @@r = int(@@c);
1519    //  def @@product = leadmonomial(syzterm) * L[@@r];
1520
1521    p_Delete(&lm, r);   
1522  }
1523
1524  const long comp = p_GetComp(product, r);
1525  const unsigned long not_sev = ~p_GetShortExpVector(product, r);
1526
1527  assume( comp >= 0 );
1528
1529//   for( int k = IDELEMS(L)-1; k>= 0; k-- )
1530//   {
1531//     const poly p = L->m[k];
1532//
1533//     if ( p_GetComp(p, r) != comp )
1534//       continue;
1535//
1536//     const unsigned long p_sev = p_GetShortExpVector(p, r); // to be stored in m_hash!!!
1537 
1538   // looking for an appropriate diviser p = L[k]...
1539  CReducersHash::const_iterator it = m_hash.find(comp); // same module component
1540
1541  if( it == m_hash.end() )
1542    return NULL;
1543
1544  assume( m_L != NULL );
1545
1546  const TReducers& reducers = it->second;
1547
1548  const BOOLEAN to_check = (syz_checker.IsNonempty()); // __TAILREDSYZ__ &&
1549
1550  const poly q = p_New(r); pNext(q) = NULL;
1551
1552  if( __DEBUG__ )
1553    p_SetCoeff0(q, 0, r); // for printing q
1554 
1555  for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ )
1556  {
1557    const poly p = (*vit)->m_lt;
1558
1559    assume( p_GetComp(p, r) == comp );
1560
1561    const int k = (*vit)->m_label;
1562
1563    assume( L->m[k] == p );
1564
1565    const unsigned long p_sev = (*vit)->m_sev;
1566
1567    assume( p_sev == p_GetShortExpVector(p, r) );     
1568
1569    if( !p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r) )
1570      continue;     
1571
1572//     // ... which divides the product, looking for the _1st_ appropriate one!
1573//     if( !p_LmDivisibleByNoComp(p, product, r) ) // included inside  p_LmShortDivisibleBy!
1574//       continue;
1575
1576    p_ExpVectorDiff(q, product, p, r); // (LM(product) / LM(L[k]))
1577    p_SetComp(q, k + 1, r);
1578    p_Setm(q, r);
1579
1580    // cannot allow something like: a*gen(i) - a*gen(i)
1581    if (syzterm != NULL && (k == c))
1582      if (p_ExpVectorEqual(syzterm, q, r))
1583      {
1584        if( __DEBUG__ )
1585        {
1586          Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: ");
1587          dPrint(syzterm, r, r, 1);
1588        }   
1589
1590        continue;
1591      }
1592
1593    // while the complement (the fraction) is not reducible by leading syzygies
1594    if( to_check && syz_checker.IsDivisible(q) ) 
1595    {
1596      if( __DEBUG__ )
1597      {
1598        PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: ");
1599      }
1600     
1601      continue;
1602    }
1603
1604    p_SetCoeff0(q, n_Neg( n_Div( p_GetCoeff(product, r), p_GetCoeff(p, r), r), r), r);
1605    return q;
1606  }
1607
1608  p_LmFree(q, r);
1609
1610  return NULL;
1611}
1612
1613
1614
1615CLCM::CLCM(const ideal& L, const SchreyerSyzygyComputationFlags& flags):
1616    SchreyerSyzygyComputationFlags(flags), std::vector<bool>(),
1617    m_compute(false), m_N(rVar(flags.m_rBaseRing))
1618{
1619  const ring& R = m_rBaseRing;
1620  assume( flags.m_rBaseRing == R );
1621  assume( R != NULL );
1622
1623  assume( L != NULL );
1624
1625  if( __TAILREDSYZ__ && !__HYBRIDNF__ && (L != NULL))
1626  {
1627    const int l = IDELEMS(L);
1628
1629    assume( l > 0 );
1630
1631    resize(l, false);
1632
1633    for( int k = l - 1; k >= 0; k-- )
1634    {
1635      const poly a = L->m[k]; assume( a != NULL );
1636
1637      for (unsigned int j = m_N; j > 0; j--)
1638        if ( !(*this)[j] )
1639          (*this)[j] = (p_GetExp(a, j, R) > 0);
1640    }
1641
1642    m_compute = true;   
1643  }
1644}
1645
1646
1647bool CLCM::Check(const poly m) const
1648{
1649  assume( m != NULL );
1650  if( m_compute && (m != NULL))
1651  { 
1652    const ring& R = m_rBaseRing;
1653
1654    assume( __TAILREDSYZ__ && !__HYBRIDNF__ );
1655
1656    for (unsigned int j = m_N; j > 0; j--)
1657      if ( (*this)[j] )
1658        if(p_GetExp(m, j, R) > 0)
1659          return true;
1660
1661    return false;
1662
1663  } else return true;
1664}
1665
1666
1667
1668
1669END_NAMESPACE               END_NAMESPACE_SINGULARXX
1670
1671
1672// Vi-modeline: vim: filetype=c:syntax:shiftwidth=2:tabstop=8:textwidth=0:expandtab
Note: See TracBrowser for help on using the repository browser.