diff options
author | Constantin Jucovschi <cj@ubuntu.localdomain> | 2009-04-24 07:20:22 -0400 |
---|---|---|
committer | Constantin Jucovschi <cj@ubuntu.localdomain> | 2009-04-24 07:20:22 -0400 |
commit | 8f27e65bddd7d4b8515ce620fb485fdd78fcdf89 (patch) | |
tree | bd328a4dd4f92d32202241b5e3a7f36177792c5f /rasodmg/alignedtiling.cc | |
download | rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.tar.gz rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.tar.xz rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.zip |
Initial commitv8.0
Diffstat (limited to 'rasodmg/alignedtiling.cc')
-rw-r--r-- | rasodmg/alignedtiling.cc | 635 |
1 files changed, 635 insertions, 0 deletions
diff --git a/rasodmg/alignedtiling.cc b/rasodmg/alignedtiling.cc new file mode 100644 index 0000000..13313f4 --- /dev/null +++ b/rasodmg/alignedtiling.cc @@ -0,0 +1,635 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +/ +/** + * SOURCE: alignedtiling.cc + * + * MODULE: rasodmg + * CLASS: r_AlignedTiling, r_DefaultTiling + * + * COMMENTS: + * None +*/ + +#include <vector> +#include <math.h> +#include <cstring> +#include <cstdlib> + +#include "rasodmg/alignedtiling.hh" +#include "raslib/rmdebug.hh" +#include "raslib/rminit.hh" + +#ifdef __VISUALC__ +#include <strstrea.h> +#else +#include <strstream> +#endif + +const char* +r_Aligned_Tiling::description = "tile configuration or tile dimension and tile size (in bytes) (ex: \"[0:9,0:9];100\" or \"2;100\")"; + +r_Aligned_Tiling::r_Aligned_Tiling(const char* encoded) throw (r_Error) + : r_Dimension_Tiling(0, 0) + { + + if(!encoded) + { + RMInit::logOut << "r_Aligned_Tiling::r_Aligned_Tiling(" << (encoded?encoded: "NULL") << ")" << std::endl; + throw r_Error(TILINGPARAMETERNOTCORRECT); + } + + r_Bytes tileS=0, lenToConvert=0; + r_Minterval* tileConf=NULL; + r_Dimension tileD=0; + bool state=false; //false for "tileconf;tilesize", true for "tiledim,tilesize" + const char *pStart=NULL, *pRes=NULL, *pEnd=NULL; + char *pToConvert=NULL; + pStart=encoded; + pEnd=pStart+strlen(pStart); + pRes=strstr(pStart, COLON); + if(!pRes) + { + RMInit::logOut << "r_Aligned_Tiling::r_Aligned_Tiling(" << encoded << "): Error decoding tile configuration from tilingparams." << std::endl; + throw r_Error(TILINGPARAMETERNOTCORRECT); + } + + //deal with first param + lenToConvert=pRes-pStart; + pToConvert = new char[lenToConvert+1]; + memcpy(pToConvert,pStart,lenToConvert); + pToConvert[lenToConvert]='\0'; + + if(*pToConvert == *LSQRBRA) + { + try + { + tileConf=new r_Minterval(pToConvert); + } + catch(r_Error& err) + { + RMInit::logOut << "r_Aligned_Tiling::r_Aligned_Tiling(" << encoded << "): Error decoding tile configuration \"" << pToConvert << "\" from tileparams." << std::endl; + RMInit::logOut << "Error " << err.get_errorno() << " : " << err.what() << std::endl; + delete [] pToConvert; + throw r_Error(TILINGPARAMETERNOTCORRECT); + } + } + else + { + tileD=strtol(pToConvert, (char**)NULL, DefaultBase); + if (!tileD) + { + RMInit::logOut << "r_Aligned_Tiling::r_Aligned_Tiling(" << encoded << "): Error decoding tile dimension \"" << pToConvert << "\" from tileparams." << std::endl; + delete[] pToConvert; + throw r_Error(TILINGPARAMETERNOTCORRECT); + } + if (tileD < 0) + { + RMInit::logOut << "r_Aligned_Tiling::r_Aligned_Tiling(" << encoded << "): Error decoding tile dimension \"" << pToConvert << "\" from tileparams." << std::endl; + RMInit::logOut << "Dimension is negative." << std::endl; + delete[] pToConvert; + throw r_Error(TILINGPARAMETERNOTCORRECT); + } + } + + //skip COLON + delete[] pToConvert; + if(pRes != (pEnd-1)) + pRes++; + else + { + RMInit::logOut << "r_Aligned_Tiling::r_Aligned_Tiling(" << encoded << "): Error decoding tiling, end of stream." << std::endl; + throw r_Error(TILINGPARAMETERNOTCORRECT); + } + + //deal with second param + tileS=strtol(pRes,(char**) NULL, DefaultBase); + if (!tileS) + { + RMInit::logOut << "r_Aligned_Tiling::r_Aligned_Tiling(" << encoded << "): Error decoding tile size \"" << pRes << "\"." << std::endl; + + if(tileConf) + delete tileConf; + + throw r_Error(TILINGPARAMETERNOTCORRECT); + } + if (tileS < 0) + { + RMInit::logOut << "r_Aligned_Tiling::r_Aligned_Tiling(" << encoded << "): Error decoding tile size \"" << pRes << "\", is negative." << std::endl; + if(tileConf) + delete tileConf; + throw r_Error(TILINGPARAMETERNOTCORRECT); + } + + //detect state + if(tileConf) + { + tile_config = *tileConf; + dimension = tile_config.dimension(); + tile_size = tileS; + delete tileConf; + } + else + { + tile_config = r_Minterval(tileD); + dimension = tileD; + tile_size = tileS; + } + + } + +r_Aligned_Tiling::r_Aligned_Tiling(r_Dimension dim, r_Bytes ts) throw (r_Error) + : r_Dimension_Tiling(dim, ts), + tile_config(dim) +{ + /// Default tile configuration - equal sides + for(r_Dimension i = 0; i < dim ; i++) + tile_config << r_Sinterval((r_Range)0, (r_Range)1); +} + +r_Aligned_Tiling::r_Aligned_Tiling(const r_Minterval& tc, r_Bytes ts) throw (r_Error) + : r_Dimension_Tiling(tc.dimension(), ts), + tile_config(tc) +{ +} + +r_Tiling* +r_Aligned_Tiling::clone() const +{ + r_Aligned_Tiling* newAT = new r_Aligned_Tiling(tile_config, tile_size); + return newAT; +} + +r_Aligned_Tiling::~r_Aligned_Tiling() +{ + tile_config.r_deactivate(); +} + +const r_Minterval& +r_Aligned_Tiling::get_tile_config() const +{ + return tile_config; +} + +r_Minterval +r_Aligned_Tiling::compute_tile_domain(const r_Minterval& dom, r_Bytes cell_size) const +{ +RMDBGENTER(3, RMDebug::module_rasodmg, "r_Aligned_Tiling", "compute_tile_domain(" << dom << ", " << cell_size << ")") + // Minimum optimal tile size. Below this value, the waste will be too big. + r_Bytes optMinTileSize = get_min_opt_tile_size(); + + // number of cells per tile according to storage options + r_Area numCellsTile = tile_size / cell_size; + + // For final result. + r_Minterval tileDomain(dimension); + + int startIx = -1; + + for (r_Dimension i = 0; i < dimension ; i++) + { + if (tile_config[i].is_low_fixed() == 0 || + tile_config[i].is_high_fixed() == 0) + startIx = i; + } + if (startIx >= 0) // Some limits are nonfixed + { + unsigned long size = cell_size; + int i; + + for(i = startIx; i >=0 ; i--) // treat the non fixed limits first + { + r_Range l, h; + + // If any of the limits is non-fixed along this direction, tiles + // will extend from one side to the other along this direction. + if ((tile_config[i].is_low_fixed() == 0) || + (tile_config[i].is_high_fixed() == 0)) + { + + l = dom[i].low(); + h = dom[i].high(); + + /* + Alternative interpretation of tile_config with non fixed limits + For the time being is useless because the splittile algorithm + doesn't take into account the origin of the tile + if (tile_config[i].is_low_fixed() == 0) + l = contentsDomain[i].low(); + else + l = tile_config[i].low(); + if (tileconfig[i].is_high_fixed() == 0) + h = contentsDomain[i].high(); + else + h = tile_config[i].high(); + */ + + if(size * (h - l + 1) > tile_size) + { + h = tile_size/size + l - 1; + } + size = size * (h - l + 1); + tileDomain[i] = r_Sinterval(r_Range(l) ,r_Range(h)); + } + } + for(i = dimension-1; i >=0 ; i--) // treat fixed limits now + { + r_Range l, h; + + // If any of the limits is non-fixed along this direction, tiles + // will extend from one side to the other along this direction. + if ((tile_config[i].is_low_fixed() != 0) && + (tile_config[i].is_high_fixed() != 0)) + { + l = tile_config[i].low(); + h = tile_config[i].high(); + + if(size * (h - l + 1) > tile_size) + { + h = tile_size/size + l - 1; + } + size = size * (h - l + 1); + tileDomain[i] = r_Sinterval(r_Range(l) ,r_Range(h)); + } + } + + RMDBGEXIT(2, RMDebug::module_rasodmg, "r_Aligned_Tiling", "calculateTileDomain result : " << tileDomain <<std::endl) + return tileDomain; + } + else // tile_config has only fixed limits + { + unsigned long numCellsTileConfig = tile_config.cell_count(); + unsigned long sizeTileConfig = numCellsTileConfig * cell_size; + + if (sizeTileConfig > get_min_opt_tile_size() && sizeTileConfig < tile_size) + { + RMDBGEXIT(2, RMDebug::module_rasodmg, "r_Aligned_Tiling", "calculateTileDomain result : " << tile_config) + return tile_config; + } + else + { + float sizeFactor = (float) numCellsTile / numCellsTileConfig; + + float f = float (1/ float(dimension)); + float dimFactor = (float)pow(sizeFactor, f); + RMDBGMIDDLE(2, RMDebug::module_rasodmg, "r_Aligned_Tiling", "dim factor == " << dimFactor) + + unsigned long l, h; + unsigned long newWidth; + + // extending the bound of each r_Sinterval of tile_config by + // using the factor dimFactor + for (int i = 0; i < dimension ; i++) + { + l = tile_config[i].low(); + h = tile_config[i].high(); + newWidth = (unsigned long) ((h - l + 1) * dimFactor); + if (newWidth < 1) newWidth = 1; + tileDomain << r_Sinterval(r_Range(l), r_Range(l + newWidth - 1)); + } + + // Approximate the resulting tile size to the target one: + + /* + r_Minterval tmpTileDomain = + get_opt_size(tileDomain, cell_size); + tileDomain = tmpTileDomain; + */ + +/* + unsigned long sz = tileDomain.cell_count() * cell_size; + + RMDBGOUT(2,"cell_size " << cell_size << " tileDomain "<< tileDomain << std::endl) + RMDBGOUT(2,"cell_count == " << tileDomain.cell_count() << " sz == " << sz << std::endl) + + unsigned long newSz = sz; + for(i = dimension-1; i >= 0 && newSz < tile_size ; i--) + { + RMDBGOUT(2, "inside the cycle " << std::endl) + unsigned long deltaSz = cell_size; + for (int j = 0 ; j < dimension ; j++) + if (j != i) + deltaSz *= (tileDomain[j].high()-tileDomain[j].low()+1); + + h = tileDomain[i].high(); + if (deltaSz + newSz <= tile_size) + { + tileDomain[i].set_high(r_Range(h + 1)); + newSz += deltaSz; + } + } +*/ + + if (tileDomain.cell_count() * cell_size > tile_size) + RMDBGMIDDLE(2, RMDebug::module_rasodmg, "Error in r_Aligned_Tiling", "calculateTileDomain() " << std::endl); + if (tileDomain.cell_count() * cell_size < optMinTileSize) + RMDBGMIDDLE(2, RMDebug::module_rasodmg, "r_Aligned_Tiling", "calculateTileDomain() result non optimal " << std::endl); + + RMDBGEXIT(2, RMDebug::module_rasodmg, "r_Aligned_Tiling", "calculateTileDomain result : " << tileDomain << std::endl) + // cout << "return 3"<<std::endl; + return tileDomain; + } + } +} + +std::vector<r_Minterval>* +r_Aligned_Tiling::compute_tiles(const r_Minterval& obj_domain, r_Bytes cell_size) const throw (r_Error) +{ + std::vector<r_Minterval>* result = new std::vector<r_Minterval>; + + r_Dimension dim = tile_config.dimension(); + + r_Minterval bigDom = obj_domain; + + r_Minterval tileDom = compute_tile_domain(obj_domain, cell_size); + + // cout << "r_Aligned_Tiling::compute_tiles() " << tileDom << std::endl; + + r_Minterval currDom(tileDom.dimension()); + r_Point cursor(tileDom.dimension()); + r_Point tileSize; + r_Point origin; + int done = 0; + + // initialize cursor + for(dim = 0; dim < cursor.dimension(); dim++) + cursor[dim] = 0; + + // calculate size of Tiles + tileSize = tileDom.get_extent(); + + // origin of bigTile + origin = bigDom.get_origin(); + + // initialize currDom + for(dim=0; dim < cursor.dimension(); dim++) + currDom << r_Sinterval((r_Range) (origin[dim]), (r_Range) (origin[dim] + tileSize[dim] - 1)); + // resets tileDom to lower left side of bigTile + tileDom = currDom; + + // intersect with bigTile + currDom.intersection_with(bigDom); + + // iterate with smallTile over bigTile + while(!done) + { + currDom.intersection_with(bigDom); + + // create new smallTile + r_Minterval smallTile(dim); + + smallTile = currDom; + + // insert tile in set + result->push_back(smallTile); + + // increment cursor, start with highest dimension + long i = cursor.dimension() - 1; + cursor[(unsigned int)i] += tileSize[(unsigned int)i]; + // move cursor + currDom = tileDom.create_translation(cursor); + while(!(currDom.intersects_with(bigDom))) + { + cursor[(unsigned int)i] = 0; + i--; + if(i < 0) + { + done = 1; + break; + } + cursor[(unsigned int)i] += tileSize[(unsigned int)i]; + // move cursor + currDom = tileDom.create_translation(cursor); + } + } + return result; +} + +r_Minterval +r_Aligned_Tiling::get_opt_size(const r_Minterval& tileDomain, r_Bytes cellSize) const +{ + + unsigned long tileSize = get_tile_size(); + unsigned long newSize = tileDomain.cell_count() * cellSize; + r_Minterval result = tileDomain; + r_Dimension dim = tileDomain.dimension(); + int* ixArr = new int[dim]; + int* tmpIxArr = new int[dim]; + r_Minterval tmpResult = result; + int j; + + for (j = 0; j < dim; j++) + ixArr[j] = j; + + for(j = dim - 1; j >=0 && newSize < tileSize ; j--) + { + int i=0; + unsigned long h, wd; + unsigned minWidthIx = 0; + unsigned long minWidth = tileDomain[0].high()-tileDomain[0].low()+1; + for(int k = j; k >=0 ; k--) + { + i = ixArr[k]; + + h = result[i].high() + 1; + wd = result[i].high() - result[i].low() + 1; + if (wd < minWidth) + { + minWidth = wd; + minWidthIx = i; + } + } + + int tmpIx = ixArr[j]; + ixArr[minWidthIx] = tmpIx; + + tmpResult[minWidthIx].set_high(r_Range(h)); + newSize = tmpResult.cell_count() * cellSize; + if (newSize > tileSize) + { + for(i = dim-1; i >=0 ; i--) + { + h = result[i].high() + 1; + wd = result[i].high() - result[i].low() + 1; + if (wd < minWidth) + { + minWidth = wd; + minWidthIx = i; + } + } + } + + result[minWidthIx].set_high(r_Range(h)); + newSize = result.cell_count() * cellSize; + if (newSize > tileSize) + { + result[minWidthIx].set_high(r_Range(h - 1)); + } + } + delete[] ixArr; + return result; +} + +r_Tiling_Scheme +r_Aligned_Tiling::get_tiling_scheme() const +{ + return r_AlignedTiling; +} + +r_Bytes +r_Aligned_Tiling::get_min_opt_tile_size() const +{ + return (get_tile_size() - get_tile_size()/10); +} + +char* +r_Aligned_Tiling::get_string_representation() const +{ + + unsigned int bufferSize = 25; // should be enough! + + // allocate buffer and initialize string stream + char* buffer = new char[bufferSize]; + std::ostrstream domainStream(buffer, bufferSize); + + // write into string stream + + print_status(domainStream); + domainStream << std::ends; + + // allocate memory taking the final string + char* returnString = strdup(buffer); + + // delete buffer + delete[] buffer; + + return returnString; +} + +void +r_Aligned_Tiling::print_status(std::ostream& os) const +{ + os << "r_Aligned_Tiling[ "; + r_Dimension_Tiling::print_status(os); + os << " tile configuration = "<< tile_config <<" ]"; +} + +/* +std::ostream& +operator<<(std::ostream& s, const r_Aligned_Tiling& at) +{ + at.print_status(s); + return s; +} +*/ + +/* +std::vector<r_Minterval>* +r_Default_Tiling::compute_tiles(const r_Minterval& obj_domain, long cell_size) + const +{ + std::vector<r_Minterval>* result = new std::vector<r_Minterval>; + + RMDBGENTER(4, RMDebug::module_rasodmg, "r_Default_Tiling", "compute_tiles") + + + r_Minterval bigDom = obj_domain; + + r_Minterval tileDom(bigDom.dimension()); + + // compute the domain of the small tiles + // tiles are n-dimensional cubes with edge length n-th root of max tile size + //old implementations: + //long edgeLength = (long)floor(exp((1/(double)tileDom.dimension())* + // log(RMInit::tileSize/mar->get_type_length()))); + //long edgeLength = (long)floor(exp((1/(double)tileDom.dimension())* + // log(get_tile_size()/cell_size))); + + RMDBGMIDDLE(4, RMDebug::module_rasodmg, "r_Default_Tiling", "tile size == " << get_tile_size()) + long edgeLength = (long) floor(pow(get_tile_size()/cell_size, + 1/(double)tileDom.dimension())); + r_Dimension dim; + + for(dim=0; dim<tileDom.dimension(); dim++) + tileDom << r_Sinterval((r_Range)0, (r_Range)edgeLength-1); + + r_Minterval currDom(tileDom.dimension()); + r_Point cursor(tileDom.dimension()); + r_Point tileSize; + r_Point origin; + int done = 0; + + // initialize cursor + for(dim = 0; dim < cursor.dimension(); dim++) + cursor[dim] = 0; + + // calculate size of Tiles + tileSize = tileDom.get_extent(); + + // origin of bigTile + origin = bigDom.get_origin(); + + // initialize currDom + for(dim=0; dim < cursor.dimension(); dim++) + currDom << r_Sinterval((r_Range) (origin[dim]), (r_Range) (origin[dim] + tileSize[dim] - 1)); + // resets tileDom to lower left side of bigTile + tileDom = currDom; + + // intersect with bigTile + currDom.intersection_with(bigDom); + + // iterate with smallTile over bigTile + while(!done) + { + currDom.intersection_with(bigDom); + + // create new smallTile + r_Minterval smallTile(dim); + + smallTile = currDom; + + // insert tile in set + result->push_back(smallTile); + + // increment cursor, start with highest dimension + long i = cursor.dimension() - 1; + cursor[(unsigned int)i] += tileSize[(unsigned int)i]; + // move cursor + currDom = tileDom.create_translation(cursor); + while(!(currDom.intersects_with(bigDom))) + { + cursor[(unsigned int)i] = 0; + i--; + if(i < 0) + { + done = 1; + break; + } + cursor[(unsigned int)i] += tileSize[(unsigned int)i]; + // move cursor + currDom = tileDom.create_translation(cursor); + } + } + RMDBGEXIT(4, RMDebug::module_rasodmg, "r_Default_Tiling", "compute_tiles") + return result; +} +*/ |