/* * This file is part of rasdaman community. * * Rasdaman community 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 3 of the License, or * (at your option) any later version. * * Rasdaman community 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 rasdaman community. If not, see . * * Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / rasdaman GmbH. * * For more information please see * or contact Peter Baumann via . / /** * SOURCE: Minterval.cc * * MODULE: raslib * CLASS: r_Minterval * * COMMENTS: * */ static const char rcsid[] = "@(#)raslib, r_Minterval: $Header: /home/rasdev/CVS-repository/rasdaman/raslib/minterval.cc,v 1.54 2005/09/03 20:31:22 rasdev Exp $"; using namespace std; using namespace std; #include "raslib/rmdebug.hh" #include "raslib/minterval.hh" #include "raslib/odmgtypes.hh" #include "raslib/dlist.hh" #include "mymalloc/mymalloc.h" #include #include #include #ifdef __VISUALC__ #include #else #include #endif r_Minterval::r_Minterval(r_Dimension dim) : dimensionality(dim), streamInitCnt(0), intervals(NULL) { RMDBGONCE(20, RMDebug::module_raslib, "r_Minterval", "r_Minterval(r_Dimension), this=" << (long)this) intervals = new r_Sinterval[ dimensionality ]; } void r_Minterval::constructorinit(char* mIntStr) throw(r_Eno_interval) { if(!mIntStr) { RMInit::logOut << "r_Minterval::r_Minterval(" << (mIntStr?mIntStr:"NULL") << ")" << endl; throw r_Eno_interval(); } char* p = NULL; // for counting ',' // for parsing the string std::istrstream str(mIntStr, strlen(mIntStr) + 1); char c = 0; r_Sinterval sint; r_Range b = 0; // bound for Sinterval if (intervals != NULL) { delete intervals; intervals = NULL; } // calculate dimensionality p = mIntStr; while(p = strchr(++p, ',')) dimensionality++; // allocate space for intervals intervals = new r_Sinterval[ dimensionality ]; // check for left bracket '[' str >> c; if (c != '[') { // error, should perhaps raise exception dimensionality = 0; delete[] intervals; intervals = NULL; RMInit::logOut << "r_Minterval::r_Minterval(" << mIntStr << "): the string doesn't have pattern [a:b,c:d]" << endl; throw r_Eno_interval(); } // for each dimension: get sinterval for (r_Dimension i=0; i> c; // test read first char if (c == '*') // low bound is '*' sint.set_low('*'); else // low bound must be a number { str.putback(c); str >> b; // read type r_Range if ( ! str ) // check for proper int recognition { RMInit::logOut << "minterval constructor failed on dim " << i << ", lo" << endl << flush; throw r_Eno_interval(); } sint.set_low(b); // store lo bound } // --- check for ':' between lower and upper bound ------- str >> c; if (c != ':') { // error dimensionality = 0; delete[] intervals; intervals = NULL; RMInit::logOut << "r_Minterval::r_Minterval(" << mIntStr << "): missing ':', string not like [a:b,c:d]" << endl; throw r_Eno_interval(); } // --- evaluate upper bound ------------------------------ str >> c; if (c == '*') sint.set_high('*'); else { str.putback(c); str >> b; if ( ! str ) { RMInit::logOut << "minterval constructor failed on dim " << i << ", hi" << endl << flush; throw r_Eno_interval(); } sint.set_high(b); } str >> c; // --- next dimension needs either ',' separator or ']' end tag if (i != dimensionality-1 && c != ',' || i == dimensionality-1 && c != ']') { dimensionality = 0; delete[] intervals; intervals = NULL; RMInit::logOut << "r_Minterval::r_Minterval(" << mIntStr << "): missing ',' or ']', string not like [a:b,c:d]" << endl; throw r_Eno_interval(); } intervals[i] = sint; sint.set_interval('*','*'); } } r_Minterval::r_Minterval(char* mIntStr) throw(r_Eno_interval) : dimensionality(1), streamInitCnt(0), intervals(NULL) { RMDBGONCE(20, RMDebug::module_raslib, "r_Minterval", "r_Minterval(char*), this=" << (long)this) constructorinit(mIntStr); } r_Minterval::r_Minterval(const char* mIntStr) throw(r_Eno_interval) : dimensionality(1), streamInitCnt(0), intervals(NULL) { RMDBGONCE(20, RMDebug::module_raslib, "r_Minterval", "r_Minterval(char*), this=" << (long)this) char* temp = (char*)mymalloc((1 + strlen(mIntStr)) * sizeof(char)); strcpy(temp, mIntStr); try { constructorinit(temp); free(temp); } catch(r_Error err) { free(temp); throw; } temp = 0; } r_Minterval& r_Minterval::operator<<(const r_Sinterval& newInterval) throw(r_Einit_overflow) { if (streamInitCnt >= dimensionality) { RMInit::logOut << "r_Minterval::operator<<(" << newInterval << ") domain is already full" << endl; throw r_Einit_overflow(); } intervals[streamInitCnt++] = newInterval; return *this; } r_Minterval& r_Minterval::operator<<(r_Range p) throw(r_Einit_overflow) { if (streamInitCnt >= dimensionality) { RMInit::logOut << "r_Minterval::operator<<(" << p << ") domain is already full" << endl; throw r_Einit_overflow(); } intervals[streamInitCnt++] = r_Sinterval(p, p); return *this; } r_Minterval::r_Minterval() : dimensionality(0), streamInitCnt(0), intervals(NULL) { RMDBGONCE(20, RMDebug::module_raslib, "r_Minterval", "r_Minterval(), this=" << this) } //cannot use the initialise function because it will crash r_Minterval::r_Minterval(const r_Minterval& minterval) : dimensionality(0), streamInitCnt(0), intervals(NULL) { RMDBGONCE(20, RMDebug::module_raslib, "r_Minterval", "r_Minterval(const r_Minterval&), this=" << this) dimensionality = minterval.dimensionality; streamInitCnt = minterval.streamInitCnt; if(minterval.intervals) { intervals = new r_Sinterval[dimensionality]; for (r_Dimension i=0; i= dimensionality) { RMInit::logOut << "r_Minterval:::operator[](" << i << ") const index out of bounds (" << dimensionality << ")" << endl; throw r_Eindex_violation(0, dimensionality-1, i); } return intervals[i]; } r_Sinterval& r_Minterval::operator[](r_Dimension i) { if (i < 0 || i >= dimensionality) { RMInit::logOut << "r_Minterval:::operator[](" << i << ") index out of bounds (" << dimensionality << ")" << endl; throw r_Eindex_violation(0, dimensionality-1, i); } return intervals[i]; } #endif const r_Minterval& r_Minterval::operator=(const r_Minterval& minterval) { if (this != &minterval) { if (intervals && dimensionality != minterval.dimension()) { delete[] intervals; intervals = NULL; } dimensionality = minterval.dimension(); streamInitCnt = minterval.streamInitCnt; if(minterval.intervals) { if (!intervals) intervals = new r_Sinterval[ dimensionality ]; for (r_Dimension i=0; i scaleVec; //create scale vector for (r_Dimension i = 0; i < dimensionality; i++){ scaleVec.push_back(d); } scale(scaleVec); return *this; } r_Minterval& r_Minterval::scale(const vector& scaleVec) throw(r_Eno_interval) { double high = 0., low = 0.; RMDBGENTER(1, RMDebug::module_raslib, "r_Minterval", "scale(" << scaleVec << ") before " << *this ); // if the size of scale vector is different from dimensionality, undefined behaviour if(scaleVec.size() != dimensionality) { RMDBGEXIT(1, RMDebug::module_raslib, "r_Minterval", "scale(" << scaleVec << ") scaleVec has wrong size " << *this ); throw r_Edim_mismatch(scaleVec.size(), dimensionality); } for (r_Dimension i = 0; i < dimensionality; i++) { // do explicit rounding, because the cast down in set_interval doesn't do the good rounding for negative values -- PB 2005-jun-19 low = floor( scaleVec[i] * intervals[i].low() ); //correction by 1e-6 to avoid the strage bug when high was a //integer value and floor return value-1(e.g. query 47.ql) high = floor(scaleVec[i] * (intervals[i].high() +1) + 0.000001) - 1; // FIXME BUG it was not forseen to be able to scale [a:a] with a very low factor f // to [af, af] // if((r_Range)high != (r_Range)low) // high--; // substract 1 which was added to high() intervals[i].set_interval((r_Range)low, (r_Range)high); } RMDBGEXIT(1, RMDebug::module_raslib, "r_Minterval", "scale(" << scaleVec << ") after " << *this ); return *this; } r_Minterval r_Minterval::create_scale(const double& d) const throw(r_Eno_interval) { r_Minterval result(*this); result.scale(d); return result; } r_Minterval r_Minterval::create_scale(const vector& scaleVec) const throw(r_Eno_interval) { r_Minterval result(*this); result.scale(scaleVec); return result; } r_Minterval& r_Minterval::union_of(const r_Minterval& mint1, const r_Minterval& mint2) throw(r_Edim_mismatch, r_Eno_interval) { if (mint1.dimension() != mint2.dimension()) { RMInit::logOut << "r_Minterval::union_of(" << mint1 << ", " << mint2 << ") dimensions do not match" << endl; throw(r_Edim_mismatch( mint1.dimension(), mint2.dimension())); } // cleanup + initializing of this if (dimensionality != mint1.dimension()) { if (intervals) delete[] intervals; dimensionality = mint1.dimension(); streamInitCnt = dimensionality; intervals = new r_Sinterval[ dimensionality ]; } for (r_Dimension i=0; i 0) { for (r_Dimension i=0; i intervals[i].high()) { RMInit::logOut << "r_Minterval::cell_offset(" << point << ") point is out of range (" << *this << ")" << endl; throw(r_Eindex_violation(point[i], intervals[i].low(), intervals[i].high())); } offset = (offset + point[i] - intervals[i].low()) * ptExt[i+1]; } // now i = dimensionality - 1 if (point[i] < intervals[i].low() || point[i] > intervals[i].high()) { RMInit::logOut << "r_Minterval::cell_offset(" << point << ") point is out of range (" << *this << ")" << endl; throw(r_Eindex_violation(point[i], intervals[i].low(), intervals[i].high())); } offset += point[i] - intervals[i].low(); return offset; } // Arguments.....: linear offset // Return value..: point object which corresponds to the linear offset of the argument // Description...: The method calucaltes the spatial domain coordinates as a point out of an offset specification. Lower dimensions are higher valued which means that the highest dimension is stored in a sequence. r_Point r_Minterval::cell_point(r_Area offset) const throw(r_Eno_cell, r_Error) { r_Dimension i; unsigned int factor=1; r_Point pt(dimensionality), ptExt; if (offset >= cell_count()) { RMInit::logOut << "r_Minterval::cell_point(" << offset << ") offset is out of range (" << cell_count() << ")" << endl; throw r_Eno_cell(); } ptExt=get_extent(); for (i=0; i= dimensionality) { RMInit::logOut << "r_Minterval::delete_dimension(" << dim << ") dimension is out of range (" << dimensionality << ")" << endl; throw r_Eindex_violation(0, dimensionality-1, dim); } dimensionality -= 1; streamInitCnt = dimensionality; r_Sinterval* newIntervals = new r_Sinterval[ dimensionality ]; for (r_Dimension i=0, j=0; i 0) sz += dimensionality * intervals->get_storage_size(); return sz; } bool r_Minterval::is_mergeable(const r_Minterval& b) const { bool is_merg = true; // An alias to this object const r_Minterval& a = *this; // The blocks must have the same dimensionality to be mergeable if (a.dimensionality != b.dimensionality) { is_merg = false; } else { // Count the number of adjacent frontiers int ones_differences = 0; // For all dimensions for (r_Dimension i=0; i& vec) { os << " Vector { "; int size = vec.size(); for (int i = 0; i < size; i++) os << vec[i] << std::endl; os << " } "; } std::ostream& operator<<(std::ostream& s, const vector& doubleVec) { vector::const_iterator iter, iterEnd; iter=doubleVec.begin(); iterEnd=doubleVec.end(); s << "{"; while(iter != iterEnd){ s << *iter; ++iter; if(iter != iterEnd) s << ", "; } s << "}"; return s; }