Frobby 0.9.5
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
33namespace 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
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
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
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}
virtual void beginConsuming()=0
virtual void consume(const mpz_class &coef, const Term &term)
virtual void doneConsuming()=0
virtual void consumeRing(const VarNames &names)=0
static const DataType & getMonomialIdealListType()
Returns the one and only instance for monomial ideal lists.
Definition: DataType.cpp:54
static const DataType & getMonomialIdealType()
Returns the one and only instance for monomial ideals.
Definition: DataType.cpp:45
static const DataType & getPolynomialType()
Returns the one and only instance for polynomials.
Definition: DataType.cpp:50
A replacement for stringstream.
virtual BigTermConsumer * doCreateIdealWriter(FILE *out)
virtual void doReadBarePolynomial(Scanner &in, const VarNames &names, CoefBigTermConsumer &consumer)
virtual void doReadBareIdeal(Scanner &in, InputConsumer &consumer)
virtual void doReadRing(Scanner &in, VarNames &names)
virtual CoefBigTermConsumer * doCreatePolynomialWriter(FILE *out)
virtual void doReadTerm(Scanner &in, InputConsumer &consumer)
static const char * staticGetName()
virtual bool doPeekRing(Scanner &in)
virtual void doWriteTerm(const vector< mpz_class > &term, const VarNames &names, FILE *out)
virtual void doWriteEmptyList()
virtual void doWriteTerm(const Term &term, const TermTranslator &translator, bool first)
virtual void doWriteFooter(bool wasZeroIdeal)
virtual void doWriteHeader(bool first)
virtual void doWriteTerm(const vector< mpz_class > &term, bool first)
virtual void doWriteTerm(const mpz_class &coef, const Term &term, const TermTranslator &translator, bool firstGenerator)
virtual void doWriteHeader()
virtual void doWriteFooter(bool wasZero)
virtual void doWriteTerm(const mpz_class &coef, const vector< mpz_class > &term, bool firstGenerator)
This class contains further functionality that makes it more convenient to derive from than IOHandler...
void registerInput(const DataType &type)
Specify that input of the argument type is supported.
void registerOutput(const DataType &type)
Specify that output of the argument type is supported.
FILE * getFile()
Definition: IdealWriter.h:43
const VarNames & getNames()
Definition: IdealWriter.h:44
FILE * getFile()
Definition: PolyWriter.h:40
const VarNames & getNames() const
Definition: PolyWriter.h:41
size_t consumeVarNumber(Scanner &in)
Reads variable as a number so that the first variable is 1.
void beginTerm()
Start consuming a term.
void beginIdeal()
Start consuming an ideal.
void consumeVarExponent(size_t var, Scanner &in)
Consumes var raised to an exponent read from in.
void consumeVarExponentOne(size_t var, const Scanner &in)
Consumes var raised to the exponent 1.
void endIdeal()
Done reading an ideal.
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
bool peek(char character)
Skips whitespace and returns true if the next character is equal to the parameter(s).
Definition: Scanner.h:262
void eatWhite()
Reads past any whitespace, where whitespace is defined by the standard function isspace().
Definition: Scanner.h:267
bool peekWhite()
Returns true if the next character is whitespace.
Definition: Scanner.h:137
void expect(char expected)
Require the next character to be equal to expected.
Definition: Scanner.h:231
const char * readIdentifier()
The returned string is only valid until the next method on this object gets called.
Definition: Scanner.cpp:255
bool peekIdentifier()
Skips whitespace and returns true if the next token is an identifier.
Definition: Scanner.h:257
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
void readInteger(mpz_class &integer)
Read an arbitrary-precision integer.
Definition: Scanner.h:238
bool match(char c)
Return true if the next character is c, and in that case skip past it.
Definition: Scanner.h:215
TermTranslator handles translation between terms whose exponents are infinite precision integers and ...
const char * getExponentString(size_t variable, Exponent exponent) const
as getExponent, except the string "e" is returned, where e is the exponent.
Term represents a product of variables which does not include a coefficient.
Definition: Term.h:49
size_t getVarCount() const
Definition: Term.h:85
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
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 clear()
Resets the number of variables to zero.
Definition: VarNames.cpp:106
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
void reportSyntaxError(const Scanner &scanner, const string &errorMsg)
Definition: error.cpp:44
void writeTermProduct(const Term &term, const TermTranslator &translator, FILE *out)
void readTerm(Scanner &in, InputConsumer &consumer)
void readCoefTerm(mpz_class &coef, vector< mpz_class > &term, bool firstTerm, Scanner &in)
void readTerm(Scanner &in, vector< mpz_class > &term)
void readVarPower(vector< mpz_class > &term, Scanner &in)
void readVarPower(Scanner &in, InputConsumer &consumer)
void writeTermProduct(const vector< mpz_class > &term, const VarNames &names, FILE *out)
void writeRing(const VarNames &names, FILE *out)
bool isIdentity(const Word *a, Word *aEnd)