Files
secondo/Algebras/Region2/Region2Tools.cpp

541 lines
13 KiB
C++
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
----
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<unsigned int>* 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<unsigned int>::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<unsigned int>* preciseValuesArray)
{
mpz_class theValue(0);
mpz_class zdiv(numeric_limits<unsigned int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::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<int>::max());
quot = x * sFac / zdiv;
quot.canonicalize();
if (cmp(quot, 1) > 0)
return true;
}
return false;
}