1 // -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 /*****************************************************************************\
3  * Computer Algebra System SINGULAR
4 \*****************************************************************************/
5 /** @file PolyEnumerator.h
6  *
7  * Concrete implementation of enumerators over polynomials
8  *
9  * @author Oleksandr Motsak
10  *
11  *
12  **/
13 /*****************************************************************************/
14 
15 #ifndef POLYENUMERATOR_H
16 #define POLYENUMERATOR_H
17 
18 // include basic definitions
19 #include "coeffs/Enumerator.h"
20 #include "polys/monomials/monomials.h"
21 #include "reporter/reporter.h" // for assume etc.
22 
23 /** @class CBasePolyEnumerator
24  *
25  * Base polynomial enumerator for simple iteration over terms of polynomials.
26  *
27  * Note that the first element desn't exist directly after Reset() call.
28  *
29  * The class doesn't inherit from IAccessor and thus doesn't override Current().
30  *
31  * @sa IBaseEnumerator, @sa CPolyCoeffsEnumerator
32  */
33 class CBasePolyEnumerator: public virtual IBaseEnumerator
34 {
35   template <class T>
36   friend class CRecursivePolyCoeffsEnumerator;
37   private:
38     poly m_poly; ///< essentially immutable original iterable object
39 
40     static const spolyrec m_prevposition_struct; ///< tag for "-1" position
41 
42   protected:
43     poly m_position; ///< current position in the iterable object
44 
45   public:
IsValid()46     virtual bool IsValid() const
47     {
48       // not -1 or past the end position?
49       return (m_position != NULL) && (m_position != &m_prevposition_struct);
50     }
51 
52 
53     /// Reset this polynomial Enumerator with a different input polynomial
Reset(poly p)54     void Reset(poly p)
55     {
56       m_poly = p;
57       m_position = const_cast<poly>(&m_prevposition_struct);
58       assume( !IsValid() );
59     }
60 
61     /// This enumerator is an empty polynomial by default
62     CBasePolyEnumerator(poly p = NULL):
IBaseEnumerator()63         IBaseEnumerator(), m_poly(p), m_position(const_cast<poly>(&m_prevposition_struct))
64     {
65       assume( !IsValid() );
66     }
67 
68     /// Sets the position marker to the leading term.
Reset()69     virtual void Reset()
70     {
71       m_position = const_cast<poly>(&m_prevposition_struct);
72       assume( !IsValid() );
73     }
74 
75 
76     /// Advances the position to the next term of the polynomial.
77     /// returns true if the position marker was successfully advanced to the
78     /// next term which can be used;
79     /// false if the position marker has passed the end of the
80     /// polynomial.
MoveNext()81     virtual bool MoveNext()
82     {
83       assume( m_position != NULL );
84 
85       {
86         const poly p_next = pNext(m_position);
87 
88         if (p_next != NULL) // not the last term?
89         {
90           m_position = p_next;
91           assume( IsValid() );
92           return true;
93         }
94       }
95 
96       if (m_position == &m_prevposition_struct) // -1 position?
97       {
98         assume( !IsValid() );
99         m_position = m_poly;
100         return (m_position != NULL);
101       }
102 
103       // else: past the end (or an empty polynomial)
104       m_position = NULL;
105       assume( !IsValid() );
106       return false;
107     }
108 };
109 
110 
111 /// This is the interface we use in coeffs.h for ClearDenominators and
112 /// ClearContent.
113 typedef IEnumerator<number> IPolyCoeffsEnumerator;
114 
115 /** @class CPolyCoeffsEnumerator
116  *
117  * This is a polynomial enumerator for simple iteration over
118  * coefficients of polynomials.
119  *
120  * It is required to inherit this class from IEnumerator<number> for
121  * its use in coeffs and implement IAccessor<number> interface.
122  *
123  * Note also the virtual multiple inheritance due to the diamond
124  * problem of inheriting both CBasePolyEnumerator and IEnumerator<T>
125  * from IBaseEnumerator.
126  *
127  * @sa CBasePolyEnumerator, @sa IEnumerator
128  */
129 class CPolyCoeffsEnumerator: public CBasePolyEnumerator, public virtual IPolyCoeffsEnumerator
130 {
131   public:
CPolyCoeffsEnumerator(poly p)132     CPolyCoeffsEnumerator(poly p): CBasePolyEnumerator(p) {}
133 
134     /// Gets the current element in the collection (read and write).
Current()135     virtual IPolyCoeffsEnumerator::reference Current()
136     {
137       assume( IsValid() );
138       return pGetCoeff(m_position);
139     }
140 
141     /// Gets the current element in the collection (read only).
Current()142     virtual IPolyCoeffsEnumerator::const_reference Current() const
143     {
144       assume( IsValid() );
145       return pGetCoeff(m_position);
146     }
147 };
148 
149 
150 struct NAConverter
151 {
convertNAConverter152   static inline poly convert(const number& n)
153   {
154     // suitable for alg. ext. numbers that are just polys actually
155     return (poly)n;
156   }
157 };
158 
159 /// go into polynomials over an alg. extension recursively
160 template <class ConverterPolicy>
161 class CRecursivePolyCoeffsEnumerator: public IPolyCoeffsEnumerator
162 {
163   private:
164     IPolyCoeffsEnumerator& m_global_enumerator; ///< iterates the input polynomial
165     CBasePolyEnumerator m_local_enumerator; ///< iterates the current coeff. of m_global_enumerator
166 
167   protected:
IsValid()168     virtual bool IsValid() const
169     {
170       return m_global_enumerator.IsValid() &&  m_local_enumerator.IsValid();
171     }
172 
173   public:
174 
175     /// NOTE: carefull: don't destruct the input enumerator before doing it with this one...
176     /// this also changes the original IPolyCoeffsEnumerator& itr!
CRecursivePolyCoeffsEnumerator(IPolyCoeffsEnumerator & itr)177     CRecursivePolyCoeffsEnumerator(IPolyCoeffsEnumerator& itr): m_global_enumerator(itr), m_local_enumerator(NULL) {}
178 
MoveNext()179     virtual bool MoveNext()
180     {
181       if( m_local_enumerator.MoveNext() )
182         return true;
183 
184       if( !m_global_enumerator.MoveNext() ) // at the end of the main input polynomial?
185         return false;
186 
187       // TODO: make the following changeable (metaprogramming: use policy?),
188       // leave the following as default option...
189       poly p = ConverterPolicy::convert(m_global_enumerator.Current()); // Assumes that these numbers are just polynomials!
190       assume( p != NULL );
191 
192       // the followig actually needs CPolyCoeffsEnumerator
193       m_local_enumerator.Reset( p ); // -1 position in p :: to be skipped now!
194 
195       if( m_local_enumerator.MoveNext() ) // should be true
196         return true;
197 
198       assume( FALSE ); return MoveNext(); // this should not happen as p should be non-zero, but just in case...
199     }
200 
Reset()201     virtual void Reset()
202     {
203       m_global_enumerator.Reset();
204       m_local_enumerator.Reset(NULL);
205     }
206 
207     /// Gets the current element in the collection (read and write).
Current()208     virtual IPolyCoeffsEnumerator::reference Current()
209     {
210       assume( IsValid() );
211       return pGetCoeff(m_local_enumerator.m_position);
212     }
213 
214     /// Gets the current element in the collection (read only).
Current()215     virtual IPolyCoeffsEnumerator::const_reference Current() const
216     {
217       assume( IsValid() );
218       return pGetCoeff(m_local_enumerator.m_position);
219     }
220 };
221 
222 
223 #endif
224 /* #ifndef POLYENUMERATOR_H */
225 
226 // Vi-modeline: vim: filetype=c:syntax:shiftwidth=2:tabstop=8:textwidth=0:expandtab
227 
228