Frobby  0.9.5
InputConsumer.cpp
Go to the documentation of this file.
1 /* Frobby: Software for monomial ideal computations.
2  Copyright (C) 2011 Bjarke Hammersholt Roune (www.broune.com)
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program. If not, see http://www.gnu.org/licenses/.
16 */
17 #include "stdinc.h"
18 #include "InputConsumer.h"
19 
20 #include "Scanner.h"
21 #include "FrobbyStringStream.h"
22 #include "error.h"
23 #include "RawSquareFreeTerm.h"
24 
25 #include <iostream>
26 
28  _idealsDeleter(_ideals),
29  _inIdeal(false),
30  _requireSquareFree(false) {
31 }
32 
34  VarNames nameCopy(names); // exception safety: copy and swap
35  if (_inIdeal) {
36  ASSERT(names.getVarCount() == _names.getVarCount());
37  if (_sqfIdeal.get() != 0)
38  _sqfIdeal->renameVars(names);
39  else
40  _bigIdeal->renameVars(names);
41  }
42  _names.swap(nameCopy);
43 }
44 
46  ASSERT(!_inIdeal);
47  _requireSquareFree = true;
48 }
49 
51  ASSERT(!_inIdeal);
52  _inIdeal = true;
53  _sqfIdeal.reset(new SquareFreeIdeal(_names));
54  _term.resize(_names.getVarCount());
55 }
56 
57 void InputConsumer::hintGenCount(size_t hintGenCountParam) {
59  _bigIdeal->reserve(hintGenCountParam);
60 }
61 
64  ASSERT(_term.size() == _names.getVarCount());
65 #ifdef DEBUG
66  for (size_t var = 0; var < _term.size(); ++var) {
67  ASSERT(_term[var].empty());
68  }
69 #endif
70  if (_sqfIdeal.get() != 0)
71  _sqfIdeal->insertIdentity();
72  else
73  _bigIdeal->newLastTerm();
74 }
75 
78 
79  size_t var;
80  in.readSizeT(var);
81 
82  if (var == 0 || var > _names.getVarCount()) {
83  FrobbyStringStream errorMsg;
84  errorMsg << "There is no variable number " << var << '.';
85  reportSyntaxError(in, errorMsg);
86  }
87  return var - 1;
88 }
89 
93  size_t var = _names.getIndex(_tmpString);
94  if (var == VarNames::invalidIndex) {
95  FrobbyStringStream errorMsg;
96  errorMsg << "Unknown variable \"" << _tmpString << "\". Maybe you forgot a *.";
97  reportSyntaxError(in, errorMsg);
98  }
99  return var;
100 }
101 
102 void InputConsumer::consumeVarExponentOne(size_t var, const Scanner& in) {
103  ASSERT(_inIdeal);
104  ASSERT(var < _names.getVarCount());
105 
106  if (_sqfIdeal.get() != 0) {
107  Word* back = _sqfIdeal->back();
108  if (!SquareFreeTermOps::getExponent(back, var)) {
109  SquareFreeTermOps::setExponent(back, var, true);
110  return;
111  }
112  } else {
113  mpz_class& exponent = _bigIdeal->getLastTermExponentRef(var);
114  if (exponent == 0) {
115  exponent = 1;
116  return;
117  }
118  }
119  errorVariableAppearsTwice(in, var);
120 }
121 
123  ASSERT(_inIdeal);
124  ASSERT(var < _names.getVarCount());
125 
126  if (_sqfIdeal.get() != 0) {
128  Word* back = _sqfIdeal->back();
129  if (!SquareFreeTermOps::getExponent(back, var)) {
130  if (_tmpString == "1")
131  SquareFreeTermOps::setExponent(back, var, true);
132  else if (_tmpString != "0") {
134  _bigIdeal->getLastTermExponentRef(var) = _tmpString;
135  }
136  return;
137  }
138  } else {
139  mpz_class& exponent = _bigIdeal->getLastTermExponentRef(var);
140  if (exponent == 0) {
141  in.readIntegerNoSign(exponent);
142  return;
143  }
144  }
145  errorVariableAppearsTwice(in, var);
146 }
147 
149  ASSERT(_inIdeal);
150 
151  beginTerm();
152  if (!in.match('1')) {
153  do {
154  const size_t var = consumeVar(in);
155  if (in.match('^'))
156  consumeVarExponent(var, in);
157  else
158  consumeVarExponentOne(var, in);
159  } while (in.match('*'));
160  }
161  endTerm();
162 }
163 
165  ASSERT(_inIdeal);
166 /* const size_t varCount = _names.getVarCount();
167  if (_sqfIdeal.get() != 0) {
168  if (_sqfIdeal->insert(_term)) {
169  for (size_t var = 0; var < varCount; ++var)
170  _term[var].clear();
171  return;
172  }
173  if (_requireSquareFree)
174  reportError("Expected square free term.");
175  toBigIdeal(_sqfIdeal, _bigIdeal);
176  }
177  ASSERT(!_requireSquareFree);
178 
179  ASSERT(_bigIdeal.get() != 0);
180  _bigIdeal->newLastTerm();
181  for (size_t var = 0; var < varCount; ++var) {
182  std::string& str = _term[var];
183  if (str.empty())
184  continue;
185  mpz_class& integer = _bigIdeal->getLastTermExponentRef(var);
186  mpz_set_str(integer.get_mpz_t(), str.c_str(), 10);
187  str.clear();
188  }*/
189 }
190 
192  ASSERT(_inIdeal);
193  _inIdeal = false;
194  auto_ptr<Entry> entry(new Entry());
195  entry->_big = _bigIdeal;
196  entry->_sqf = _sqfIdeal;
198 }
199 
200 void InputConsumer::releaseIdeal(auto_ptr<SquareFreeIdeal>& sqf, auto_ptr<BigIdeal>& big) {
201  ASSERT(!_inIdeal);
202  ASSERT(!empty());
203  Entry entry;
204  releaseIdeal(entry);
205  sqf = entry._sqf;
206  big = entry._big;
207 }
208 
209 auto_ptr<BigIdeal> InputConsumer::releaseBigIdeal() {
210  ASSERT(!_inIdeal);
211  ASSERT(!empty());
212  Entry entry;
213  releaseIdeal(entry);
214  toBigIdeal(entry._sqf, entry._big);
215  return entry._big;
216 }
217 
218 auto_ptr<SquareFreeIdeal> InputConsumer::releaseSquareFreeIdeal() {
219  ASSERT(!_inIdeal);
220  ASSERT(!empty());
221  ASSERT(_ideals.front()->_sqf.get() != 0);
222  Entry entry;
223  releaseIdeal(entry);
224  return entry._sqf;
225 }
226 
228  ASSERT(!_inIdeal);
229  ASSERT(!empty());
230  entry = *_ideals.front();
231  _ideals.pop_front();
232 }
233 
235  FrobbyStringStream errorMsg;
236  errorMsg << "The variable " << _names.getName(var)
237  << " appears twice in the same monomial.";
238  reportSyntaxError(in, errorMsg);
239 }
240 
242  if (_requireSquareFree)
243  reportError("Expected square free term.");
245 }
246 
247 void InputConsumer::toBigIdeal(std::auto_ptr<SquareFreeIdeal>& sqf, std::auto_ptr<BigIdeal>& big) {
248  if (big.get() != 0)
249  return;
250  ASSERT(sqf.get() != 0);
251  big.reset(new BigIdeal(sqf->getNames()));
252  big->insert(*sqf);
253  sqf.reset(0);
254 }
void exceptionSafePushBack(Container &container, auto_ptr< Element > pointer)
A replacement for stringstream.
void requireSquareFree()
void errorVariableAppearsTwice(const Scanner &in, size_t var)
auto_ptr< SquareFreeIdeal > releaseSquareFreeIdeal()
Returns the least recently read ideal that has not been released.
bool empty() const
Returns true if there are ideals stored.
Definition: InputConsumer.h:74
size_t consumeVarNumber(Scanner &in)
Reads variable as a number so that the first variable is 1.
void idealNotSquareFree()
void releaseIdeal(auto_ptr< SquareFreeIdeal > &sqf, auto_ptr< BigIdeal > &big)
Struct that keeps either a BigIdeal or a SquareFreeIdeal.
void beginTerm()
Start consuming a term.
void beginIdeal()
Start consuming an ideal.
bool _requireSquareFree
VarNames _names
size_t consumeVar(Scanner &in)
Reads variable and returns id.
std::list< Entry * > _ideals
void consumeTermProductNotation(Scanner &in)
Reads a term in a format like "a^4*b*c^2".
static void toBigIdeal(auto_ptr< SquareFreeIdeal > &sqf, auto_ptr< BigIdeal > &big)
void consumeRing(const VarNames &names)
void consumeVarExponent(size_t var, Scanner &in)
Consumes var raised to an exponent read from in.
void hintGenCount(size_t hintGenCount)
Suggest that the current ideal will have the given number of generators.
auto_ptr< BigIdeal > releaseBigIdeal()
Returns the least recently read ideal that has not been released.
auto_ptr< SquareFreeIdeal > _sqfIdeal
void consumeVarExponentOne(size_t var, const Scanner &in)
Consumes var raised to the exponent 1.
auto_ptr< BigIdeal > _bigIdeal
void endIdeal()
Done reading an ideal.
vector< string > _term
void endTerm()
Done reading a term.
This class offers an input interface which is more convenient and for some purposes more efficient th...
Definition: Scanner.h:50
void readIntegerNoSign(string &str)
Read an arbitrary-precision integer.
Definition: Scanner.h:252
const char * readIdentifier()
The returned string is only valid until the next method on this object gets called.
Definition: Scanner.cpp:255
void readSizeT(size_t &size)
Reads a size_t, where the representable range of that type determines when the number is too big.
Definition: Scanner.cpp:205
bool match(char c)
Return true if the next character is c, and in that case skip past it.
Definition: Scanner.h:215
Defines the variables of a polynomial ring and facilities IO involving them.
Definition: VarNames.h:40
size_t getVarCount() const
Returns the current number of variables.
Definition: VarNames.h:113
const string & getName(size_t index) const
The returned reference can become invalid next time addVar is called.
Definition: VarNames.cpp:100
void swap(VarNames &names)
Definition: VarNames.cpp:190
static const size_t invalidIndex
Returns a fixed variable offset that is always invalid.
Definition: VarNames.h:100
size_t getIndex(const string &name) const
Returns VarNames::invalidIndex() if name is not known.
Definition: VarNames.cpp:83
void reportSyntaxError(const Scanner &scanner, const string &errorMsg)
Definition: error.cpp:44
void reportError(const string &errorMsg)
Definition: error.cpp:23
void setExponent(Word *a, size_t var, bool value)
bool getExponent(const Word *a, size_t var)
returns true if var divides a and false otherwise.
unsigned long Word
The native unsigned type for the CPU.
Definition: stdinc.h:93
#define ASSERT(X)
Definition: stdinc.h:86
auto_ptr< SquareFreeIdeal > _sqf
Definition: InputConsumer.h:96
auto_ptr< BigIdeal > _big
Definition: InputConsumer.h:95