/* ---- This file is part of SECONDO. Copyright (C) 2013, University in Hagen, Faculty of Mathematics and Computer Science, Database Systems for New Applications. SECONDO 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. SECONDO 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 SECONDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---- //paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}] //[TOC] [\tableofcontents] //[_] [\_] [1] File RegionTools2.h This file contains functions handling with regions of the Region2-Algebra and the MovingRegion3-Algebra. [TOC] 1 Conversion functions for GMP-type mpq\_class 1.1 Function ~gmpTypeToTextType1()~ Reads from inValue and stores its representation as TextType in resultList. */ #include "Region2Tools.h" using namespace std; void gmpTypeToTextType1 (const mpq_class& inValue, ListExpr& resultList) { stringstream theStream; theStream << inValue; resultList = nl->TextAtom(); string st = theStream.str(); nl->AppendText(resultList, st); } /* 1.1 Function ~gmpTypeToTextType2()~ Reads from inValue and stores its representation as TextType in resultList. */ void gmpTypeToTextType2 (const mpq_class& inValue, ListExpr& resultList) { stringstream theStream; mpf_class helper(inValue,1024); theStream << setprecision(1024) << helper; resultList = nl->TextAtom(theStream.str()); } /* 1.1 Function ~textTypeToGmpType1()~ Reads from inList and stores its representation as mpq\_class in outValue. */ void textTypeToGmpType1 (const ListExpr& inList, mpq_class& outValue) { TextScan theScan = nl->CreateTextScan(inList); stringstream theStream; char lastChar = '*'; //just a random initialization... for (unsigned int i = 0; i < nl->TextLength(inList); i++) { string str = ""; nl->GetText(theScan, 1, str); //Checking for valid character if ((int)str[0] < 47 || (int)str[0] > 57 || (i == 0 && (int)str[0] == 48 && nl->TextLength(inList) > 1) || (lastChar == '/' && (int)str[0] == 48)) { stringstream message; message << "Precise coordinate not valid: " << nl->ToString(inList) << endl << "Only characters 1, 2, 3, 4, 5, " "6, 7, 8, 9, 0 and / allowed." << endl << "0 mustn't be leading " "character when " "more than one character " "in total are given" << endl << ", and 0 is " "not allowed directly after /"; throw invalid_argument(message.str()); } theStream.put(str[0]); lastChar = str[0]; } theStream >> outValue; outValue.canonicalize(); if (cmp(outValue, 1) >= 0 || cmp(outValue,0) < 0) { stringstream message; message << "Precise coordinate not valid: " << nl->ToString(inList) << endl << "Resulting value is not between 0 and 1, " "where 0 is allowed, but 1 is not."; throw invalid_argument(message.str()); } } /* 1.1 Function ~textTypeToGmpType2()~ Reads from inList and stores its representation as mpq\_class in outValue. */ void textTypeToGmpType2 (const ListExpr& inList, mpq_class& outValue) { TextScan theScan = nl->CreateTextScan(inList); stringstream numStream, denStream; bool denStart = false; denStream.put('1'); for (unsigned int i = 0; i < nl->TextLength(inList); i++) { string str = ""; nl->GetText(theScan, 1, str); //Checking for valid character // CHECK FOR +/- 3.4e +/- 38 (~7 digits) ???? if ( (int)str[0] < 43 || (int)str[0] > 57 || (int)str[0] == 47 || (int)str[0] == 44 || ((i != 0 || nl->TextLength(inList) == 1) && ((int)str[0] == 43 || (int)str[0] == 45)) ) { stringstream message; message << "Precise coordinate not valid: " << nl->ToString(inList) << endl << "Only characters 1, 2, 3, 4, 5, " "6, 7, 8, 9, 0 and . allowed." << endl << "+/- must be leading " "character when " "more than one character " "in total are given" << endl; throw invalid_argument(message.str()); } if (denStart) denStream.put('0'); if ((int)str[0] != 46) numStream.put(str[0]); else { denStart = true; } } outValue = mpq_class(mpz_class(numStream.str()), mpz_class(denStream.str())); outValue.canonicalize(); } /* 1.1 Function ~D2MPQ()~ Converts value of type double to a value of type mpq\_class */ mpq_class D2MPQ( const double d ) { mpq_class res = mpq_class(d); stringstream s, numStream, denStream; bool denStart = false; denStream.put('1'); s << setprecision(16) << d; if (s.str().find("E") == string::npos && s.str().find("e") == string::npos) { for (unsigned int i = 0; i < s.str().length(); i++) { if (denStart) denStream.put('0'); if ((int)s.str()[i] != 46) numStream.put(s.str()[i]); else { denStart = true; } } res = mpq_class(mpz_class(numStream.str(), 10), mpz_class(denStream.str(), 10)); res.canonicalize(); } return res; } /* 1 Functions to write the precise values to and read them from the DbArray 1.1 Function ~SetValueX()~ Stores value z of type mpz\_class in DbArray of type unsigned int, gives back the startposition and the number of used unsigned int-values */ void SetValueX(mpz_class z, DbArray* preciseValuesArray, int& startpos, int& numofInt) { if (cmp(z, 0) < 0) return; if (startpos == -1) startpos = preciseValuesArray->Size(); int index = startpos; if (index >= preciseValuesArray->Size()) preciseValuesArray->resize(index+1); numofInt = 0; mpz_class zdiv(numeric_limits::max()); zdiv++; mpz_class w(0); while ( !(cmp(z, 0) == 0) ) { w = z%zdiv; unsigned int wert = (unsigned int)w.get_ui(); preciseValuesArray->Put(index, wert); index++; numofInt++; z = z/zdiv; } } /* 1.1 Function ~GetValueX()~ Reads value of type mpz\_class from DbArray of type unsigned int, starting at startposition and with number of used unsigned int-values */ mpz_class GetValueX(const int startpos, const int numofInt, const DbArray* preciseValuesArray) { mpz_class theValue(0); mpz_class zdiv(numeric_limits::max()); zdiv++; unsigned int wert; for (int i = startpos + numofInt-1; i >= startpos; i--) { preciseValuesArray->Get(i, wert); theValue = theValue*zdiv + wert; } return theValue; } /* 1 Functions to detect an overflow of integer values 1.1 Function ~overflowAsInt~ checks int-overflow of x1 or x2 with scalefactor s */ bool overflowAsInt(mpq_class x1, mpq_class x2, int s ) { mpz_t sFactor; mpz_init(sFactor); mpq_class sFac(0); uint sfactor; mpz_class zdiv; mpq_class quot; if (s < 0) { sfactor = -s; mpz_ui_pow_ui(sFactor, 10, sfactor); sFac = mpq_class(mpz_class(1), mpz_class(sFactor)); } else if (s > 0) { sfactor = s; mpz_ui_pow_ui(sFactor, 10, sfactor); sFac = mpq_class(mpz_class(sFactor), mpz_class(1)); } else sFac = mpq_class(1); sFac.canonicalize(); mpz_clear(sFactor); if (cmp(x1, 0) > 0) { x1 = x1*sFac; zdiv = mpz_class(numeric_limits::max())+1; quot = x1 / zdiv; quot.canonicalize(); if (cmp(quot, 1) >= 0) return true; } if (cmp(x1, 0) < 0) { x1 = x1*sFac; zdiv = mpz_class(numeric_limits::min())-1; quot = x1 / zdiv; quot.canonicalize(); if (cmp(quot, 1) >= 0) return true; } if (cmp(x2, 0) > 0) { x2 = x2*sFac; zdiv = mpz_class(numeric_limits::max())+1; quot = x2 / zdiv; quot.canonicalize(); if (cmp(quot, 1) >= 0) return true; } if (cmp(x2, 0) < 0) { x2 = x2*sFac; zdiv = mpz_class(numeric_limits::min())-1; quot = x2 / zdiv; quot.canonicalize(); if (cmp(quot, 1) >= 0) return true; } return false; } /* 1.1 Function ~overflowAsInt~ checks int-overflow of x1 or x2 by scaling with s */ bool overflowAsInt(mpq_class x1, mpq_class x2, double s) { if (s == 1.0) return false; mpq_class sFac(s); mpz_class zdiv; mpq_class quot; if (cmp(x1, 0) > 0 && s > 1.0) { x1 = x1*sFac; zdiv = mpz_class(numeric_limits::max())+1; quot = x1 / zdiv; quot.canonicalize(); if (cmp(quot, 1) >= 0) return true; } if (cmp(x1, 0) > 0 && s < -1.0) { x1 = x1*sFac; zdiv = mpz_class(numeric_limits::min())-1; quot = x1 / zdiv; quot.canonicalize(); if (cmp(quot, 1) >= 0) return true; } if (cmp(x1, 0) < 0 && s > 1.0) { x1 = x1*sFac; zdiv = mpz_class(numeric_limits::min())-1; quot = x1 / zdiv; quot.canonicalize(); if (cmp(quot, 1) >= 0) return true; } if (cmp(x1, 0) < 0 && s < -1.0) { x1 = x1*sFac; zdiv = mpz_class(numeric_limits::max())+1; quot = x1 / zdiv; quot.canonicalize(); if (cmp(quot, 1) >= 0) return true; } if (cmp(x2, 0) > 0 && s > 1.0) { x2 = x2*sFac; zdiv = mpz_class(numeric_limits::max())+1; quot = x2 / zdiv; quot.canonicalize(); if (cmp(quot, 1) >= 0) return true; } if (cmp(x2, 0) > 0 && s < -1.0) { x2 = x2*sFac; zdiv = mpz_class(numeric_limits::min())-1; quot = x2 / zdiv; quot.canonicalize(); if (cmp(quot, 1) >= 0) return true; } if (cmp(x2, 0) < 0 && s > 1.0) { x2 = x2*sFac; zdiv = mpz_class(numeric_limits::min())-1; quot = x2 / zdiv; quot.canonicalize(); if (cmp(quot, 1) >= 0) return true; } if (cmp(x2, 0) < 0 && s < -1.0) { x2 = x2*sFac; zdiv = mpz_class(numeric_limits::max())+1; quot = x2 / zdiv; quot.canonicalize(); if (cmp(quot, 1) >= 0) return true; } return false; } /* 1.1 Function ~checkFactorOverflow~ checks int-overflow of maxI or minI with scalefactor s */ bool checkFactorOverflow(int maxI, int minI, int s ) { if (s <= 0 || (maxI == 0 && minI == 0)) return false; mpz_t sFactor; mpz_init(sFactor); mpq_class sFac(0); uint sfactor; mpz_class zdiv; mpq_class quot; mpz_class x; sfactor = s; mpz_ui_pow_ui(sFactor, 10, sfactor); sFac = mpq_class(mpz_class(sFactor), mpz_class(1)); sFac.canonicalize(); mpz_clear(sFactor); if (maxI > 0) { x = mpz_class(maxI); zdiv = mpz_class(numeric_limits::max()); quot = x * sFac / zdiv; quot.canonicalize(); if (cmp(quot, 1) > 0) return true; } if (minI < 0) { x = mpz_class(minI); zdiv = mpz_class(numeric_limits::min()); quot = x * sFac / zdiv; quot.canonicalize(); if (cmp(quot, 1) > 0) return true; } return false; } /* 1.1 Function ~checkFactorOverflow~ checks int-overflow of maxI or minI by scaling with s */ bool checkFactorOverflow(int maxI, int minI, double s ) { if (s == 1.0 || (maxI == 0 && minI == 0)) return false; mpq_class sFac(s); mpz_class zdiv; mpq_class quot; mpz_class x; if (maxI > 0 && s > 1.0) { x = mpz_class(maxI); zdiv = mpz_class(numeric_limits::max()); quot = x * sFac / zdiv; quot.canonicalize(); if (cmp(quot, 1) > 0) return true; } if (maxI > 0 && s < -1.0) { x = mpz_class(maxI); zdiv = mpz_class(numeric_limits::min()); quot = x * sFac / zdiv; quot.canonicalize(); if (cmp(quot, 1) > 0) return true; } if (minI < 0 && s > 1.0) { x = mpz_class(minI); zdiv = mpz_class(numeric_limits::min()); quot = x * sFac / zdiv; quot.canonicalize(); if (cmp(quot, 1) > 0) return true; } if (minI < 0 && s < -1.0) { x = mpz_class(minI); zdiv = mpz_class(numeric_limits::max()); quot = x * sFac / zdiv; quot.canonicalize(); if (cmp(quot, 1) > 0) return true; } return false; }