Frobby  0.9.1
CoCoA4IOHandler.cpp
Go to the documentation of this file.
1 /* Frobby: Software for monomial ideal computations.
2  Copyright (C) 2007 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 "CoCoA4IOHandler.h"
19 
20 #include "Scanner.h"
21 #include "VarNames.h"
22 #include "Term.h"
23 #include "TermTranslator.h"
24 #include "FrobbyStringStream.h"
25 #include "DataType.h"
26 #include "IdealWriter.h"
27 #include "PolyWriter.h"
28 #include "error.h"
29 #include "InputConsumer.h"
30 
31 #include <cstdio>
32 
33 namespace IO {
34  namespace CoCoA4 {
35  void writeRing(const VarNames& names, FILE* out);
36  void writeTermProduct(const Term& term,
37  const TermTranslator& translator,
38  FILE* out);
39  void writeTermProduct(const vector<mpz_class>& term,
40  const VarNames& names,
41  FILE* out);
42  void readTerm(Scanner& in, vector<mpz_class>& term);
43  void readTerm(Scanner& in, InputConsumer& consumer);
44  void readVarPower(vector<mpz_class>& term, Scanner& in);
45  void readVarPower(Scanner& in, InputConsumer& consumer);
46  void readCoefTerm(mpz_class& coef,
47  vector<mpz_class>& term,
48  bool firstTerm,
49  Scanner& in);
50  }
51  namespace C = CoCoA4;
52 
53  class CoCoA4IdealWriter : public IdealWriter {
54  public:
55  CoCoA4IdealWriter(FILE* out): IdealWriter(out) {
56  }
57 
58  private:
59  virtual void doWriteHeader(bool first) {
61  fputs("I := Ideal(", getFile());
62  }
63 
64  virtual void doWriteTerm(const Term& term,
65  const TermTranslator& translator,
66  bool first) {
67  fputs(first ? "\n " : ",\n ", getFile());
68  C::writeTermProduct(term, translator, getFile());
69  }
70 
71  virtual void doWriteTerm(const vector<mpz_class>& term,
72  bool first) {
73  fputs(first ? "\n " : ",\n ", getFile());
75  }
76 
77  virtual void doWriteFooter(bool wasZeroIdeal) {
78  fputs("\n);\n", getFile());
79  }
80 
81  virtual void doWriteEmptyList() {
83  }
84  };
85 
86  class CoCoA4PolyWriter : public PolyWriter {
87  public:
88  CoCoA4PolyWriter(FILE* out): PolyWriter(out) {
89  }
90 
91  virtual void doWriteHeader() {
93  fputs("p :=", getFile());
94  }
95 
96  virtual void doWriteTerm(const mpz_class& coef,
97  const Term& term,
98  const TermTranslator& translator,
99  bool firstGenerator) {
100  fputs("\n ", getFile());
101 
102  if (coef >= 0 && !firstGenerator)
103  fputc('+', getFile());
104 
105  if (term.isIdentity()) {
106  gmp_fprintf(getFile(), "%Zd", coef.get_mpz_t());
107  return;
108  }
109 
110  if (coef == -1)
111  fputc('-', getFile());
112  else if (coef != 1)
113  gmp_fprintf(getFile(), "%Zd", coef.get_mpz_t());
114 
115  C::writeTermProduct(term, translator, getFile());
116  }
117 
118  virtual void doWriteTerm(const mpz_class& coef,
119  const vector<mpz_class>& term,
120  bool firstGenerator) {
121  fputs("\n ", getFile());
122  if (coef >= 0 && !firstGenerator)
123  fputc('+', getFile());
124 
125  bool isIdentity = true;
126  for (size_t var = 0; var < term.size(); ++var)
127  if (term[var] != 0)
128  isIdentity = false;
129 
130  if (isIdentity) {
131  gmp_fprintf(getFile(), "%Zd", coef.get_mpz_t());
132  return;
133  }
134 
135  if (coef == -1)
136  fputc('-', getFile());
137  else if (coef != 1)
138  gmp_fprintf(getFile(), "%Zd", coef.get_mpz_t());
139 
141  }
142 
143  virtual void doWriteFooter(bool wasZero) {
144  if (wasZero)
145  fputs("\n 0", getFile());
146  fputs(";\n", getFile());
147  }
148  };
149 
151  IOHandlerCommon(staticGetName(),
152  "Format understandable by the program CoCoA 4.") {
158  }
159 
161  return "cocoa4";
162  }
163 
165  return new CoCoA4IdealWriter(out);
166  }
167 
169  return new CoCoA4PolyWriter(out);
170  }
171 
172  void CoCoA4IOHandler::doWriteTerm(const vector<mpz_class>& term,
173  const VarNames& names,
174  FILE* out) {
175  C::writeTermProduct(term, names, out);
176  }
177 
179  C::readTerm(in, consumer);
180  }
181 
183  names.clear();
184 
185  in.expect("Use");
186  in.expect('R');
187  in.expect("::=");
188  in.expect('Q');
189  in.expect('[');
190  in.expect('x');
191 
192  size_t varCount = 0;
193  if (in.match('[')) {
194  in.expect('1');
195  in.expect("..");
196  in.readSizeT(varCount);
197  in.expect(']');
198  }
199  in.expect(']');
200  in.expect(';');
201 
202  in.expect("Names");
203  in.expect(":=");
204  in.expect('[');
205 
206  for (size_t var = 0; var < varCount; ++var) {
207  in.expect('\"');
208  if (in.peekWhite())
209  reportSyntaxError(in, "Variable name contains space.");
210 
211  names.addVarSyntaxCheckUnique(in, in.readIdentifier());
212 
213  if (in.peekWhite())
214  reportSyntaxError(in, "Variable name contains space.");
215 
216  in.expect('\"');
217  if (var < varCount - 1)
218  in.expect(',');
219  }
220 
221  in.expect(']');
222  in.expect(';');
223  }
224 
226  return in.peek('U') || in.peek('u');
227  }
228 
230  (Scanner& in, InputConsumer& consumer) {
231  consumer.beginIdeal();
232 
233  in.expect('I');
234  in.expect(":=");
235  in.expect("Ideal");
236  in.expect('(');
237 
238  if (!in.match(')')) {
239  do {
240  C::readTerm(in, consumer);
241  } while (in.match(','));
242  in.expect(')');
243  }
244  in.match(';');
245 
246  consumer.endIdeal();
247  }
248 
250  const VarNames& names,
251  CoefBigTermConsumer& consumer) {
252  consumer.consumeRing(names);
253  vector<mpz_class> term(names.getVarCount());
254  mpz_class coef;
255 
256  in.expect('p');
257  in.expect(":=");
258 
259  consumer.beginConsuming();
260  bool first = true;
261  do {
262  C::readCoefTerm(coef, term, first, in);
263  consumer.consume(coef, term);
264  first = false;
265  } while (!in.match(';'));
266  consumer.doneConsuming();
267  }
268 
269  void C::writeRing(const VarNames& names, FILE* out) {
270  if (names.getVarCount() == 0) {
271  fputs("Use R ::= Q[x];\nNames := [];\n", out);
272  return;
273  }
274 
275  fprintf(out, "Use R ::= Q[x[1..%lu]];\n",
276  (unsigned long)names.getVarCount());
277 
278  fputs("Names := [", out);
279 
280  const char* pre = "\"";
281  for (size_t i = 0; i < names.getVarCount(); ++i) {
282  fputs(pre, out);
283  fputs(names.getName(i).c_str(), out);
284  pre = "\", \"";
285  }
286  fputs("\"];\n", out);
287  }
288 
289  void C::writeTermProduct(const Term& term,
290  const TermTranslator& translator,
291  FILE* out) {
292  bool seenNonZero = false;
293  size_t varCount = term.getVarCount();
294  for (size_t var = 0; var < varCount; ++var) {
295  const char* exp = translator.getExponentString(var, term[var]);
296  if (exp == 0)
297  continue;
298  seenNonZero = true;
299 
300  fprintf(out, "x[%lu]", (unsigned long)(var + 1));
301  if (exp[0] != '1' || exp[1] != '\0') {
302  fputc('^', out);
303  fputs(exp, out);
304  }
305  }
306 
307  if (!seenNonZero)
308  fputc('1', out);
309  }
310 
311  void C::writeTermProduct(const vector<mpz_class>& term,
312  const VarNames& names,
313  FILE* out) {
314  bool seenNonZero = false;
315  size_t varCount = term.size();
316  for (size_t var = 0; var < varCount; ++var) {
317  if (term[var] == 0)
318  continue;
319  seenNonZero = true;
320 
321  fprintf(out, "x[%lu]", (unsigned long)(var + 1));
322  if (term[var] != 1) {
323  fputc('^', out);
324  mpz_out_str(out, 10, term[var].get_mpz_t());
325  }
326  }
327 
328  if (!seenNonZero)
329  fputc('1', out);
330  }
331 
332  void C::readTerm(Scanner& in, vector<mpz_class>& term) {
333  for (size_t var = 0; var < term.size(); ++var)
334  term[var] = 0;
335 
336  if (in.match('1'))
337  return;
338 
339  do {
340  C::readVarPower(term, in);
341  in.eatWhite();
342  } while (in.peek() == 'x');
343  }
344 
345  void C::readTerm(Scanner& in, InputConsumer& consumer) {
346  consumer.beginTerm();
347  if (!in.match('1')) {
348  do {
349  C::readVarPower(in, consumer);
350  in.eatWhite();
351  } while (in.peek() == 'x');
352  }
353  consumer.endTerm();
354  }
355 
356  void C::readVarPower(vector<mpz_class>& term, Scanner& in) {
357  in.expect('x');
358  in.expect('[');
359 
360  size_t var;
361  in.readSizeT(var);
362  if (var == 0 || var > term.size()) {
363  FrobbyStringStream errorMsg;
364  errorMsg << "There is no variable x[" << var << "].";
365  reportSyntaxError(in, errorMsg);
366  }
367  --var;
368 
369  in.expect(']');
370 
371  if (term[var] != 0) {
372  FrobbyStringStream errorMsg;
373  errorMsg << "The variable x["
374  << (var + 1)
375  << "] appears twice in the same monomial.";
376  reportSyntaxError(in, errorMsg);
377  }
378 
379  if (in.match('^')) {
380  in.readInteger(term[var]);
381  if (term[var] <= 0) {
382  FrobbyStringStream errorMsg;
383  errorMsg << "Expected positive integer as exponent but got "
384  << term[var] << '.';
385  reportSyntaxError(in, errorMsg);
386  }
387  } else
388  term[var] = 1;
389  }
390 
391  void C::readVarPower(Scanner& in, InputConsumer& consumer) {
392  in.expect('x');
393  in.expect('[');
394  size_t var = consumer.consumeVarNumber(in);
395  in.expect(']');
396  if (in.match('^'))
397  consumer.consumeVarExponent(var, in);
398  else
399  consumer.consumeVarExponentOne(var, in);
400  }
401 
402  void C::readCoefTerm(mpz_class& coef,
403  vector<mpz_class>& term,
404  bool firstTerm,
405  Scanner& in) {
406  for (size_t var = 0; var < term.size(); ++var)
407  term[var] = 0;
408 
409  bool positive = true;
410  if (!firstTerm && in.match('+'))
411  positive = !in.match('-');
412  else if (in.match('-'))
413  positive = false;
414  else if (!firstTerm) {
415  in.expect('+');
416  return;
417  }
418  if (in.match('+') || in.match('-'))
419  reportSyntaxError(in, "Too many adjacent signs.");
420 
421  if (in.peekIdentifier()) {
422  coef = 1;
423  C::readVarPower(term, in);
424  } else
425  in.readInteger(coef);
426 
427  in.eatWhite();
428  while (in.peek() == 'x') {
429  C::readVarPower(term, in);
430  in.eatWhite();
431  }
432 
433  if (!positive)
434  coef = -coef;
435  }
436 }
IO::CoCoA4IOHandler::doCreatePolynomialWriter
virtual CoefBigTermConsumer * doCreatePolynomialWriter(FILE *out)
Definition: CoCoA4IOHandler.cpp:168
Term::isIdentity
static bool isIdentity(const Exponent *a, size_t varCount)
Returns whether a is 1, i.e. whether all entries of a are 0.
Definition: Term.h:316
DataType.h
IO::CoCoA4IOHandler::doPeekRing
virtual bool doPeekRing(Scanner &in)
Definition: CoCoA4IOHandler.cpp:225
CoefBigTermConsumer
Definition: CoefBigTermConsumer.h:29
DataType::getMonomialIdealListType
static const DataType & getMonomialIdealListType()
Returns the one and only instance for monomial ideal lists.
Definition: DataType.cpp:54
IO::CoCoA4::readCoefTerm
void readCoefTerm(mpz_class &coef, vector< mpz_class > &term, bool firstTerm, Scanner &in)
Scanner::readInteger
void readInteger(mpz_class &integer)
Read an arbitrary-precision integer.
Definition: Scanner.h:238
stdinc.h
IO::PolyWriter
Definition: PolyWriter.h:25
DataType::getPolynomialType
static const DataType & getPolynomialType()
Returns the one and only instance for polynomials.
Definition: DataType.cpp:50
IO::CoCoA4IOHandler::doReadRing
virtual void doReadRing(Scanner &in, VarNames &names)
Definition: CoCoA4IOHandler.cpp:182
IO::CoCoA4::writeRing
void writeRing(const VarNames &names, FILE *out)
IO::CoCoA4IOHandler::CoCoA4IOHandler
CoCoA4IOHandler()
Definition: CoCoA4IOHandler.cpp:150
IO::CoCoA4::readTerm
void readTerm(Scanner &in, InputConsumer &consumer)
InputConsumer::beginTerm
void beginTerm()
Start consuming a term.
Definition: InputConsumer.cpp:62
IO::CoCoA4IdealWriter::doWriteEmptyList
virtual void doWriteEmptyList()
Definition: CoCoA4IOHandler.cpp:81
Scanner
This class offers an input interface which is more convenient and for some purposes more efficient th...
Definition: Scanner.h:50
InputConsumer::consumeVarNumber
size_t consumeVarNumber(Scanner &in)
Reads variable as a number so that the first variable is 1.
Definition: InputConsumer.cpp:76
IO::IOHandlerCommon
This class contains further functionality that makes it more convenient to derive from than IOHandler...
Definition: IOHandlerCommon.h:33
IO::CoCoA4IOHandler::doReadBarePolynomial
virtual void doReadBarePolynomial(Scanner &in, const VarNames &names, CoefBigTermConsumer &consumer)
Definition: CoCoA4IOHandler.cpp:249
IO::IOHandlerImpl::registerInput
void registerInput(const DataType &type)
Specify that input of the argument type is supported.
Definition: IOHandlerImpl.cpp:60
IO::CoCoA4::readVarPower
void readVarPower(vector< mpz_class > &term, Scanner &in)
PolyWriter.h
CoefBigTermConsumer::consumeRing
virtual void consumeRing(const VarNames &names)=0
IO::CoCoA4::writeTermProduct
void writeTermProduct(const Term &term, const TermTranslator &translator, FILE *out)
IO::CoCoA4PolyWriter::CoCoA4PolyWriter
CoCoA4PolyWriter(FILE *out)
Definition: CoCoA4IOHandler.cpp:88
IO::IdealWriter::getNames
const VarNames & getNames()
Definition: IdealWriter.h:44
IO::CoCoA4PolyWriter::doWriteTerm
virtual void doWriteTerm(const mpz_class &coef, const vector< mpz_class > &term, bool firstGenerator)
Definition: CoCoA4IOHandler.cpp:118
IO::CoCoA4IdealWriter::doWriteTerm
virtual void doWriteTerm(const vector< mpz_class > &term, bool first)
Definition: CoCoA4IOHandler.cpp:71
IO::CoCoA4::readTerm
void readTerm(Scanner &in, vector< mpz_class > &term)
Term::getVarCount
size_t getVarCount() const
Definition: Term.h:85
IO::CoCoA4PolyWriter::doWriteTerm
virtual void doWriteTerm(const mpz_class &coef, const Term &term, const TermTranslator &translator, bool firstGenerator)
Definition: CoCoA4IOHandler.cpp:96
Scanner::match
bool match(char c)
Return true if the next character is c, and in that case skip past it.
Definition: Scanner.h:215
IO::PolyWriter::getFile
FILE * getFile()
Definition: PolyWriter.h:40
CoefBigTermConsumer::beginConsuming
virtual void beginConsuming()=0
Scanner::readIdentifier
const char * readIdentifier()
The returned string is only valid until the next method on this object gets called.
Definition: Scanner.cpp:255
VarNames::getName
const string & getName(size_t index) const
The returned reference can become invalid next time addVar is called.
Definition: VarNames.cpp:100
IO::CoCoA4PolyWriter
Definition: CoCoA4IOHandler.cpp:86
IO::CoCoA4PolyWriter::doWriteHeader
virtual void doWriteHeader()
Definition: CoCoA4IOHandler.cpp:91
Term.h
TermTranslator
TermTranslator handles translation between terms whose exponents are infinite precision integers and ...
Definition: TermTranslator.h:41
FrobbyStringStream.h
VarNames::addVarSyntaxCheckUnique
void addVarSyntaxCheckUnique(const Scanner &in, const string &name)
As addvar, except it reports a syntax error if name is already a variable.
Definition: VarNames.cpp:68
IO::PolyWriter::getNames
const VarNames & getNames() const
Definition: PolyWriter.h:41
InputConsumer::consumeVarExponentOne
void consumeVarExponentOne(size_t var, const Scanner &in)
Consumes var raised to the exponent 1.
Definition: InputConsumer.cpp:102
VarNames::getVarCount
size_t getVarCount() const
Returns the current number of variables.
Definition: VarNames.h:113
Scanner.h
InputConsumer::endIdeal
void endIdeal()
Done reading an ideal.
Definition: InputConsumer.cpp:191
IO
Definition: CoCoA4IOHandler.cpp:33
IO::CoCoA4IdealWriter::doWriteHeader
virtual void doWriteHeader(bool first)
Definition: CoCoA4IOHandler.cpp:59
IO::CoCoA4IdealWriter::CoCoA4IdealWriter
CoCoA4IdealWriter(FILE *out)
Definition: CoCoA4IOHandler.cpp:55
CoefBigTermConsumer::doneConsuming
virtual void doneConsuming()=0
InputConsumer
Definition: InputConsumer.h:30
VarNames.h
IO::IdealWriter::getFile
FILE * getFile()
Definition: IdealWriter.h:43
Scanner::peekWhite
bool peekWhite()
Returns true if the next character is whitespace.
Definition: Scanner.h:137
IO::CoCoA4IOHandler::doReadBareIdeal
virtual void doReadBareIdeal(Scanner &in, InputConsumer &consumer)
Definition: CoCoA4IOHandler.cpp:230
Term
Term represents a product of variables which does not include a coefficient.
Definition: Term.h:49
error.h
BigTermConsumer
Definition: BigTermConsumer.h:29
Scanner::expect
void expect(char expected)
Require the next character to be equal to expected.
Definition: Scanner.h:231
InputConsumer::endTerm
void endTerm()
Done reading a term.
Definition: InputConsumer.cpp:164
reportSyntaxError
void reportSyntaxError(const Scanner &scanner, const string &errorMsg)
Definition: error.cpp:44
IdealWriter.h
IO::CoCoA4IOHandler::doWriteTerm
virtual void doWriteTerm(const vector< mpz_class > &term, const VarNames &names, FILE *out)
Definition: CoCoA4IOHandler.cpp:172
TermTranslator::getExponentString
const char * getExponentString(size_t variable, Exponent exponent) const
as getExponent, except the string "e" is returned, where e is the exponent.
Definition: TermTranslator.cpp:410
VarNames::clear
void clear()
Resets the number of variables to zero.
Definition: VarNames.cpp:106
IO::CoCoA4::readVarPower
void readVarPower(Scanner &in, InputConsumer &consumer)
IO::CoCoA4IdealWriter::doWriteTerm
virtual void doWriteTerm(const Term &term, const TermTranslator &translator, bool first)
Definition: CoCoA4IOHandler.cpp:64
IO::IOHandlerImpl::registerOutput
void registerOutput(const DataType &type)
Specify that output of the argument type is supported.
Definition: IOHandlerImpl.cpp:67
Scanner::readSizeT
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
DataType::getMonomialIdealType
static const DataType & getMonomialIdealType()
Returns the one and only instance for monomial ideals.
Definition: DataType.cpp:45
IO::CoCoA4PolyWriter::doWriteFooter
virtual void doWriteFooter(bool wasZero)
Definition: CoCoA4IOHandler.cpp:143
TermTranslator.h
InputConsumer.h
FrobbyStringStream
A replacement for stringstream.
Definition: FrobbyStringStream.h:26
Scanner::eatWhite
void eatWhite()
Reads past any whitespace, where whitespace is defined by the standard function isspace().
Definition: Scanner.h:267
IO::CoCoA4IOHandler::doReadTerm
virtual void doReadTerm(Scanner &in, InputConsumer &consumer)
Definition: CoCoA4IOHandler.cpp:178
IO::CoCoA4::writeTermProduct
void writeTermProduct(const vector< mpz_class > &term, const VarNames &names, FILE *out)
CoefBigTermConsumer::consume
virtual void consume(const mpz_class &coef, const Term &term)
Definition: CoefBigTermConsumer.cpp:25
InputConsumer::consumeVarExponent
void consumeVarExponent(size_t var, Scanner &in)
Consumes var raised to an exponent read from in.
Definition: InputConsumer.cpp:122
IO::CoCoA4IdealWriter::doWriteFooter
virtual void doWriteFooter(bool wasZeroIdeal)
Definition: CoCoA4IOHandler.cpp:77
InputConsumer::beginIdeal
void beginIdeal()
Start consuming an ideal.
Definition: InputConsumer.cpp:50
Scanner::peekIdentifier
bool peekIdentifier()
Skips whitespace and returns true if the next token is an identifier.
Definition: Scanner.h:257
VarNames
Defines the variables of a polynomial ring and facilities IO involving them.
Definition: VarNames.h:40
IO::CoCoA4IOHandler::doCreateIdealWriter
virtual BigTermConsumer * doCreateIdealWriter(FILE *out)
Definition: CoCoA4IOHandler.cpp:164
IO::CoCoA4IdealWriter
Definition: CoCoA4IOHandler.cpp:53
CoCoA4IOHandler.h
Scanner::peek
bool peek(char character)
Skips whitespace and returns true if the next character is equal to the parameter(s).
Definition: Scanner.h:262
IO::CoCoA4IOHandler::staticGetName
static const char * staticGetName()
Definition: CoCoA4IOHandler.cpp:160
IO::IdealWriter
Definition: IdealWriter.h:28
SquareFreeTermOps::isIdentity
bool isIdentity(const Word *a, Word *aEnd)
Definition: RawSquareFreeTerm.cpp:51