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