InputConsumer.cpp
Go to the documentation of this file.
/* Frobby: Software for monomial ideal computations.
Copyright (C) 2011 Bjarke Hammersholt Roune (www.broune.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
*/
#include "stdinc.h"
#include "InputConsumer.h"
#include "Scanner.h"
#include "FrobbyStringStream.h"
#include "error.h"
#include "RawSquareFreeTerm.h"
#include <iostream>
InputConsumer::InputConsumer():
_idealsDeleter(_ideals),
_inIdeal(false),
_requireSquareFree(false) {
}
void InputConsumer::consumeRing(const VarNames& names) {
VarNames nameCopy(names); // exception safety: copy and swap
if (_inIdeal) {
ASSERT(names.getVarCount() == _names.getVarCount());
if (_sqfIdeal.get() != 0)
_sqfIdeal->renameVars(names);
else
_bigIdeal->renameVars(names);
}
_names.swap(nameCopy);
}
void InputConsumer::requireSquareFree() {
ASSERT(!_inIdeal);
_requireSquareFree = true;
}
void InputConsumer::beginIdeal() {
ASSERT(!_inIdeal);
_inIdeal = true;
_sqfIdeal.reset(new SquareFreeIdeal(_names));
_term.resize(_names.getVarCount());
}
void InputConsumer::hintGenCount(size_t hintGenCountParam) {
ASSERT(_inIdeal);
_bigIdeal->reserve(hintGenCountParam);
}
void InputConsumer::beginTerm() {
ASSERT(_inIdeal);
ASSERT(_term.size() == _names.getVarCount());
#ifdef DEBUG
for (size_t var = 0; var < _term.size(); ++var) {
ASSERT(_term[var].empty());
}
#endif
if (_sqfIdeal.get() != 0)
_sqfIdeal->insertIdentity();
else
_bigIdeal->newLastTerm();
}
size_t InputConsumer::consumeVarNumber(Scanner& in) {
ASSERT(_inIdeal);
size_t var;
in.readSizeT(var);
if (var == 0 || var > _names.getVarCount()) {
FrobbyStringStream errorMsg;
errorMsg << "There is no variable number " << var << '.';
reportSyntaxError(in, errorMsg);
}
return var - 1;
}
size_t InputConsumer::consumeVar(Scanner& in) {
ASSERT(_inIdeal);
in.readIdentifier(_tmpString);
size_t var = _names.getIndex(_tmpString);
if (var == VarNames::invalidIndex) {
FrobbyStringStream errorMsg;
errorMsg << "Unknown variable \"" << _tmpString << "\". Maybe you forgot a *.";
reportSyntaxError(in, errorMsg);
}
return var;
}
void InputConsumer::consumeVarExponentOne(size_t var, const Scanner& in) {
ASSERT(_inIdeal);
ASSERT(var < _names.getVarCount());
if (_sqfIdeal.get() != 0) {
Word* back = _sqfIdeal->back();
if (!SquareFreeTermOps::getExponent(back, var)) {
SquareFreeTermOps::setExponent(back, var, true);
return;
}
} else {
mpz_class& exponent = _bigIdeal->getLastTermExponentRef(var);
if (exponent == 0) {
exponent = 1;
return;
}
}
errorVariableAppearsTwice(in, var);
}
void InputConsumer::consumeVarExponent(size_t var, Scanner& in) {
ASSERT(_inIdeal);
ASSERT(var < _names.getVarCount());
if (_sqfIdeal.get() != 0) {
in.readIntegerNoSign(_tmpString);
Word* back = _sqfIdeal->back();
if (!SquareFreeTermOps::getExponent(back, var)) {
if (_tmpString == "1")
SquareFreeTermOps::setExponent(back, var, true);
else if (_tmpString != "0") {
idealNotSquareFree();
_bigIdeal->getLastTermExponentRef(var) = _tmpString;
}
return;
}
} else {
mpz_class& exponent = _bigIdeal->getLastTermExponentRef(var);
if (exponent == 0) {
in.readIntegerNoSign(exponent);
return;
}
}
errorVariableAppearsTwice(in, var);
}
void InputConsumer::consumeTermProductNotation(Scanner& in) {
ASSERT(_inIdeal);
beginTerm();
if (!in.match('1')) {
do {
const size_t var = consumeVar(in);
if (in.match('^'))
consumeVarExponent(var, in);
else
consumeVarExponentOne(var, in);
} while (in.match('*'));
}
endTerm();
}
void InputConsumer::endTerm() {
ASSERT(_inIdeal);
/* const size_t varCount = _names.getVarCount();
if (_sqfIdeal.get() != 0) {
if (_sqfIdeal->insert(_term)) {
for (size_t var = 0; var < varCount; ++var)
_term[var].clear();
return;
}
if (_requireSquareFree)
reportError("Expected square free term.");
toBigIdeal(_sqfIdeal, _bigIdeal);
}
ASSERT(!_requireSquareFree);
ASSERT(_bigIdeal.get() != 0);
_bigIdeal->newLastTerm();
for (size_t var = 0; var < varCount; ++var) {
std::string& str = _term[var];
if (str.empty())
continue;
mpz_class& integer = _bigIdeal->getLastTermExponentRef(var);
mpz_set_str(integer.get_mpz_t(), str.c_str(), 10);
str.clear();
}*/
}
void InputConsumer::endIdeal() {
ASSERT(_inIdeal);
_inIdeal = false;
unique_ptr<Entry> entry(new Entry());
entry->_big = std::move(_bigIdeal);
entry->_sqf = std::move(_sqfIdeal);
exceptionSafePushBack(_ideals, std::move(entry));
}
void InputConsumer::releaseIdeal(unique_ptr<SquareFreeIdeal>& sqf, unique_ptr<BigIdeal>& big) {
ASSERT(!_inIdeal);
ASSERT(!empty());
Entry entry;
releaseIdeal(entry);
sqf = std::move(entry._sqf);
big = std::move(entry._big);
}
unique_ptr<BigIdeal> InputConsumer::releaseBigIdeal() {
ASSERT(!_inIdeal);
ASSERT(!empty());
Entry entry;
releaseIdeal(entry);
toBigIdeal(entry._sqf, entry._big);
return std::move(entry._big);
}
unique_ptr<SquareFreeIdeal> InputConsumer::releaseSquareFreeIdeal() {
ASSERT(!_inIdeal);
ASSERT(!empty());
ASSERT(_ideals.front()->_sqf.get() != 0);
Entry entry;
releaseIdeal(entry);
return std::move(entry._sqf);
}
void InputConsumer::releaseIdeal(Entry& entry) {
ASSERT(!_inIdeal);
ASSERT(!empty());
entry = std::move(*_ideals.front());
_ideals.pop_front();
}
void InputConsumer::errorVariableAppearsTwice(const Scanner& in, size_t var) {
FrobbyStringStream errorMsg;
errorMsg << "The variable " << _names.getName(var)
<< " appears twice in the same monomial.";
reportSyntaxError(in, errorMsg);
}
void InputConsumer::idealNotSquareFree() {
if (_requireSquareFree)
reportError("Expected square free term.");
toBigIdeal(_sqfIdeal, _bigIdeal);
}
void InputConsumer::toBigIdeal(std::unique_ptr<SquareFreeIdeal>& sqf, std::unique_ptr<BigIdeal>& big) {
if (big.get() != 0)
return;
ASSERT(sqf.get() != 0);
big.reset(new BigIdeal(sqf->getNames()));
big->insert(*sqf);
sqf.reset(0);
}
exceptionSafePushBack
void exceptionSafePushBack(Container &container, unique_ptr< Element > pointer)
Definition ElementDeleter.h:129
FrobbyStringStream.h
InputConsumer.h
RawSquareFreeTerm.h
Scanner.h
BigIdeal
Definition BigIdeal.h:27
FrobbyStringStream
A replacement for stringstream.
Definition FrobbyStringStream.h:26
InputConsumer::releaseIdeal
void releaseIdeal(unique_ptr< SquareFreeIdeal > &sqf, unique_ptr< BigIdeal > &big)
Struct that keeps either a BigIdeal or a SquareFreeIdeal.
Definition InputConsumer.cpp:200
InputConsumer::requireSquareFree
void requireSquareFree()
Definition InputConsumer.cpp:45
InputConsumer::errorVariableAppearsTwice
void errorVariableAppearsTwice(const Scanner &in, size_t var)
Definition InputConsumer.cpp:234
InputConsumer::empty
bool empty() const
Returns true if there are ideals stored.
Definition InputConsumer.h:74
InputConsumer::_sqfIdeal
unique_ptr< SquareFreeIdeal > _sqfIdeal
Definition InputConsumer.h:108
InputConsumer::consumeVarNumber
size_t consumeVarNumber(Scanner &in)
Reads variable as a number so that the first variable is 1.
Definition InputConsumer.cpp:76
InputConsumer::idealNotSquareFree
void idealNotSquareFree()
Definition InputConsumer.cpp:241
InputConsumer::releaseBigIdeal
unique_ptr< BigIdeal > releaseBigIdeal()
Returns the least recently read ideal that has not been released.
Definition InputConsumer.cpp:209
InputConsumer::_tmpString
string _tmpString
Definition InputConsumer.h:105
InputConsumer::beginTerm
void beginTerm()
Start consuming a term.
Definition InputConsumer.cpp:62
InputConsumer::beginIdeal
void beginIdeal()
Start consuming an ideal.
Definition InputConsumer.cpp:50
InputConsumer::_requireSquareFree
bool _requireSquareFree
Definition InputConsumer.h:114
InputConsumer::_names
VarNames _names
Definition InputConsumer.h:106
InputConsumer::consumeVar
size_t consumeVar(Scanner &in)
Reads variable and returns id.
Definition InputConsumer.cpp:90
InputConsumer::_ideals
std::list< Entry * > _ideals
Definition InputConsumer.h:111
InputConsumer::consumeTermProductNotation
void consumeTermProductNotation(Scanner &in)
Reads a term in a format like "a^4*b*c^2".
Definition InputConsumer.cpp:148
InputConsumer::consumeRing
void consumeRing(const VarNames &names)
Definition InputConsumer.cpp:33
InputConsumer::releaseSquareFreeIdeal
unique_ptr< SquareFreeIdeal > releaseSquareFreeIdeal()
Returns the least recently read ideal that has not been released.
Definition InputConsumer.cpp:218
InputConsumer::InputConsumer
InputConsumer()
Definition InputConsumer.cpp:27
InputConsumer::consumeVarExponent
void consumeVarExponent(size_t var, Scanner &in)
Consumes var raised to an exponent read from in.
Definition InputConsumer.cpp:122
InputConsumer::hintGenCount
void hintGenCount(size_t hintGenCount)
Suggest that the current ideal will have the given number of generators.
Definition InputConsumer.cpp:57
InputConsumer::consumeVarExponentOne
void consumeVarExponentOne(size_t var, const Scanner &in)
Consumes var raised to the exponent 1.
Definition InputConsumer.cpp:102
InputConsumer::_idealsDeleter
ElementDeleter< std::list< Entry * > > _idealsDeleter
Definition InputConsumer.h:112
InputConsumer::_inIdeal
bool _inIdeal
Definition InputConsumer.h:113
InputConsumer::_bigIdeal
unique_ptr< BigIdeal > _bigIdeal
Definition InputConsumer.h:107
InputConsumer::endIdeal
void endIdeal()
Done reading an ideal.
Definition InputConsumer.cpp:191
InputConsumer::toBigIdeal
static void toBigIdeal(unique_ptr< SquareFreeIdeal > &sqf, unique_ptr< BigIdeal > &big)
Definition InputConsumer.cpp:247
InputConsumer::_term
vector< string > _term
Definition InputConsumer.h:109
InputConsumer::endTerm
void endTerm()
Done reading a term.
Definition InputConsumer.cpp:164
Scanner
This class offers an input interface which is more convenient and for some purposes more efficient th...
Definition Scanner.h:50
Scanner::readIntegerNoSign
void readIntegerNoSign(string &str)
Read an arbitrary-precision integer.
Definition Scanner.h:252
Scanner::readIdentifier
const char * readIdentifier()
The returned string is only valid until the next method on this object gets called.
Definition Scanner.cpp:255
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
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
SquareFreeIdeal
Definition SquareFreeIdeal.h:24
VarNames
Defines the variables of a polynomial ring and facilities IO involving them.
Definition VarNames.h:40
VarNames::getVarCount
size_t getVarCount() const
Returns the current number of variables.
Definition VarNames.h:113
VarNames::invalidIndex
static const size_t invalidIndex
Returns a fixed variable offset that is always invalid.
Definition VarNames.h:100
reportSyntaxError
void reportSyntaxError(const Scanner &scanner, const string &errorMsg)
Definition error.cpp:44
reportError
void reportError(const string &errorMsg)
Definition error.cpp:23
error.h
SquareFreeTermOps::setExponent
void setExponent(Word *a, size_t var, bool value)
Definition RawSquareFreeTerm.h:170
SquareFreeTermOps::getExponent
bool getExponent(const Word *a, size_t var)
returns true if var divides a and false otherwise.
Definition RawSquareFreeTerm.h:151
stdinc.h
This header file includes common definitions and is included as the first line of code in every imple...
Word
unsigned long Word
The native unsigned type for the CPU.
Definition stdinc.h:93
ASSERT
#define ASSERT(X)
Definition stdinc.h:86
InputConsumer::Entry
Definition InputConsumer.h:94
InputConsumer::Entry::_sqf
unique_ptr< SquareFreeIdeal > _sqf
Definition InputConsumer.h:96
InputConsumer::Entry::_big
unique_ptr< BigIdeal > _big
Definition InputConsumer.h:95