/*
* 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: dirtiling.cc
*
* MODULE: rasodmg
* CLASS: r_DirTiling
*
* COMMENTS:
* None
*/
#ifdef __VISUALC__
// Diable warning for signed/unsigned mismatch.
#pragma warning( disable : 4018 )
#endif
#include "rasodmg/dirtiling.hh"
#include "rasodmg/dirdecompose.hh"
#include "rasodmg/alignedtiling.hh"
#include "raslib/rminit.hh"
#include
#include
#include
#include
#ifdef AIX
#include
#endif
// Uncoment the _VISUALIZE_2D_DECOMP_ line to generate ppm files the
// visualization of the domain decomposition done by the algoritm
// #define _VISUALIZE_2D_DECOMP_
// Uncoment the folling line for some debug printfs on this class
// #define _DEBUG_DIRTILING_
#ifdef _DEBUG_DIRTILING_
#define DEBUG_DIR(msg) cout << "[" << __LINE__ << "] " << msg;
#else
#define DEBUG_DIR(msg)
#endif
#ifdef _VISUALIZE_2D_DECOMP_
#include "tools/visualtiling2d.hh"
#endif
const char*
r_Dir_Tiling::description = "dimensions, decomposision patterns, tile size(in bytes) and subtiling [SUBTILING|NOSUBTILING] (ex: \"3;[0,2,4,5],[*],[0,10,15];100;NOSUBTILING\")";
const char* r_Dir_Tiling::subtiling_name_withoutsubtiling = "NOSUBTILING";
const char* r_Dir_Tiling::subtiling_name_withsubtiling = "SUBTILING";
const char* r_Dir_Tiling::all_subtiling_names[r_Dir_Tiling::NUMBER]={
subtiling_name_withoutsubtiling,
subtiling_name_withsubtiling
};
r_Dir_Tiling::SubTiling
r_Dir_Tiling::get_subtiling_from_name(const char* name)
{
if(!name) {
RMInit::logOut << "r_Dir_Tiling::get_subtiling_from_name(" << (name?name:"NULL") << ")." << endl;
return r_Dir_Tiling::NUMBER;
}
unsigned int i=r_Dir_Tiling::NUMBER;
for (i=0; i<(unsigned int)r_Dir_Tiling::NUMBER; i++)
{
if (strcasecmp(name, all_subtiling_names[i]) == 0)
break;
}
return (r_Dir_Tiling::SubTiling)i;
}
const char*
r_Dir_Tiling::get_name_from_subtiling(SubTiling tsl)
{
static const char* unknown="UNKNOWN";
unsigned int idx = (unsigned int)tsl;
if (idx >= (unsigned int)r_Dir_Tiling::NUMBER)
return unknown;
return all_subtiling_names[idx];
}
r_Dir_Tiling::r_Dir_Tiling(const char* encoded) throw (r_Error)
: r_Dimension_Tiling(0, 0)
{
if(!encoded)
{
RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << (encoded?encoded: "NULL") << ")." << endl;
throw r_Error(TILINGPARAMETERNOTCORRECT);
}
r_Dimension tileD=0, dirIndex=0;
r_Range decomp=0;
std::vector vectDirDecomp;
r_Bytes tileS=0, lenToConvert=0, lenDirToConvert=0, lenDecomp=0;
r_Dir_Tiling::SubTiling subTiling;
const char *pStart=NULL, *pEnd=NULL, *pRes=NULL, *pTemp=NULL, *pToConvertEnd=NULL;
char* pToConvert=NULL;
const char *pDirRes=NULL, *pDirEnd=NULL, *pDirTemp=NULL, *pDirStart=NULL;
char* pDirToConvert=NULL;
char* pDecomp=NULL;
//initialisation
pStart=encoded;
pTemp=pStart;
pEnd=pTemp+strlen(pStart);
//deal with dimension
pRes=strstr(pTemp, TCOLON);
if(!pRes)
{
RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding tile dimension." << endl;
throw r_Error(TILINGPARAMETERNOTCORRECT);
}
lenToConvert=pRes-pTemp;
pToConvert=new char[lenToConvert+1];
memcpy(pToConvert, pTemp, lenToConvert);
pToConvert[lenToConvert]='\0';
tileD=strtol(pToConvert, (char**)NULL, DefaultBase);
if(!tileD)
{
RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding tile dimension \"" << pToConvert << "\" is not a number." << endl;
delete[] pToConvert;
throw r_Error(TILINGPARAMETERNOTCORRECT);
}
if(tileD<0)
{
RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding tile dimension \"" << pToConvert << "\" is negative." << endl;
delete[] pToConvert;
throw r_Error(TILINGPARAMETERNOTCORRECT);
}
vectDirDecomp=std::vector(tileD);
delete[] pToConvert;
if(pRes==(pEnd-1))
{
RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose, end of stream." << endl;
throw r_Error(TILINGPARAMETERNOTCORRECT);
}
else
pRes++;
pTemp=pRes;
//deal with directional decompose
pRes=strstr(pTemp, TCOLON);
if(!pRes)
{
RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose." << endl;
throw r_Error(TILINGPARAMETERNOTCORRECT);
}
lenToConvert=pRes-pTemp;
pToConvert=new char[lenToConvert+1];
memcpy(pToConvert, pTemp, lenToConvert);
pToConvert[lenToConvert]='\0';
pToConvertEnd=pToConvert+strlen(pToConvert);
pDirTemp=pToConvert;
while(dirIndex < tileD)
{
pDirRes=strstr(pDirTemp, LSQRBRA);
if(!pDirRes)
{
RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose for dimension " << dirIndex+1 << " from \"" << pToConvert << "\"." << endl;
delete[] pToConvert;
throw r_Error(TILINGPARAMETERNOTCORRECT);
}
pDirStart=pDirRes;
pDirRes=strstr(pDirTemp, RSQRBRA);
if(!pDirRes)
{
RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose for dimension " << dirIndex+1 << " from \"" << pToConvert << "\"." << endl;
delete[] pToConvert;
throw r_Error(TILINGPARAMETERNOTCORRECT);
}
pDirEnd=pDirRes;
lenDirToConvert=pDirEnd-pDirStart;
if(lenDirToConvert == 1)
{
RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose for dimension " << dirIndex+1 << " from \"" << pToConvert << "\"." << endl;
delete[] pToConvert;
throw r_Error(TILINGPARAMETERNOTCORRECT);
}
pDirToConvert=new char[lenDirToConvert];
memcpy(pDirToConvert, pDirStart+1, lenDirToConvert-1);
pDirToConvert[lenDirToConvert-1]='\0';
pDirTemp=pDirToConvert;
pDirStart=pDirEnd;
pDirEnd=pDirToConvert+strlen(pDirToConvert);
if(*pDirToConvert != *ASTERIX)
{
pDirRes=strstr(pDirToConvert, TCOMMA);
if(!pDirRes)
{
RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose for dimension " << dirIndex+1 << " from \"" << pToConvert << "\"." << endl;
delete[] pDirToConvert;
delete[] pToConvert;
throw r_Error(TILINGPARAMETERNOTCORRECT);
}
while(pDirRes)
{
lenDecomp=pDirRes-pDirTemp;
pDecomp=new char[lenDecomp+1];
memcpy(pDecomp, pDirTemp, lenDecomp);
pDecomp[lenDecomp]='\0';
decomp=strtoul(pDecomp, (char**)&pDirTemp, DefaultBase);
if(*pDirTemp !='\0')
{
RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding decompose \"" << pDecomp << "\" from directional decompose \"" << pDirToConvert << "\", is not a number." << endl;
delete[] pDecomp;
delete[] pDirToConvert;
delete[] pToConvert;
throw r_Error(TILINGPARAMETERNOTCORRECT);
}
vectDirDecomp[dirIndex] << decomp;
//skip COMMA & free buffer
delete[] pDecomp;
if(pDirRes==(pDirEnd-1))
{
RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose \"" << pDirToConvert << "\", end of stream." << endl;
delete[] pDirToConvert;
delete[] pToConvert;
throw r_Error(TILINGPARAMETERNOTCORRECT);
}
else
pDirRes++;
pDirTemp=pDirRes;
//next decomp
pDirRes=strstr(pDirTemp, TCOMMA);
if(!pDirRes)
{
decomp=strtoul(pDirTemp, (char**)&pDirRes, DefaultBase);
if(*pDirRes !='\0')
{
RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding decompose \"" << pDirTemp << "\" from directional decompose \"" << pDirToConvert << "\", is not a number." << endl;
delete[] pDirToConvert;
delete[] pToConvert;
throw r_Error(TILINGPARAMETERNOTCORRECT);
}
vectDirDecomp[dirIndex]<& decomp, r_Bytes ts, SubTiling sub) throw (r_Error)
: r_Dimension_Tiling(dims, ts),
dim_decomp(decomp),
sub_tile(sub)
{
if (dim_decomp.size() != dimension)
{
RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << dims << ", " << decomp << ", " << ts << ", " << sub << ") number of dimensions (" << dimension << ") does not match number of decomposition entries (" << decomp.size() << ")" << endl;
throw r_Edim_mismatch(dimension, dim_decomp.size());
}
}
r_Dir_Tiling::~r_Dir_Tiling()
{
}
r_Tiling_Scheme
r_Dir_Tiling::get_tiling_scheme() const
{
return r_DirectionalTiling;
}
r_Tiling* r_Dir_Tiling::clone() const
{
r_Tiling* copy = new r_Dir_Tiling(dimension, dim_decomp, tile_size, sub_tile);
return copy;
}
void r_Dir_Tiling::print_status(std::ostream& os) const
{
os << "r_Dir_Tiling[ ";
r_Dimension_Tiling::print_status(os);
os << " sub tiling = " << sub_tile << " decompose = { ";
for (r_Dimension i = 0; i < dim_decomp.size(); i++)
os << "dim #" << i << " : " << dim_decomp[i] << " ";
os << "} ";
}
std::vector*
r_Dir_Tiling::compute_tiles(const r_Minterval& domain, r_Bytes typelen) const throw (r_Error)
{
// Aux variable
r_Dimension i = 0;
// The result
std::vector* decomp_result = new std::vector();
// An alias to result
std::vector& result = *decomp_result;
std::vector temp_dim_decomp = dim_decomp;
// Check dims
if (dimension != domain.dimension())
{
delete decomp_result;
RMInit::logOut << "r_Dir_Tiling::compute_tiles(" << domain << ", " << typelen << ") dimensions of domain (" << domain.dimension() << ") do not match dimensions of tiling strategy (" << dimension << ")" << endl;
throw r_Edim_mismatch(dimension, domain.dimension());
}
// Undefined dims
bool* undef_dim = new bool[dimension];
// Count of undef dims
r_Dimension total_undef = 0;
// Check if limits ok
for (i = 0; i < dimension; i++)
{
// Restric defined
if (temp_dim_decomp[i].get_num_intervals() > 0)
{
undef_dim[i] = false;
r_Range lim1 = 0;
r_Range lim2 = 0;
lim1 = domain[i].high();
lim2 = temp_dim_decomp[i].get_partition(temp_dim_decomp[i].get_num_intervals() - 1);
if (lim1 != lim2)
{
delete[] undef_dim;
delete decomp_result;
RMInit::logOut << "r_Dir_Tiling::compute_tiles(" << domain << ", " << typelen << ") upper limit of domain (" << domain.dimension() << ") at dimension " << i << " (" << domain[i] << ") does not partition " << temp_dim_decomp[i].get_partition(temp_dim_decomp[i].get_num_intervals() - 1) << endl;
throw r_Elimits_mismatch(lim1, lim2);
}
lim1 = domain[i].low();
lim2 = temp_dim_decomp[i].get_partition(0);
if (lim1 != lim2)
{
delete[] undef_dim;
delete decomp_result;
RMInit::logOut << "r_Dir_Tiling::compute_tiles(" << domain << ", " << typelen << ") lower limit of domain (" << domain.dimension() << ") at dimension " << i << " (" << domain[i] << ") does not partition " << temp_dim_decomp[i].get_partition(0) << endl;
throw r_Elimits_mismatch(lim1, lim2);
}
}
else // Restric not defined
{
// Dim unspecified
undef_dim[i] = true;
total_undef++;
temp_dim_decomp[i] << domain[i].low() << domain[i].high();
}
}
// Create a counter for each dimension
r_Dimension* dim_counter = new r_Dimension[dimension];
memset(dim_counter, 0, sizeof(r_Dimension) * dimension);
#ifdef _VISUALIZE_2D_DECOMP_
// User wants a visual of the 2D decomp.
// Number of times a decomp has been made
static int count;
++count; // Update decomp count
Visual_Tiling_2D* vis;
if (dimension == 2)
{
// Create an object for visualization
char fname[80];
sprintf(fname, "2D_decomp_dir_%d.ppm", count);
vis = new Visual_Tiling_2D(domain, fname);
}
#endif
// Iterate over the all space
bool done = false;
while (!done)
{
// Determine tile coordinates
r_Minterval tile(dimension);
for (i = 0; i < dimension; i++)
{
r_Range origin = temp_dim_decomp[i].get_partition(dim_counter[i]);
if (dim_counter[i] != 0)
origin++;
r_Range limit = temp_dim_decomp[i].get_partition(dim_counter[i]+1);
tile << r_Sinterval(origin, limit);
}
// Do something with tile coordinates (decompose big object)
#ifdef _DEBUG_DIRTILING_
cout << "(DirTiling::compute_tiles(): Tile: " << tile << endl;
#endif
// Check if sub-tiling should be done and calculate edgesize
if ((tile.cell_count() * typelen > tile_size) && (sub_tile == WITH_SUBTILING))
{
// Create a specification for the partition
r_Minterval partition(dimension);
if (total_undef == 0)
{
// No unspecified dimensions --- create block cross sections
for (i=0; i