summaryrefslogtreecommitdiffstats
path: root/rasodmg
diff options
context:
space:
mode:
authorConstantin Jucovschi <cj@ubuntu.localdomain>2009-04-24 07:20:22 -0400
committerConstantin Jucovschi <cj@ubuntu.localdomain>2009-04-24 07:20:22 -0400
commit8f27e65bddd7d4b8515ce620fb485fdd78fcdf89 (patch)
treebd328a4dd4f92d32202241b5e3a7f36177792c5f /rasodmg
downloadrasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.zip
rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.tar.gz
rasdaman-upstream-8f27e65bddd7d4b8515ce620fb485fdd78fcdf89.tar.xz
Initial commitv8.0
Diffstat (limited to 'rasodmg')
-rw-r--r--rasodmg/Makefile.am58
-rw-r--r--rasodmg/alignedtiling.cc635
-rw-r--r--rasodmg/alignedtiling.hh211
-rw-r--r--rasodmg/alignedtiling.icc31
-rw-r--r--rasodmg/collection.cc627
-rw-r--r--rasodmg/collection.hh224
-rw-r--r--rasodmg/collection.icc73
-rw-r--r--rasodmg/database.cc475
-rw-r--r--rasodmg/database.hh270
-rw-r--r--rasodmg/database.icc38
-rw-r--r--rasodmg/dirdecompose.cc147
-rw-r--r--rasodmg/dirdecompose.hh114
-rw-r--r--rasodmg/dirtiling.cc682
-rw-r--r--rasodmg/dirtiling.hh133
-rw-r--r--rasodmg/gmarray.cc484
-rw-r--r--rasodmg/gmarray.hh185
-rw-r--r--rasodmg/gmarray.icc119
-rw-r--r--rasodmg/interesttiling.cc809
-rw-r--r--rasodmg/interesttiling.hh183
-rw-r--r--rasodmg/iterator.cc216
-rw-r--r--rasodmg/iterator.hh137
-rw-r--r--rasodmg/iterator.icc39
-rw-r--r--rasodmg/marray.cc354
-rw-r--r--rasodmg/marray.hh145
-rw-r--r--rasodmg/marray.icc31
-rw-r--r--rasodmg/object.cc603
-rw-r--r--rasodmg/object.hh240
-rw-r--r--rasodmg/object.icc151
-rw-r--r--rasodmg/oqlquery.cc628
-rw-r--r--rasodmg/oqlquery.hh251
-rw-r--r--rasodmg/oqlquery.icc52
-rw-r--r--rasodmg/partinsert.cc199
-rw-r--r--rasodmg/partinsert.hh109
-rw-r--r--rasodmg/polycutout.cc709
-rw-r--r--rasodmg/polycutout.hh162
-rw-r--r--rasodmg/polygon.cc879
-rw-r--r--rasodmg/polygon.hh287
-rw-r--r--rasodmg/ref.cc656
-rw-r--r--rasodmg/ref.hh323
-rw-r--r--rasodmg/ref.icc64
-rw-r--r--rasodmg/set.cc92
-rw-r--r--rasodmg/set.hh79
-rw-r--r--rasodmg/stattiling.cc678
-rw-r--r--rasodmg/stattiling.hh210
-rw-r--r--rasodmg/storagelayout.cc182
-rw-r--r--rasodmg/storagelayout.hh132
-rw-r--r--rasodmg/storagelayout.icc31
-rw-r--r--rasodmg/test/Makefile372
-rw-r--r--rasodmg/test/Makefile.dep0
-rw-r--r--rasodmg/test/cmov_16.ql425
-rw-r--r--rasodmg/test/cmov_32.ql425
-rw-r--r--rasodmg/test/cmov_64.ql425
-rw-r--r--rasodmg/test/croll_16.ql180
-rw-r--r--rasodmg/test/croll_32.ql180
-rw-r--r--rasodmg/test/croll_64.ql180
-rw-r--r--rasodmg/test/croll_sliced.ql180
-rw-r--r--rasodmg/test/csel_16.ql43
-rw-r--r--rasodmg/test/csel_32.ql43
-rw-r--r--rasodmg/test/csel_64.ql43
-rw-r--r--rasodmg/test/csel_sliced.ql43
-rw-r--r--rasodmg/test/defconv.cc598
-rw-r--r--rasodmg/test/defdiff.cc537
-rw-r--r--rasodmg/test/defutil.hh412
-rw-r--r--rasodmg/test/deletecollection.cc720
-rw-r--r--rasodmg/test/earth.ql68
-rw-r--r--rasodmg/test/earth_16.ql41
-rw-r--r--rasodmg/test/earth_32.ql41
-rw-r--r--rasodmg/test/earth_64.ql41
-rw-r--r--rasodmg/test/gen_pattern.cc248
-rw-r--r--rasodmg/test/gen_query.pl116
-rw-r--r--rasodmg/test/gen_rollup.pl209
-rw-r--r--rasodmg/test/gen_s2k.pl65
-rw-r--r--rasodmg/test/init_fast_collection.pl111
-rw-r--r--rasodmg/test/polytest.poly3
-rw-r--r--rasodmg/test/rasql.cc126
-rw-r--r--rasodmg/test/rasql.hh38
-rw-r--r--rasodmg/test/readln.cc64
-rw-r--r--rasodmg/test/readln.hh45
-rw-r--r--rasodmg/test/runbm.sh94
-rw-r--r--rasodmg/test/small_16.ql42
-rw-r--r--rasodmg/test/small_32.ql42
-rw-r--r--rasodmg/test/small_64.ql42
-rw-r--r--rasodmg/test/stat1.dat3
-rw-r--r--rasodmg/test/stat2.dat7
-rw-r--r--rasodmg/test/stat3.dat4
-rw-r--r--rasodmg/test/system_basic.cc1945
-rw-r--r--rasodmg/test/system_basic.hh210
-rw-r--r--rasodmg/test/system_compare.cc273
-rw-r--r--rasodmg/test/system_compare.hh40
-rw-r--r--rasodmg/test/system_insert.cc384
-rw-r--r--rasodmg/test/system_insert.hh43
-rw-r--r--rasodmg/test/system_query.cc400
-rw-r--r--rasodmg/test/system_query.hh37
-rw-r--r--rasodmg/test/system_update.cc399
-rw-r--r--rasodmg/test/system_update.hh40
-rw-r--r--rasodmg/test/test_alignedtiling.cc126
-rw-r--r--rasodmg/test/test_all.sh9
-rw-r--r--rasodmg/test/test_benchmark.cc273
-rw-r--r--rasodmg/test/test_bmark_dir.cc257
-rw-r--r--rasodmg/test/test_bmark_dir1.cc318
-rw-r--r--rasodmg/test/test_bmark_int.cc241
-rw-r--r--rasodmg/test/test_bmark_int1.cc242
-rw-r--r--rasodmg/test/test_bmark_pet.cc235
-rw-r--r--rasodmg/test/test_bmark_stat.cc331
-rw-r--r--rasodmg/test/test_breakdown.cc112
-rw-r--r--rasodmg/test/test_collection.cc116
-rw-r--r--rasodmg/test/test_comp_conv.sh325
-rw-r--r--rasodmg/test/test_db2blob.sqC399
-rw-r--r--rasodmg/test/test_dirtiling.cc93
-rw-r--r--rasodmg/test/test_fastscale.cc293
-rw-r--r--rasodmg/test/test_gmarray.cc229
-rw-r--r--rasodmg/test/test_insert.cc235
-rw-r--r--rasodmg/test/test_insert3.cc843
-rw-r--r--rasodmg/test/test_interesttiling.cc97
-rw-r--r--rasodmg/test/test_iterator.cc135
-rw-r--r--rasodmg/test/test_lookup.cc378
-rw-r--r--rasodmg/test/test_marray.cc110
-rw-r--r--rasodmg/test/test_oqlquery.cc157
-rw-r--r--rasodmg/test/test_polygon.cc951
-rw-r--r--rasodmg/test/test_query.cc693
-rw-r--r--rasodmg/test/test_ref.cc69
-rw-r--r--rasodmg/test/test_set.cc104
-rw-r--r--rasodmg/test/test_stattiling.cc173
-rw-r--r--rasodmg/test/test_storage.cc282
-rw-r--r--rasodmg/test/test_transaction.cc152
-rw-r--r--rasodmg/test/tmov_16.ql425
-rw-r--r--rasodmg/test/tmov_32.ql425
-rw-r--r--rasodmg/test/tmov_64.ql425
-rw-r--r--rasodmg/test/tomo_ops.ql27
-rw-r--r--rasodmg/test/tomo_select.ql72
-rw-r--r--rasodmg/test/troll_16.ql180
-rw-r--r--rasodmg/test/troll_32.ql180
-rw-r--r--rasodmg/test/troll_64.ql180
-rw-r--r--rasodmg/test/troll_sliced.ql180
-rw-r--r--rasodmg/test/tsel_16.ql43
-rw-r--r--rasodmg/test/tsel_32.ql43
-rw-r--r--rasodmg/test/tsel_64.ql43
-rw-r--r--rasodmg/test/tsel_sliced.ql43
-rw-r--r--rasodmg/tiling.cc309
-rw-r--r--rasodmg/tiling.hh228
-rw-r--r--rasodmg/transaction.cc377
-rw-r--r--rasodmg/transaction.hh167
-rw-r--r--rasodmg/transaction.icc46
143 files changed, 34535 insertions, 0 deletions
diff --git a/rasodmg/Makefile.am b/rasodmg/Makefile.am
new file mode 100644
index 0000000..a2da39c
--- /dev/null
+++ b/rasodmg/Makefile.am
@@ -0,0 +1,58 @@
+# -*-Makefile-*- (for Emacs)
+#
+# 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>.
+#
+# MAKEFILE FOR:
+# module rasodmg
+#
+# COMMENTS:
+#
+##################################################################
+
+AM_CXXFLAGS=@CLIENTCXXFLAGS@
+AM_LDFLAGS=@CLIENTLDFLAGS@
+
+noinst_LIBRARIES=librasodmg.a
+
+librasodmg_a_SOURCES = collection.cc collection.hh collection.icc \
+ set.cc set.hh \
+ iterator.cc iterator.hh iterator.icc \
+ marray.cc marray.hh marray.icc \
+ ref.cc ref.hh ref.icc \
+ transaction.cc transaction.hh transaction.icc \
+ oqlquery.cc oqlquery.hh oqlquery.icc \
+ object.cc object.hh object.icc \
+ database.cc database.hh database.icc \
+ gmarray.cc gmarray.hh gmarray.icc \
+ storagelayout.cc storagelayout.hh storagelayout.icc \
+ tiling.cc tiling.hh \
+ alignedtiling.cc alignedtiling.hh alignedtiling.icc \
+ dirtiling.cc dirtiling.hh \
+ dirdecompose.cc dirdecompose.hh \
+ interesttiling.cc interesttiling.hh \
+ stattiling.cc stattiling.hh \
+ partinsert.cc partinsert.hh \
+ polygon.cc polygon.hh \
+ polycutout.cc polycutout.hh
+
+CLEANFILES = core
+
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;
+}
+*/
diff --git a/rasodmg/alignedtiling.hh b/rasodmg/alignedtiling.hh
new file mode 100644
index 0000000..ba8c2a4
--- /dev/null
+++ b/rasodmg/alignedtiling.hh
@@ -0,0 +1,211 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: alignedtiling.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Aligned_Tiling, r_Default_Tiling
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_ALIGNEDTILING_HH_
+#define _R_ALIGNEDTILING_HH_
+
+class r_Aligned_Tiling;
+
+#include "rasodmg/tiling.hh"
+#include "raslib/minterval.hh"
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ The {\tt r_Aligned_Tiling} class is used to express the options
+ for aligned tiling of {\tt r_Marray} objects.
+
+ The following options may be set:
+
+ \begin{itemize}
+ \item {\bf Tile configuration}
+
+ describes which format tiles should have. The tile configuration
+ is expressed using a multidimensional interval {\tt r_Minterval}.
+ This interval should have null lower limits and
+ must have the same dimensionality as that of the
+ objects to which it is to be applied. Its lengths along each
+ direction are interpreted relative to the others.
+
+ For example, if tile configuration is {\tt[ 0:9, 0:9, 0:19]}, tiles
+ will be three dimensional arrays with two sides of equal length and
+ double that length along the third direction.
+
+ If a fixed tile is required, tile configuration and
+ tile size should be set in such a way that the size of a tile
+ with the given configuration is equal to the specified tile size.
+ For example, if the tile configuration is {\tt [ 0:29, 0:39, 0:59]}
+ and cell size is 2, then the tile size should be set to
+ 144000. This will also result in more efficient computation of
+ the tiling since the given tile configuration is used unchanged if
+
+ {\tt 90% * tile_size < size of tile_config < tile_size}
+
+ (i.e., no computation is necessary). This applies equally to tile
+ configurations with non-fixed limits.
+
+ Tiles with non-fixed limits are used to express preferential
+ directions for tiling. For example, {\tt [ 0:9 , 0:* ]} expresses that
+ tiles should be done along the first direction, i.e., they
+ should have domains :
+
+ \begin{verbatim}
+ [ 0 : 9 , 0 : marray.domain[1].high() ]
+ [ 10 : 19 , 0 : marray.domain[1].high() ]
+ ...
+ \end{verbatim}
+
+ assuming this results in a tile with the given tile size. If not,
+ the limits in the first direction are changed. The higher dimensions
+ are given preference in that tiles will be preferably
+ extended along a higher dimension than a lower one if two or
+ more limits are open.
+
+ The default configuration corresponds to an interval with equal
+ lengths along all directions.
+
+ \item {\bf Tile size }
+
+ describes the size for tiles of the object in characters.
+ Tiling is done so that tiles are as big as possible but wit a
+ smaller size than this one.
+ The default tile size is the size specified for the RasDaMan client.
+
+ Notice: the tiling options are invalid if the rasdaman client is running
+ with the option notiling. In that case, no tiling is done,
+ independently of the storage layout chosen.
+*/
+
+class r_Aligned_Tiling : public r_Dimension_Tiling
+{
+ public:
+ /// read everything from encoded string
+ /// (e.g. "[0:9,0:9];100" or "2;100")
+ r_Aligned_Tiling(const char* encoded) throw (r_Error);
+
+ /// dimension and tile size.
+ r_Aligned_Tiling(r_Dimension dim, r_Bytes ts = RMInit::clientTileSize) throw (r_Error);
+
+ /// dimension and tile size will be taken from RMInit::clientTileSize.
+ //r_Aligned_Tiling(r_Dimension dim) throw (r_Error);
+
+ /// tile configuration and tile size.
+ r_Aligned_Tiling(const r_Minterval& tc, r_Bytes ts = RMInit::clientTileSize) throw (r_Error);
+
+ virtual r_Tiling* clone() const;
+
+ virtual ~r_Aligned_Tiling();
+
+ /// returns the current value for the tile configuration option
+ const r_Minterval& get_tile_config() const;
+
+ std::vector<r_Minterval>* compute_tiles(const r_Minterval& obj_domain, r_Bytes cell_size) const throw (r_Error);
+
+ char* get_string_representation() const;
+ /**
+ The string representation delivered by this method is allocated using
+ {\tt malloc()} and has to be freed using {\tt free()} in the end.
+ */
+
+ /// writes the state of the object to the specified stream
+ void print_status(std::ostream& s = cout) const;
+
+ virtual r_Tiling_Scheme get_tiling_scheme() const;
+
+ static const char* description;
+
+ protected:
+
+ /// determines the individual tiles domains
+ r_Minterval compute_tile_domain(const r_Minterval& dom, r_Bytes cell_size) const;
+ /**
+ Determines the individual tiles domains for aligned tiling,
+ using the options expressed in this object.
+ Takes into account the tile size and the tile configuration,
+ as well as the cell size given by {\ttcell_size}.
+
+ Returns the domain for tiles in such a way that the tile
+ configuration is as close to {\tttile_config} set in this object and
+ the size is lower than {\tt tile_size}.
+
+ The origin of the returned interval is the same as that from
+ {\ttthis->tile_config}.
+
+ The data to partition has domain {\tt dom } and cells with size
+ {\tt cell_size}.
+ To be used before splitting a tile with domain {\tt dom} (typically,
+ containing all the cells belonging to an {\ttr_Marray} object).
+ */
+
+ /// tile configuration
+ r_Minterval tile_config;
+
+ ///
+ r_Bytes get_min_opt_tile_size() const;
+
+ ///
+ r_Minterval get_opt_size(const r_Minterval& tile_domain, r_Bytes cell_size) const;
+};
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ The {\tt r_Default_Tiling} class is used to express the default tiling
+ of {\tt r_Marray} objects. According to this algorithm, tiles are divided
+ into equal sized multidimensional blocks qith equal lengths along
+ all directions of the spatial domain.
+
+ The following parameter may be set:
+
+ \item {\bf Tile size }
+
+ describes the size for tiles of the object in characters.
+ Tiling is done so that tiles have a smaller size than this one.
+ The default tile size is the size specified for the RasDaMan client.
+ In bytes.
+*/
+
+
+//@ManMemo: Module: {\bf rasodmg }
+/**
+ Output stream operator for objects of type {\tt const}
+ \Ref{r_Aligned_Tiling}.
+*/
+//extern std::ostream& operator<<(std::ostream& s, const r_Aligned_Tiling& at);
+
+#endif
+
+
+
+
diff --git a/rasodmg/alignedtiling.icc b/rasodmg/alignedtiling.icc
new file mode 100644
index 0000000..6abeb23
--- /dev/null
+++ b/rasodmg/alignedtiling.icc
@@ -0,0 +1,31 @@
+/*
+* 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>.
+/
+/**
+ * INLINE SOURCE: storage.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Storage
+ *
+ * COMMENTS:
+ * None
+*/
diff --git a/rasodmg/collection.cc b/rasodmg/collection.cc
new file mode 100644
index 0000000..c5da7de
--- /dev/null
+++ b/rasodmg/collection.cc
@@ -0,0 +1,627 @@
+/*
+* 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: collection.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Collection
+ *
+ * COMMENTS:
+ * None
+*/
+
+using namespace std;
+
+static const char rcsidcollection[] = "@(#)rasodmg, r_Collection: $Id: collection.cc,v 1.53 2005/07/06 23:30:22 rasdev Exp $";
+
+#include "raslib/rmdebug.hh"
+#include "raslib/collectiontype.hh"
+
+#include "rasodmg/collection.hh"
+#include "rasodmg/iterator.hh"
+#include "rasodmg/database.hh"
+
+#include "clientcomm/clientcomm.hh"
+#include <string.h>
+
+#ifndef __GNUG__
+#define NULL 0
+#endif
+
+template<class T>
+r_Collection<T>::r_Collection() throw(r_Error)
+ : r_Object( 2 ), card(0)
+{
+ init_node_list( coll );
+ init_node_list( removed_objects );
+}
+
+
+template<class T>
+r_Collection<T>::r_Collection( const r_Collection<T>& collection ) throw(r_Error)
+ : r_Object( collection, 2 )
+{
+ CNode* nptr;
+ CNode* optr;
+
+ coll = new CNode;
+ nptr = coll;
+ optr = collection.coll;
+
+ while ( optr->next != NULL )
+ {
+ nptr->next = new CNode;
+ nptr->elem = new T;
+ *(nptr->elem) = *(optr->elem);
+ nptr = nptr->next;
+ optr = optr->next;
+ }
+ if ( optr->elem != NULL )
+ {
+ nptr->elem = new T;
+ *(nptr->elem) = *(optr->elem);
+ }
+
+ nptr->next = NULL;
+ card = collection.cardinality();
+
+ init_node_list( removed_objects );
+}
+
+template<class T>
+r_Collection<T>::r_Collection( const void* node1 )
+{
+ // This constructor is nearly the same as a copy constrctor,
+ // except that the argument is not of type r_Collection but
+ // of type CNode* (the collection's internal representation).
+ // Does the same as function set_internal_representation.
+
+ // We assume that node1 is a correct CNode structure as
+ // defined in collection.hh
+ // copy it and determine cardinality
+ CNode* nptr;
+ CNode* optr;
+
+ card = 0;
+ coll = new CNode;
+ nptr = coll;
+ optr = (CNode*)node1;
+
+ while ( optr->next != NULL )
+ {
+ nptr->next = new CNode;
+ nptr->elem = new T;
+ card++;
+ *(nptr->elem) = *(optr->elem);
+ nptr = nptr->next;
+ optr = optr->next;
+ }
+ if ( optr->elem != NULL )
+ {
+ nptr->elem = new T;
+ card++;
+ *(nptr->elem) = *(optr->elem);
+ }
+
+ nptr->next = NULL;
+
+ init_node_list( removed_objects );
+}
+
+template<class T>
+r_Collection<T>::~r_Collection()
+{
+ RMDBGONCE(1, RMDebug::module_rasodmg, "r_Collection<T>", "~r_Collection")
+
+ r_deactivate();
+}
+
+
+
+/*************************************************************
+ * Method name...: r_deactivate()
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: This method is called when the object leaves
+ * the application cache. It frees all dynamic
+ * memory allocated within the class.
+ ************************************************************/
+template<class T>
+void
+r_Collection<T>::r_deactivate()
+{
+ RMDBGONCE(1, RMDebug::module_rasodmg, "r_Collection<T>", "r_deactivate()")
+
+ remove_all_nodes( coll );
+ remove_all_nodes( removed_objects );
+}
+
+
+
+template<class T>
+int
+r_Collection<T>::contains_element( const T& element ) const
+{
+ CNode* ptr = coll;
+
+ while ( *(ptr->elem) != element && ptr->next != NULL )
+ ptr = ptr->next;
+
+ if ( *(ptr->elem) == element )
+ return true;
+ else
+ return false;
+}
+
+template<class T>
+void
+r_Collection<T>::insert_element( const T& element, int no_modification )
+{
+ // add node to list...
+ add_node( coll, element );
+
+ // increase cardinaltity
+ card++;
+
+ // ...and remove it from removed objects if it exists
+ remove_node( removed_objects, element );
+
+ if( !no_modification )
+ mark_modified(); // remember modification
+}
+
+template<class T>
+void
+r_Collection<T>::remove_element( const T& element )
+{
+ // remove node from list...
+ if( remove_node( coll, element ) )
+ {
+ // ...and add it to removed objects list
+ add_node( removed_objects, element );
+
+ // decrease cardinality
+ card--;
+
+ mark_modified(); // remember modification
+ }
+}
+
+template<class T>
+void
+r_Collection<T>::remove_all()
+{
+ CNode* ptr = coll;
+ CNode* ptrLast = coll;
+
+ if ( ptr->elem != NULL )
+ {
+ add_node( removed_objects, *ptr->elem );
+ delete ptr->elem;
+ ptr->elem = NULL;
+ }
+ if ( ptr->next != NULL )
+ {
+ ptr = ptr->next;
+ while ( ptr->next != NULL )
+ {
+ add_node( removed_objects, *ptr->elem );
+ delete ptr->elem;
+ ptrLast = ptr;
+ ptr = ptr->next;
+ delete ptrLast;
+ }
+ delete ptr->elem;
+ delete ptr;
+ }
+ coll->next = NULL;
+ card = 0;
+
+ mark_modified(); // remember modification
+}
+
+
+
+template<class T>
+const r_Collection<T>&
+r_Collection<T>::operator=( const r_Collection<T>& collection )
+{
+ CNode* nptr;
+ CNode* optr;
+
+ if( this != &collection )
+ {
+ if( coll )
+ remove_all();
+ else
+ coll = new CNode;
+
+ nptr = coll;
+ optr = collection.coll;
+
+ while ( optr->next != NULL )
+ {
+ nptr->next = new CNode;
+ nptr->elem = new T;
+ *(nptr->elem) = *(optr->elem);
+ nptr = nptr->next;
+ optr = optr->next;
+ }
+ if ( optr->elem != NULL )
+ {
+ nptr->elem = new T;
+ *(nptr->elem) = *(optr->elem);
+ }
+
+ nptr->next = NULL;
+ card = collection.cardinality();
+ }
+
+ return *this;
+}
+
+
+
+template<class T>
+void
+r_Collection<T>::set_internal_representation( const void* node1 )
+{
+ // We assume that node1 is a correct CNode structure as
+ // defined in collection.hh
+ // copy it and determine cardinality
+ CNode* nptr;
+ CNode* optr;
+
+ if( coll )
+ remove_all();
+ else
+ coll = new CNode;
+
+ card = 0;
+ nptr = coll;
+ optr = (CNode*)node1;
+
+ while ( optr->next != NULL )
+ {
+ nptr->next = new CNode;
+ nptr->elem = new T;
+ card++;
+ *(nptr->elem) = *(optr->elem);
+ nptr = nptr->next;
+ optr = optr->next;
+ }
+ if ( optr->elem != NULL )
+ {
+ nptr->elem = new T;
+ card++;
+ *(nptr->elem) = *(optr->elem);
+ }
+
+ nptr->next = NULL;
+}
+
+
+template<class T>
+r_Iterator<T>
+r_Collection<T>::create_removed_iterator()
+{
+ return r_Iterator<T>( *this, 1 );
+}
+
+
+template<class T>
+r_Iterator<T>
+r_Collection<T>::create_iterator()
+{
+ return r_Iterator<T>( *this );
+}
+
+
+
+template<class T>
+void
+r_Collection<T>::insert_obj_into_db()
+{
+ // Insert myself in database only if I have an object name. If the
+ // collection doesn't have a name an exception is thrown.
+ if( !object_name || !strlen( object_name ) )
+ {
+ r_Error err = r_Error( r_Error::r_Error_ObjectUnknown );
+ throw err;
+ }
+
+ // Insert myself in database only if I have a type name, otherwise
+ // an exception is thrown.
+ if( !type_name || !strlen( type_name ) )
+ {
+ r_Error err = r_Error( r_Error::r_Error_DatabaseClassUndefined );
+ throw err;
+ }
+
+ // Insert myself into the database even if i'm empty.
+// r_Database::actual_database->communication->insertColl( object_name, type_name, get_oid() );
+ r_Database::actual_database->insertColl( object_name, type_name, get_oid() );
+ if( !is_empty() )
+ {
+ r_Iterator<T> iter = create_iterator();
+ for ( iter.reset(); iter.not_done(); iter++ )
+ // Search for *1 for an explanation of the following cast.
+ ((r_Object*)((r_Ref<r_Object>)(*iter)).ptr())->insert_obj_into_db( object_name );
+ }
+}
+
+
+
+template<class T>
+void
+r_Collection<T>::update_obj_in_db()
+{
+ // Update myself in database only if I have an object name. If the
+ // collection doesn't have a name an exception is thrown.
+ if( !object_name || !strlen( object_name ) )
+ {
+ r_Error err = r_Error( r_Error::r_Error_ObjectUnknown );
+ throw err;
+ }
+
+ // inspect collection elements
+ if( !is_empty() )
+ {
+ r_Iterator<T> iter = create_iterator();
+ for ( iter.reset(); iter.not_done(); iter++ )
+ {
+ // *1
+ //
+ // The following is a very ugly cast, but necessary if collection elements are not restricted
+ // to r_Ref objects. Anyway, if the elements are not of type r_Ref, it is not possible to make
+ // them persistent. A workaround would be to call a global function instead having a template
+ // specification for our case.
+ r_Ref<r_Object> ref = (r_Ref<r_Object>)(*iter);
+
+ RMInit::logOut << " Collection object " << ref.get_oid() << " " << std::flush;
+
+ // check if object is loaded
+ if( ref.get_memory_ptr() != 0 )
+ {
+ // Search for *1 for an explanation of the following cast.
+ switch( ((r_Ref<r_Object>)(*iter))->get_status() )
+ {
+ case r_Object::deleted:
+ RMInit::logOut << "state DELETED, not implemented" << endl;
+ RMInit::logOut << "OK" << endl;
+ break;
+
+ case r_Object::created:
+ RMInit::logOut << "state CREATED, writing ... " << std::flush;
+ // Search for *1 for an explanation of the following cast.
+ ((r_Object*)((r_Ref<r_Object>)(*iter)).ptr())->insert_obj_into_db( object_name );
+ RMInit::logOut << "OK" << endl;
+ break;
+
+ case r_Object::modified:
+ RMInit::logOut << "state MODIFIED, not implemented" << endl;
+ break;
+
+ case r_Object::read:
+ RMInit::logOut << "state READ, OK" << endl;
+ break;
+
+ case r_Object::transient:
+ RMInit::logOut << "state TRANSIENT, OK" << endl;
+ break;
+
+ default:
+ RMInit::logOut << "state UNKNOWN" << endl;
+ break;
+ }
+ }
+ else
+ RMInit::logOut << "state NOT LOADED" << endl;
+ }
+ }
+
+ // inspect removed objects
+ if( removed_objects->elem )
+ {
+ r_Iterator<T> iter = create_removed_iterator();
+ for ( iter.reset( 1 ); iter.not_done(); iter++ )
+ {
+ // *1
+ //
+ // The following is a very ugly cast, but necessary if collection elements are not restricted
+ // to r_Ref objects. Anyway, if the elements are not of type r_Ref, it is not possible to make
+ // them persistent. A workaround would be to call a global function instead of having a template
+ // specification for our case.
+ // The oid could also be got by (*iter)->get_oid() from r_Object but in this case, dereferencing
+ // r_Ref would load the object from the server.
+ r_OId currentOId = ((r_Ref<r_Object>)(*iter)).get_oid();
+
+ RMInit::logOut << " Collection object " << currentOId << " " << std::flush;
+
+ RMInit::logOut << "state REMOVED, removing ... " << std::flush;
+ try
+ {
+// r_Database::actual_database->communication->removeObjFromColl( object_name, currentOId );
+ r_Database::actual_database->removeObjFromColl( object_name, currentOId );
+ RMInit::logOut << "OK" << endl;
+ }
+ catch( r_Error& obj )
+ {
+ RMInit::logOut << "FAILED" << endl;
+ RMInit::logOut << obj.what() << endl;
+ }
+ }
+ }
+}
+
+
+
+template<class T>
+void
+r_Collection<T>::add_node( r_Collection<T>::CNode* &root, const T& element )
+{
+ CNode* ptr = root;
+
+ if ( ptr->elem == NULL )
+ {
+ ptr->elem = new T;
+ *(ptr->elem) = element;
+ }
+ else
+ {
+ while ( ptr->next != NULL )
+ ptr = ptr->next;
+
+ ptr->next = new CNode;
+ ptr = ptr->next;
+ ptr->next = NULL;
+ ptr->elem = new T;
+ *(ptr->elem) = element;
+ }
+}
+
+template<class T>
+int
+r_Collection<T>::remove_node( CNode* &root, const T& element )
+{
+ CNode* ptr = root;
+ CNode* ptrLast = root;
+ int success = 0;
+
+ if( ptr && ptr->elem )
+ {
+ // Look for the element or end of list
+ while ( *(ptr->elem) != element && ptr->next != NULL )
+ {
+ ptrLast = ptr;
+ ptr = ptr->next;
+ }
+
+ // If element is found, destroy the element itself.
+ // After that, there are four cases
+ // case 1: The element was the only element of the list
+ // (if so, don't destroy the node itself, only set the elem field NULL)
+ // case 2: The element had no successor
+ // (if so, the node before the element becomes the last node)
+ // case 3: The element had no predecessor
+ // (if so, the node after the element becomes the first node)
+ // case 4: The element had a successor and a prodecessor
+ // (if so, the node after the element becomes the successor of the
+ // node before the element)
+ if ( *(ptr->elem) == element )
+ {
+ success = 1;
+
+ delete ptr->elem;
+ if ( ptr == ptrLast && ptr->next == NULL ) // case 1
+ ptr->elem = NULL;
+ else
+ if ( ptr->next == NULL ) // case 2
+ {
+ ptrLast->next = NULL;
+ delete ptr;
+ }
+ else
+ if ( ptr == ptrLast ) // case 3
+ {
+ root = ptr->next;
+ delete ptr;
+ }
+ else // case 4
+ {
+ ptrLast->next = ptr->next;
+ delete ptr;
+ }
+ }
+ }
+
+ return success;
+}
+
+
+
+template<class T>
+void
+r_Collection<T>::remove_all_nodes( CNode* &root )
+{
+ if( root )
+ {
+ CNode* ptr = root;
+ CNode* ptrLast = root;
+
+ while ( ptr->next != NULL )
+ {
+ delete ptr->elem;
+ ptrLast = ptr;
+ ptr = ptr->next;
+ delete ptrLast;
+ }
+ delete ptr->elem;
+ delete ptr;
+ }
+
+ root = 0;
+}
+
+
+template<class T>
+void
+r_Collection<T>::init_node_list( CNode* &root )
+{
+ root = new CNode;
+ root->next = NULL;
+ root->elem = NULL;
+}
+
+
+
+template<class T>
+const r_Type*
+r_Collection<T>::get_element_type_schema()
+{
+ const r_Type* typePtr = r_Object::get_type_schema();
+ const r_Type* elementTypePtr = 0;
+
+ if( typePtr )
+ {
+ if( typePtr->type_id() == r_Type::COLLECTIONTYPE )
+ {
+ const r_Collection_Type* collectionTypePtr = (const r_Collection_Type*)typePtr;
+ elementTypePtr = &(collectionTypePtr->element_type());
+ }
+ }
+
+ return elementTypePtr;
+}
+
+
+
+
+
+
+
+
+
diff --git a/rasodmg/collection.hh b/rasodmg/collection.hh
new file mode 100644
index 0000000..d90eb39
--- /dev/null
+++ b/rasodmg/collection.hh
@@ -0,0 +1,224 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: collection.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Collection
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_COLLECTION_
+#define _D_COLLECTION_
+
+#include "raslib/error.hh"
+#include "rasodmg/object.hh"
+
+template <class T>
+class r_Iterator;
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ Basic class of a collection. Possible subclasses are \Ref{r_Set},
+ \Ref{r_Bag} and \Ref{r_List}. The protected members isOrdered and
+ allowsDuplicates are not initialized here, they have to be initialized
+ in the respective subclasses.
+
+*/
+
+template <class T>
+class r_Collection : public r_Object
+{
+ friend class r_Iterator<T>;
+
+ public:
+ /// default constructor
+ r_Collection() throw(r_Error);
+ /// copy constructor
+ r_Collection( const r_Collection<T>& collection ) throw(r_Error);
+ /// virtual destructor
+ virtual ~r_Collection();
+
+ /// it is called when an object leaves transient memory
+ virtual void r_deactivate();
+
+ /// get number of elements
+ inline unsigned long cardinality() const;
+
+ /// tells if the collection is empty or not
+ inline int is_empty() const;
+ /// tells if the collection is ordered or not
+ inline int is_ordered() const;
+ /// tells if the collections allowes duplicates or not
+ inline int allows_duplicates() const;
+
+ /// asks about the containment of a specific element
+ int contains_element( const T& element ) const;
+ /// inserts an alement at the beginning
+ virtual void insert_element( const T& element, int no_modification = 0 );
+ /**
+ The method inserts an element into the collection. If {\tt no_modification}
+ is set, the {\tt mark_modified()} method of r_Object is not invoked and, therefore,
+ a modification will not be recognized at the commit point.
+ */
+ /// removes an element
+ virtual void remove_element( const T& element );
+ /// removes all elements
+ void remove_all();
+
+ /// assignment operator
+ const r_Collection<T>& operator=( const r_Collection<T>& collection );
+
+ /// create an iterator pointing at the first element in the collection
+ r_Iterator<T> create_iterator();
+
+ /// get base type schema
+ const r_Type* get_element_type_schema();
+
+ //@Man: Methods for database communication (internal use only):
+ //@{
+ ///
+
+ /// insert myself into the database
+ virtual void insert_obj_into_db();
+
+ /// inserts an object into a specific collection in the database
+ virtual void insert_obj_into_db( const char* ){;};
+ /**
+ The method has no functionality in this class. It supposed to be removed in
+ future.
+ */
+
+ /// update myself
+ virtual void update_obj_in_db();
+
+ ///
+ //@}
+
+ //@Man: Constructors/Methods for internal use only:
+ //@{
+ ///
+
+ /// constructor getting an internal collection representation
+ r_Collection( const void* node1 );
+ ///
+ inline void* get_internal_representation() const;
+ ///
+ void set_internal_representation( const void* node1 );
+
+ ///
+ //@}
+
+ protected:
+ ///
+ typedef struct CNode
+ {
+ CNode* next;
+ T* elem;
+ };
+
+ //@Man: Methods/Attributes for maintainance of removed objects
+ //@{
+ ///
+
+ /// create an iterator for removed objects
+ r_Iterator<T> create_removed_iterator();
+
+ ///
+ /// pointer to list of removed elements
+ CNode* removed_objects;
+
+ ///
+ //@}
+
+ //@Man: Attributes storing some state information
+ //@{
+ ///
+ ///
+ int isOrdered;
+ ///
+ int allowsDuplicates;
+ ///
+ unsigned long card;
+ ///
+ //@}
+
+ // Normally, we would have used the following class to implement the
+ // internal structure of a r_Collection. But for RPC's sake, we use
+ // a simple structure. (RPC is not able to transfer C++ objects.)
+ //
+ // template <class T>
+ // class CNode
+ // {
+ // public:
+ // CNode();
+ // CNode( const CNode& cnode );
+ // ~CNode();
+ //
+ // inline CNode* get_next() const;
+ // inline void set_next( const CNode& cnode );
+ // inline T* get_elem() const;
+ // inline void set_elem( const T& element);
+ //
+ // private:
+ // CNode* next;
+ // T* elem;
+ // }
+
+ //@Man: Methods for manipulating CNode lists
+ //@{
+ ///
+
+ ///
+ void add_node( CNode* &root, const T& element );
+ ///
+ int remove_node( CNode* &root, const T& element );
+ ///
+ void remove_all_nodes( CNode* &root );
+ ///
+ void init_node_list( CNode* &root );
+
+ ///
+ //@}
+
+ /// pointer to collection elements
+ CNode* coll;
+};
+
+#include "rasodmg/collection.icc"
+
+#ifdef EARLY_TEMPLATE
+#ifdef __EXECUTABLE__
+#ifdef __VISUALC__
+#include "collection.cpp"
+#else
+#include "collection.cc"
+#endif
+#endif
+#endif
+
+#endif
diff --git a/rasodmg/collection.icc b/rasodmg/collection.icc
new file mode 100644
index 0000000..59b11ab
--- /dev/null
+++ b/rasodmg/collection.icc
@@ -0,0 +1,73 @@
+/*
+* 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>.
+/
+/**
+ * INLINE SOURCE: collection.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Collection
+ *
+ * COMMENTS:
+ * None
+*/
+
+template<class T>
+inline unsigned long
+r_Collection<T>::cardinality() const
+{
+ return card;
+}
+
+
+template<class T>
+inline int
+r_Collection<T>::is_empty() const
+{
+ if ( coll->elem )
+ return false;
+ else
+ return true;
+}
+
+
+template<class T>
+inline int
+r_Collection<T>::is_ordered() const
+{
+ return isOrdered;
+}
+
+
+template<class T>
+inline int
+r_Collection<T>::allows_duplicates() const
+{
+ return allowsDuplicates;
+}
+
+
+template<class T>
+inline void*
+r_Collection<T>::get_internal_representation() const
+{
+ return (void*)coll;
+}
diff --git a/rasodmg/database.cc b/rasodmg/database.cc
new file mode 100644
index 0000000..bdf11b0
--- /dev/null
+++ b/rasodmg/database.cc
@@ -0,0 +1,475 @@
+/*
+* 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: database.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Database
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsid[] = "@(#)rasodmg, r_Database: $Id: database.cc,v 1.47 2005/09/03 20:39:35 rasdev Exp $";
+
+#ifdef __VISUALC__
+#ifndef __EXECUTABLE__
+#define __EXECUTABLE__
+#define DATABASE_NOT_SET
+#endif
+#endif
+
+#include "rasodmg/database.hh"
+#include "rasodmg/transaction.hh"
+#include "clientcomm/clientcomm.hh"
+
+#ifdef DATABASE_NOT_SET
+#undef __EXECUTABLE__
+#endif
+
+#include <string.h>
+
+// At the beginning, no database is actually opened.
+r_Database* r_Database::actual_database = 0;
+
+
+r_Database::r_Database()
+ : db_status( not_open ),
+ rasmgrName(0),
+ userName(0),
+ plainPass(0),
+ communication(0)
+{
+}
+
+r_Database::r_Database( const char* name ) throw(r_Error)
+ : db_status( not_open ),
+ userName(0),
+ plainPass(0),
+ communication(0)
+{
+ if(!name)
+ {
+ RMInit::logOut << "Error: null database name." << std::endl;
+ throw r_Error(r_Error::r_Error_NameInvalid);
+ }
+ this->rasmgrName = strdup( name );
+}
+
+r_Type*
+r_Database::get_type_schema(const char* typeName, type_schema typeType) throw (r_Error)
+{
+ r_Type* retval = 0;
+
+ if ((typeName == NULL) || (strlen(typeName) == 0))
+ throw r_Error(r_Error::r_Error_NameInvalid);
+ else if ((typeType != COLLECTION ) && (typeType != MARRAY))
+ throw r_Error(r_Error::r_Error_TypeInvalid);
+ else if (r_Database::actual_database != NULL)
+ throw r_Error(r_Error::r_Error_DatabaseClosed);
+ else if (r_Database::actual_database->get_status() != r_Database::not_open)
+ throw r_Error(r_Error::r_Error_DatabaseClosed);
+ else if (r_Transaction::actual_transaction != NULL)
+ throw r_Error(r_Error::r_Error_TransactionNotOpen);
+ else if (r_Transaction::actual_transaction->get_status() == r_Transaction::active)
+ throw r_Error(r_Error::r_Error_TransactionNotOpen);
+ else
+ {
+ ClientComm::r_Type_Type type;
+ if (typeType == COLLECTION)
+ type = ClientComm::r_SetType_Type;
+ else
+ type = ClientComm::r_MDDType_Type;
+ char* temp = r_Database::actual_database->communication->getTypeStructure( typeName, type );
+ retval = r_Type::get_any_type(temp);
+ delete [] temp;
+ temp = 0;
+ }
+ return retval;
+}
+
+r_Database::~r_Database()
+{
+ if( db_status != not_open )
+ close();
+
+ if( rasmgrName )
+ free( rasmgrName );
+ if( userName )
+ free( userName );
+ if( plainPass )
+ free( plainPass );
+}
+
+void
+r_Database::open( const char* database_name, access_status new_status )
+ throw( r_Error )
+{
+ if( db_status != not_open || actual_database )
+ {
+ r_Error err = r_Error(r_Error::r_Error_DatabaseOpen);
+ throw err;
+ }
+
+ if(!database_name)
+ {
+ RMInit::logOut << "r_Database::open(name, new_status) name is null" << std::endl;
+ throw r_Error(r_Error::r_Error_NameInvalid);
+ }
+
+ // While instantiating the communication object, the first connection to
+ // the server is established. Any exception is given through to the caller
+ // of open(...).
+ try
+ {
+ communication = ClientComm::createObject( rasmgrName, rasmgrPort );
+ if( userName && plainPass )
+ communication->setUserIdentification( userName, plainPass );
+ }
+ catch( ... )
+ {
+ if(communication)
+ delete communication;
+ throw; // re-throw the exception (r_Error_HostInvalid, r_Error_ServerInvalid)
+ }
+
+ // open database
+ unsigned int status=0;
+ try
+ {
+ status = communication->openDB( (char*)database_name );
+ }
+ catch( ... )
+ {
+ if(communication)
+ delete communication;
+ throw;
+ }
+
+ if( status )
+ {
+ // translate error values into exceptions
+ r_Error err;
+
+ switch( status )
+ {
+ case 1:
+ err = r_Error( r_Error::r_Error_ClientUnknown );
+ break;
+
+ case 2:
+ err = r_Error( r_Error::r_Error_DatabaseUnknown );
+ break;
+
+ case 3:
+ err = r_Error( r_Error::r_Error_DatabaseOpen );
+ break;
+
+ case 4:
+ err = r_Error( r_Error::r_Error_RpcInterfaceIncompatible );
+ break;
+ case CONNECTIONCLOSED:
+ err = r_Error(CONNECTIONCLOSED);
+ break;
+ default:
+ err = r_Error( r_Error::r_Error_General );
+ }
+
+ if(communication)
+ delete communication;
+
+ throw err;
+ }
+
+ actual_database = this;
+ db_status = new_status;
+}
+
+void
+r_Database::close()
+{
+ if( db_status != not_open )
+ {
+ // if a communication object exists, close and delete it
+ if( communication )
+ {
+ // abort any open TA -- PB 2005-sep-02
+ // This is quite a hack (borrowed from fastscale.cc):
+ // Actual transaction is a pointer to this in a TA.
+ // Since the TA was allocated by the application program
+ // it should be save to use it like this.
+ if (r_Transaction::actual_transaction != 0)
+ { // make _very_ sure we have sequential evaluation -> nested ifs
+ if (r_Transaction::actual_transaction->get_status() == r_Transaction::active)
+ r_Transaction::actual_transaction->abort();
+ }
+
+ communication->closeDB();
+ delete communication;
+ communication = 0;
+ }
+
+ db_status = not_open;
+ actual_database = 0;
+ }
+}
+
+void
+r_Database::create( const char* name ) throw( r_Error )
+{
+ // this operation is not supported through this interface; use rasdl
+ throw( r_Error(803)); // Access denied, no permission
+}
+
+void
+r_Database::destroy( const char* name ) throw( r_Error )
+{
+ // this operation is not supported through this interface; use rasdl
+ throw( r_Error(803)); // Access denied, no permission
+}
+
+
+void
+r_Database::set_servername( const char* name, int port ) throw (r_Error)
+{
+ //We let the name of the function as it is, but it's about the rasmgr name
+
+ if(!name)
+ {
+ RMInit::logOut << "r_Database::set_servername(name, port) name is null" << std::endl;
+ throw r_Error(r_Error::r_Error_NameInvalid);
+ }
+
+ if( rasmgrName)
+ free( rasmgrName );
+
+ rasmgrName = strdup( name );
+ rasmgrPort = port;
+}
+void
+r_Database::set_useridentification( const char* name, const char *plain_pass ) throw(r_Error)
+{
+ if(!name)
+ {
+ RMInit::logOut << "r_Database::set_useridentification(name, plain_pass) name is null" << std::endl;
+ throw r_Error(r_Error::r_Error_NameInvalid);
+ }
+ if(!plain_pass)
+ {
+ RMInit::logOut << "r_Database::set_useridentification(name, plain_pass) plain_pass is null" << std::endl;
+ throw r_Error(r_Error::r_Error_NameInvalid);
+ }
+
+ if (userName)
+ free(userName);
+ if (plainPass)
+ free(plainPass);
+ userName = strdup( name );
+ plainPass = strdup( plain_pass );
+}
+
+void
+r_Database::set_object_name( r_Object &obj, const char* name ) throw(r_Error)
+{
+ obj.set_object_name( name );
+}
+
+r_Ref_Any
+r_Database::lookup_object( const char* name ) const throw( r_Error )
+{
+ r_Ref_Any returnValue;
+
+ if( db_status == not_open )
+ {
+ r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
+ throw err;
+ }
+
+ if(!name)
+ {
+ RMInit::logOut << "r_Database::lookup_object(name) name is null" << std::endl;
+ throw r_Error(r_Error::r_Error_NameInvalid);
+ }
+
+ if( !r_Transaction::actual_transaction
+ || r_Transaction::actual_transaction->get_status() != r_Transaction::active )
+ {
+ r_Error err = r_Error( r_Error::r_Error_TransactionNotOpen );
+ throw err;
+ }
+
+ try
+ {
+ // get collection
+ returnValue = communication->getCollOIdsByName( name );
+ }
+ catch( ... )
+ {
+ throw; // re-throw the exception
+ }
+
+ return returnValue;
+}
+
+
+
+r_Ref_Any
+r_Database::lookup_object( const r_OId& oid ) const throw( r_Error )
+{
+ r_Ref_Any returnValue;
+
+ if( db_status == not_open )
+ {
+ r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
+ throw err;
+ }
+
+ if( !r_Transaction::actual_transaction
+ || r_Transaction::actual_transaction->get_status() != r_Transaction::active )
+ {
+ r_Error err = r_Error( r_Error::r_Error_TransactionNotOpen );
+ throw err;
+ }
+
+ try
+ {
+ // determine type of object and get it
+ if( communication->getObjectType( oid ) == 1 )
+ returnValue = communication->getMDDByOId( oid );
+ else
+ returnValue = communication->getCollOIdsByOId( oid );
+ }
+ catch( ... )
+ {
+ throw; // re-throw the exception
+ }
+
+ return returnValue;
+}
+
+
+void
+r_Database::set_transfer_format( r_Data_Format format, const char *formatParams ) throw( r_Error )
+{
+ unsigned short result;
+
+ if ( db_status == not_open )
+ {
+ r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
+ throw (err);
+ }
+ //keeps from crashing in rpc on linux
+ if (formatParams == 0)
+ formatParams = "";
+ result = communication->setTransferFormat(format, formatParams);
+
+ switch (result)
+ {
+ case 1:
+ {
+ r_Error err = r_Error( r_Error::r_Error_ClientUnknown );
+ throw(err);
+ }
+ break;
+ case 2:
+ {
+ r_Error err = r_Error( r_Error::r_Error_FeatureNotSupported );
+ throw(err);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void
+r_Database::set_storage_format( r_Data_Format format, const char *formatParams ) throw( r_Error )
+{
+ unsigned short result;
+
+ if ( db_status == not_open )
+ {
+ r_Error err( r_Error::r_Error_DatabaseClosed );
+ throw(err);
+ }
+
+ //keeps from crashing in rpc on linux
+ if (formatParams == 0)
+ formatParams = "";
+
+ result = communication->setStorageFormat(format, formatParams);
+
+ switch (result)
+ {
+ case 1:
+ {
+ r_Error err( r_Error::r_Error_ClientUnknown );
+ throw(err);
+ }
+ break;
+ case 2:
+ {
+ r_Error err( r_Error::r_Error_FeatureNotSupported );
+ throw(err);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+
+
+const r_OId
+r_Database::get_new_oid( unsigned short objType ) const throw(r_Error)
+{
+ return communication->getNewOId( objType );
+}
+
+
+void r_Database::insertColl( const char* collName, const char* typeName, const r_OId& oid ) throw( r_Error )
+{
+ communication->insertColl(collName,typeName,oid );
+}
+
+void r_Database::removeObjFromColl( const char* name, const r_OId& oid ) throw ( r_Error )
+{
+ communication->removeObjFromColl(name,oid);
+}
+
+ClientComm* r_Database::getComm()
+{
+ return communication;
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rasodmg/database.hh b/rasodmg/database.hh
new file mode 100644
index 0000000..7491eb0
--- /dev/null
+++ b/rasodmg/database.hh
@@ -0,0 +1,270 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: database.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Database
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_DATABASE_
+#define _D_DATABASE_
+
+#include "raslib/rminit.hh"
+#include "raslib/error.hh"
+#include "rasodmg/object.hh"
+#include "raslib/mddtypes.hh"
+
+// forward declarations
+class r_Object;
+class r_Transaction;
+class ClientComm;
+class r_Ref_Any;
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ A database object must be instantiated and opened before
+ starting any transaction which uses the database, and closed
+ after ending these transactions.
+
+*/
+
+class r_Database
+{
+ public:
+ /// possible database states
+ enum access_status { not_open, read_write, read_only, exclusive };
+
+ /// possible types define by symbolic names
+ enum type_schema {
+ CELL = 3,
+ MARRAY = 2,
+ COLLECTION = 1
+ };
+
+ /// default constructor
+ r_Database();
+
+ /// constructor getting the rasmgr name
+ r_Database( const char* name ) throw(r_Error);
+ /**
+ One error situations can occur which raise an exception of type \Ref{r_Error} with
+ one of the following kinds:
+ r_Error_NameInvalid && Name is NULL.\\
+ */
+
+ /// destructor
+ ~r_Database();
+
+ /// open a database
+ void open( const char* database_name, access_status status = read_write )
+ throw( r_Error );
+ /**
+ The method opens the database specified with {\tt database_name}. Several error
+ situations can occur which raise an exception of type \Ref{r_Error} with
+ one of the following kinds:
+
+ \begin{tabular}{lll}
+ r_Error_HostInvalid && Host can not be found.\\
+ r_Error_ServerInvalid && Server can not be found.\\
+ r_Error_ClientUnknown && Client is not known by the server (earlier communication problems).\\
+ r_Error_DatabaseUnknown && Database does not exist.\\
+ r_Error_DatabaseOpen && Database is already open.\\
+ r_Error_TransferFailed && Other communication problem. \\
+ r_Error_NameInvalid && Name is NULL.\\
+ \end{tabular}
+ */
+
+ /// close a database
+ void close();
+
+ /// create a database with fixed schema RasDaSchema
+ void create( const char* name ) throw( r_Error );
+ /**
+ This method works only if a server host name has been specified with
+ {\tt set_servername()}.
+ One of error situations can occur will raise an exception of type \Ref{r_Error} with
+ one of the following kinds:
+ r_Error_NameInvalid && Name is NULL.\\
+ */
+
+ /// destroy a database
+ void destroy( const char* name ) throw( r_Error );
+ /**
+ This method works only if a server host name has been specified with
+ {\tt set_servername()}.
+ One of error situations can occur will raise an exception of type \Ref{r_Error} with
+ one of the following kinds:
+ r_Error_NameInvalid && Name is NULL.\\
+ */
+
+ /// set the server name
+ void set_servername( const char* name, int port = RASMGRPORT) throw(r_Error);
+ /**
+ One of error situations can occur will raise an exception of type \Ref{r_Error} with
+ one of the following kinds:
+ r_Error_NameInvalid && Name is NULL.\\
+ */
+ /// set the user name and password
+ void set_useridentification( const char* name, const char *plain_pass ) throw(r_Error);
+ /**
+ One of error situations can occur will raise an exception of type \Ref{r_Error} with
+ one of the following kinds:
+ r_Error_NameInvalid && Name is NULL.\\
+ */
+
+ /// get the actual status
+ inline access_status get_status() const;
+
+ /// give a name to an object (signature is not ODMG conformant because of compiler bug)
+ void set_object_name( r_Object& obj, const char* name ) throw(r_Error);
+ /**
+ The method gives the {\tt name} to the object {\tt obj}. The name is used for
+ further retrieval of the object. Right now, names can just be given to sets
+ of type {\tt r_Set}.
+ One of error situations can occur will raise an exception of type \Ref{r_Error} with
+ one of the following kinds:
+ r_Error_NameInvalid && Name is NULL.\\
+ */
+
+ /// lookup named objects in a database (must be called within open database and running transaction)
+ r_Ref_Any lookup_object( const char* name ) const
+ throw( r_Error );
+ /**
+ The method looks up an object with {\tt name}. Right now, just objects of type \Ref{r_Set} are
+ allowed. Error kinds:
+
+ \begin{tabular}{lll}
+ r_Error_ClientUnknown && Client is not known by the server (earlier communication problems).\\
+ r_Error_DatabaseClosed && Database is not open. \\
+ r_Error_TransactionNotOpen && No transaction is active. \\
+ r_Error_ObjectUnknown && The object with {\tt name} is not in the database.\\
+ r_Error_TransferFailed && Other communication problem. \\
+ r_Error_NameInvalid && Name is NULL.\\
+ \end{tabular}
+ */
+
+ /// lookup objects by oids in a database (must be called within open database and running transaction)
+ r_Ref_Any lookup_object( const r_OId& oid ) const
+ throw( r_Error );
+ /**
+ The method looks up an object with {\tt oid}. Right now, just objects of type \Ref{r_Set} and
+ \Ref{r_GMarray} are allowed.
+
+ Error kinds:
+ \begin{tabular}{lll}
+ r_Error_ClientUnknown && Client is not known by the server (earlier communication problems).\\
+ r_Error_DatabaseClosed && Database is not open. \\
+ r_Error_TransactionNotOpen && No transaction is active. \\
+ r_Error_ObjectUnknown && The object with {\tt oid} is not in the database.\\
+ r_Error_TransferFailed && Other communication problem. \\
+ \end{tabular}
+ */
+
+ r_Type* get_type_schema(const char* typeName, type_schema typetype) throw (r_Error);
+ /**
+ The method looks up the type structure with {\tt typeName} as its name. typetype is 1 for marray and 2 for collection.
+
+ Error kinds:
+ \begin{tabular}{lll}
+ r_Error_ClientUnknown && Client is not known by the server (earlier communication problems).\\
+ r_Error_DatabaseClosed && Database is not open. \\
+ r_Error_TransactionNotOpen && No transaction is active. \\
+ r_Error_ObjectUnknown && The object with {\tt typeName} is not in the database.\\
+ r_Error_TransferFailed && Other communication problem. \\
+ r_Error_TypeInvalid && The typetype is neither 1 nor 2. \\
+ r_Error_NameInvalid && The typeName is neither NULL or is a "\0". \\
+ \end{tabular}
+ */
+
+
+ /// set the transfer compression format, both for data sent from the server
+ /// to the client and the other way around.
+ void set_transfer_format( r_Data_Format format, const char *formatParams=NULL ) throw( r_Error );
+ /**
+ The method sets the transfer compression used for the communications of
+ this client with the server.
+
+ Error kinds:
+ \begin{tabular}{lll}
+ r_Error_ClientUnknown && Client is not known by the server\\
+ r_Error_DatabaseClosed && Database is not open\\
+ r_Error_FeatureNotSupported && Unsupported transfer format\\
+ \end{tabular}
+ */
+
+ /// set the storage format for newly created MDD for this client
+ void set_storage_format( r_Data_Format format, const char *formatParams=NULL) throw( r_Error );
+ /**
+ This method sets the storage format to use for MDD created by this client
+ in the RasDaMan database. The return values are identical to set_transfer_format()
+ */
+
+ /// stores a pointer to the actually opened database
+ static r_Database* actual_database;
+
+
+ //@Man: Methods for internal use only:
+ //@{
+ ///
+ const r_OId get_new_oid( unsigned short objType ) const throw(r_Error);
+ ///
+ //@}
+
+
+ // creates an empty MDD collection on the server
+ void insertColl( const char* collName, const char* typeName, const r_OId& oid ) throw( r_Error );
+
+ /// removes an object from a collection
+ void removeObjFromColl( const char* name, const r_OId& oid ) throw ( r_Error );
+
+ ClientComm* getComm();
+ private:
+ /// stores a pointer to a communication object, which is valid while a database is opened
+ ClientComm* communication;
+
+ /// database status
+ access_status db_status;
+
+ /// stores the RasMGR name
+ char* rasmgrName;
+
+ /// stores the RasMGR port
+ int rasmgrPort;
+
+ /// stores the user name
+ char* userName;
+
+ /// stores the user password (this will change!)
+ char* plainPass;
+};
+
+#include "rasodmg/database.icc"
+#include "rasodmg/ref.hh"
+
+#endif
diff --git a/rasodmg/database.icc b/rasodmg/database.icc
new file mode 100644
index 0000000..fb75479
--- /dev/null
+++ b/rasodmg/database.icc
@@ -0,0 +1,38 @@
+/*
+* 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>.
+/
+/**
+ * INLINE SOURCE: database.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Database
+ *
+ * COMMENTS:
+ * None
+*/
+
+inline
+r_Database::access_status
+r_Database::get_status() const
+{
+ return db_status;
+}
diff --git a/rasodmg/dirdecompose.cc b/rasodmg/dirdecompose.cc
new file mode 100644
index 0000000..d00b9b4
--- /dev/null
+++ b/rasodmg/dirdecompose.cc
@@ -0,0 +1,147 @@
+/*
+* 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: dirdecomp.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_DirDecomp
+ *
+ * COMMENTS:
+ * None
+ *
+*/
+
+#include "rasodmg/dirdecompose.hh"
+#include <string.h>
+
+// Default size of the interval buffer for holding intervals
+const r_Dimension r_Dir_Decompose::DEFAULT_INTERVALS = 5;
+
+r_Dir_Decompose::r_Dir_Decompose()
+: num_intervals(0), current_interval(0), intervals(NULL)
+{
+ num_intervals = r_Dir_Decompose::DEFAULT_INTERVALS;
+ intervals = new r_Range[num_intervals];
+}
+
+r_Dir_Decompose::~r_Dir_Decompose()
+{
+ if ( intervals )
+ {
+ delete [] intervals;
+ intervals = NULL;
+ }
+}
+
+r_Dir_Decompose::r_Dir_Decompose(const r_Dir_Decompose& other)
+: num_intervals(0), current_interval(0), intervals(NULL)
+{
+ num_intervals = other.num_intervals;
+ current_interval = other.current_interval;
+
+ if(other.intervals)
+ {
+ intervals = new r_Range[num_intervals];
+ memcpy(intervals, other.intervals, num_intervals*sizeof(r_Range));
+ }
+}
+
+const r_Dir_Decompose& r_Dir_Decompose::operator=(const r_Dir_Decompose& other)
+{
+ if (this != &other)
+ {
+ delete [] intervals;
+
+ num_intervals = other.num_intervals;
+ current_interval = other.current_interval;
+
+ if(other.intervals)
+ {
+ intervals = new r_Range[num_intervals];
+ memcpy(intervals, other.intervals, num_intervals*sizeof(r_Range));
+ }
+ }
+
+ return *this;
+}
+
+r_Dir_Decompose& r_Dir_Decompose::operator<<(r_Range limit)
+{
+ if (current_interval == num_intervals)
+ {
+ r_Range *aux = new r_Range[num_intervals*2];
+
+ for (int i=0; i<num_intervals; i++)
+ aux[i] = intervals[i];
+
+ delete [] intervals;
+ intervals = aux;
+
+ num_intervals*= 2;
+ }
+
+ intervals[current_interval++] = limit;
+
+ return *this;
+}
+
+int r_Dir_Decompose::get_num_intervals() const
+{
+ return current_interval;
+}
+
+r_Range r_Dir_Decompose::get_partition(int number) const
+ throw (r_Eindex_violation)
+{
+ if (number >= current_interval)
+ {
+ r_Eindex_violation err(0, current_interval, number);
+ throw err;
+ }
+
+ return intervals[number];
+}
+
+void r_Dir_Decompose::print_status(std::ostream& os) const
+{
+ os << "r_Dir_Decompose[ num intervals = " << num_intervals << " current interval = " << current_interval << " intervals = {";
+
+ for (int i=0; i<current_interval; i++)
+ os << intervals[i] << " ";
+
+ os << "} ]";
+}
+
+std::ostream& operator<<(std::ostream& os, const r_Dir_Decompose& d)
+{
+ d.print_status(os);
+
+ return os;
+}
+
+r_Sinterval
+r_Dir_Decompose::get_total_interval( )
+{
+ return r_Sinterval( intervals[0], intervals[current_interval - 1]);
+}
+
diff --git a/rasodmg/dirdecompose.hh b/rasodmg/dirdecompose.hh
new file mode 100644
index 0000000..c183fd0
--- /dev/null
+++ b/rasodmg/dirdecompose.hh
@@ -0,0 +1,114 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: dirdecomp.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Dir_Decompose
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_DIRDECOMPOSE_HH_
+#define _R_DIRDECOMPOSE_HH_
+
+// Include statements
+
+#include <iostream>
+using std::cout;
+
+#include "raslib/error.hh"
+#include "raslib/sinterval.hh"
+
+//@ManMemo: Module {\bf rasodmg}
+
+/*@Doc:
+
+ The {\tt r_Dir_Decompose} class is used to specify a decomposition on
+ an n-dimensional cube (for use in {\tt r_Dir_Tiling}). For instance, to
+ specify a tiling restriction on a dimension with the form: [0, 2, 4, 5],
+ the following code would apply:
+
+ r_Dir_Decompose decomp;
+
+ decomp << 0 << 2 << 4 << 5;
+
+ Note that the first and the last elements input into the object must be
+ the origin and limit of that dimension or else a cross-section of the domain
+ will occur (as if the elements outside the specification wouldn't mind).
+
+ If one dimension is considered to be a prefered access direction, then
+ the r_Dir_Decompose should be empty, this is, no restriction should be
+ entered.
+*/
+
+class r_Dir_Decompose
+{
+ public:
+
+ r_Dir_Decompose();
+
+ virtual ~r_Dir_Decompose();
+
+ /// Copy constructor
+ r_Dir_Decompose(const r_Dir_Decompose& other);
+
+ /// Assigment operator
+ const r_Dir_Decompose& operator=(const r_Dir_Decompose& other);
+
+ /// Reads a new limit for the current dimension
+ r_Dir_Decompose& operator<<(r_Range limit);
+
+ /// Gets the number of intervals the dimension is to be split into
+ int get_num_intervals() const;
+
+ /// Gets a restriction
+ r_Range get_partition(int number) const throw (r_Eindex_violation);
+
+ /// Prints the current status of the object
+ virtual void print_status(std::ostream& os = cout ) const;
+
+protected:
+ r_Sinterval get_total_interval( );
+
+ /// Initial number of intervals of the buffer
+ const static r_Dimension DEFAULT_INTERVALS;
+
+ /// The number of intervals that this object can currently suport
+ r_Dimension num_intervals;
+
+ /// The current interval that is being used for input
+ r_Dimension current_interval;
+
+ /// The buffer that holds the information
+ r_Range* intervals;
+};
+
+//@ManMemo: Module: {\bf rasodmg}
+/**
+ Prints the status of an r_Dir_Decompose object to a stream
+*/
+extern std::ostream& operator<<(std::ostream& os, const r_Dir_Decompose& d);
+
+#endif
diff --git a/rasodmg/dirtiling.cc b/rasodmg/dirtiling.cc
new file mode 100644
index 0000000..f0bf682
--- /dev/null
+++ b/rasodmg/dirtiling.cc
@@ -0,0 +1,682 @@
+/*
+* 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: 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 <assert.h>
+#include <string.h>
+#include <math.h>
+#include <cstdlib>
+
+#ifdef AIX
+#include <strings.h>
+#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<r_Dir_Decompose> 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, COLON);
+ 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<r_Dir_Decompose>(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, COLON);
+ 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, COMMA);
+ 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, COMMA);
+ 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;
+ break;
+ }//end if
+ }//end while
+ } //end if
+
+ delete[] pDirToConvert;
+ dirIndex++;
+ if(dirIndex < tileD)
+ {
+ if(pDirStart == (pToConvertEnd-1))
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose for dimension " << dirIndex << " from \"" << pToConvert << "\", end of stream." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ else
+ pDirStart++;
+
+ pDirRes=strstr(pDirStart, COMMA);
+ if(!pDirRes)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose for dimension " << dirIndex+1 << " from \"" << pToConvert << "\", end of stream." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ if(pDirRes == (pToConvertEnd-1))
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding directional decompose for dimension " << dirIndex << " from \"" << pToConvert << "\", end of stream." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ else
+ pDirRes++;
+
+ pDirTemp=pDirRes;
+ }//end if(dirIndex<tileD)
+ }//end while
+
+ //skip COLON & free buffer
+ delete[] pToConvert;
+ if(pRes==(pEnd-1))
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding tile size from \"" << pStart << "\", end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ else
+ pRes++;
+ pTemp=pRes;
+
+ //deal with tilesize
+ pRes=strstr(pTemp, COLON);
+ if(!pRes)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding tile size from \"" << pTemp << "\", end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ lenToConvert=pRes-pTemp;
+ pToConvert=new char[lenToConvert+1];
+ memcpy(pToConvert, pTemp, lenToConvert);
+ pToConvert[lenToConvert]='\0';
+
+ tileS=strtol(pToConvert, (char**)NULL, DefaultBase);
+
+ if(!tileS)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding tile size from \"" << pToConvert << "\", is not a number." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if(tileS<0)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding tile size from \"" << pToConvert << "\", is negative." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //skip COLON & free buffer
+ delete[] pToConvert;
+ if(pRes==(pEnd-1))
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding subtiling from \"" << pStart << "\", end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ else
+ pRes++;
+ pTemp=pRes;
+ //deal with subtilig
+ subTiling=r_Dir_Tiling::get_subtiling_from_name(pTemp);
+ if(subTiling==r_Dir_Tiling::NUMBER)
+ {
+ RMInit::logOut << "r_Dir_Tiling::r_Dir_Tiling(" << encoded << "): Error decoding subtiling from \"" << pTemp << "\"." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ dimension = tileD;
+ dim_decomp = vectDirDecomp;
+ sub_tile = subTiling;
+ tile_size = tileS;
+}
+
+r_Dir_Tiling::r_Dir_Tiling(r_Dimension dims, const std::vector<r_Dir_Decompose>& 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_Minterval>*
+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<r_Minterval>* decomp_result = new std::vector<r_Minterval>();
+ // An alias to result
+ std::vector<r_Minterval>& result = *decomp_result;
+ std::vector<r_Dir_Decompose> 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<dimension; i++)
+ partition << r_Sinterval((r_Range) 0, tile[i].high()-tile[i].low());
+ }
+ else
+ {
+ // Some unspecified dimensions
+
+ // Compute edgesize
+ r_Range edgesize = tile_size;
+
+ for (i = 0; i < dimension; i++)
+ {
+ if (!undef_dim[i])
+ edgesize/= (tile[i].high()-tile[i].low()+1) * typelen;
+ }
+
+ edgesize = floor(pow(((double)edgesize)/((double)typelen), (1.0/((double)total_undef))));
+
+ // Create specification
+
+ for (i = 0; i < dimension; i++)
+ {
+ if (undef_dim[i])
+ partition << r_Sinterval((r_Range) 0, (edgesize-1));
+ else
+ partition << r_Sinterval((r_Range) 0, tile[i].high()-tile[i].low());
+ }
+ }
+
+#ifdef _DEBUG_DIRTILING_
+ cout << "(DirTiling::compute_tiles(): Tile size = " << get_tile_size()
+ << " Specs = " << partition << endl;
+#endif
+
+ // Create subtiles and insert them in the result
+
+ r_Aligned_Tiling subtiling(partition, get_tile_size());
+ std::vector<r_Minterval>* subtiles = subtiling.compute_tiles(tile, typelen);
+ std::vector<r_Minterval>::iterator it = subtiles->begin();
+ for (; it != subtiles->end(); it++)
+ {
+ result.push_back(*it);
+
+#ifdef _VISUALIZE_2D_DECOMP_ // If we are visualizing
+ if (domain.dimension() == 2)
+ {
+ vis->set_pen(0, 255, 0);
+ if (dimension == 2)
+ (*vis) << (*it);
+ }
+#endif
+ }
+ delete subtiles;
+ }
+ else
+ result.push_back(tile);
+
+#ifdef _VISUALIZE_2D_DECOMP_ // If we are visualizing
+ if (domain.dimension() == 2)
+ {
+ vis->set_pen(255, 255, 0);
+ if (dimension == 2)
+ (*vis) << tile;
+ }
+#endif
+
+ // Update dimension counters
+
+ for (i=0; i < dimension; i++)
+ {
+ dim_counter[i]++;
+ if (dim_counter[i] == (temp_dim_decomp[i].get_num_intervals()-1))
+ dim_counter[i] = 0;
+ else
+ break;
+ }
+
+ // See if we are done
+ done = 1;
+ for (i=0; i<dimension; i++)
+ if (dim_counter[i] != 0)
+ {
+ done = 0;
+ break;
+ }
+ }
+
+ delete [] dim_counter;
+
+#ifdef _VISUALIZE_2D_DECOMP_
+ if (dimension == 2)
+ delete vis;
+#endif
+
+ delete [] undef_dim;
+ return &result;
+}
+
+bool
+r_Dir_Tiling::is_compatible(const r_Minterval& domain, r_Bytes type_len) const
+{
+ bool retval = true;
+ if (!r_Dimension_Tiling::is_compatible(domain, type_len))
+ retval = false;
+ else {
+
+ // Aux variable
+ r_Dimension i = 0;
+
+ for (i = 0; i < dimension; i++) // Check if limits ok
+ {
+ if (dim_decomp[i].get_num_intervals() > 0) // Restric defined
+ {
+ r_Range lim1, lim2;
+
+ lim1 = domain[i].high();
+ lim2 = dim_decomp[i].get_partition(dim_decomp[i].get_num_intervals()-1);
+ if (lim1 != lim2)
+ {
+ retval = false;
+ break;
+ }
+
+ lim1 = domain[i].low();
+ lim2 = dim_decomp[i].get_partition(0);
+ if (lim1 != lim2)
+ {
+ retval = false;
+ break;
+ }
+ }
+ }
+ }
+ return retval;
+}
+
diff --git a/rasodmg/dirtiling.hh b/rasodmg/dirtiling.hh
new file mode 100644
index 0000000..9495571
--- /dev/null
+++ b/rasodmg/dirtiling.hh
@@ -0,0 +1,133 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: dirtiling.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Dir_Tiling
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_DIRTILING_HH_
+#define _R_DIRTILING_HH_
+
+// Include statements
+class r_Dir_Decompose;
+class r_Dir_Tiling;
+
+#include "rasodmg/tiling.hh"
+
+// Class definition
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+ This class implements the "Directional Tiling" tiling method. In this
+ method the decomposition is done along certain directions of the
+ multi-dimensional cube. The user uses {\tt r_Dir_Decompose} to inform
+ the system on how the decomposition is done in each dimension.
+*/
+
+class r_Dir_Tiling : public r_Dimension_Tiling
+{
+ // ******************* PUBLIC SECTION *******************
+
+ public:
+
+ /// Constants that specify if subtiling will occur inside the blocks
+ enum SubTiling {
+ WITHOUT_SUBTILING = 0,
+ WITH_SUBTILING = 1,
+ NUMBER = 2
+ };
+ /// read everything from encoded string
+ /// e.g. "3;[0,2,4,5],[*],[0,10,15];100;NOSUBTILING"
+ r_Dir_Tiling(const char* encoded) throw (r_Error);
+
+ /// Class constructor
+ r_Dir_Tiling(r_Dimension dims,
+ const std::vector<r_Dir_Decompose>& decomp,
+ r_Bytes ts = RMInit::clientTileSize,
+ SubTiling sub = WITH_SUBTILING) throw (r_Error);
+ /**
+ The user has to give the number of dimensions of the space and the
+ decomposition wanted for that space. Note that the number of elements of
+ decomp must be the same as the number of dimensions of the space.
+ See {\tt r_Dir_Decompose} for details on how to indicate a decomposition.
+ SubTiling indicates if subtiling should occur inside the blocks specified
+ by the user.
+ Throws an exception when the decomp.size is not equal to the specified
+ dimension.
+ */
+
+ virtual ~r_Dir_Tiling();
+
+ virtual std::vector<r_Minterval>* compute_tiles(const r_Minterval& obj_domain, r_Bytes cell_size) const throw (r_Error);
+
+ virtual bool is_compatible(const r_Minterval& obj_domain, r_Bytes type_len) const;
+
+ virtual void print_status(std::ostream& os) const;
+
+ virtual r_Tiling* clone() const;
+
+ virtual r_Tiling_Scheme get_tiling_scheme() const;
+
+ //@ManMemo: Module: {\bf raslib}
+ /**
+ Get a tilesize limit for a tilisize limit name
+ */
+ static r_Dir_Tiling::SubTiling get_subtiling_from_name(const char* name);
+ //@ManMemo: Module: {\bf raslib}
+ /**
+ Get a tilisize limit name for a tilesize limit
+ */
+ static const char* get_name_from_subtiling(SubTiling st);
+
+ static const char* description;
+
+ protected: // data
+
+ /// The decomposition to be used
+ std::vector<r_Dir_Decompose> dim_decomp;
+
+ /// If sub-tiling should occour
+ SubTiling sub_tile;
+
+ //@ManMemo: Module: {\bf raslib}
+ /**
+ The names of all subtiling types, to avoid redundant storage and inconsistencies.
+ The variable name convention is the prefix subtiling_name_ followed by the name
+ of the data format in lower case, i.e. for WITH_SUBTILING subtiling_name_withsubtiling.
+ In addition there's an array of names all_subtiling_names where the subtiling
+ can be used as index to get the name.
+ */
+ static const char* subtiling_name_withoutsubtiling;
+ static const char* subtiling_name_withsubtiling;
+
+ static const char* all_subtiling_names[r_Dir_Tiling::NUMBER];
+};
+
+#endif
+
diff --git a/rasodmg/gmarray.cc b/rasodmg/gmarray.cc
new file mode 100644
index 0000000..89fa919
--- /dev/null
+++ b/rasodmg/gmarray.cc
@@ -0,0 +1,484 @@
+/*
+* 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: gmarray.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_GMarray
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsidgarray[] = "@(#)rasodmg, r_GMarray: $Id: gmarray.cc,v 1.45 2003/12/27 23:02:56 rasdev Exp $";
+
+#include <vector>
+
+#ifdef __VISUALC__
+#ifndef __EXECUTABLE__
+#define __EXECUTABLE__
+#define GMARRAY_NOT_SET
+#endif
+#endif
+
+#include "rasodmg/marray.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/storagelayout.hh"
+#include "rasodmg/alignedtiling.hh"
+#include "clientcomm/clientcomm.hh"
+
+#ifdef GMARRAY_NOT_SET
+#undef __EXECUTABLE__
+#endif
+
+#include "raslib/rmdebug.hh"
+#include "raslib/type.hh"
+#include "raslib/marraytype.hh"
+#include "raslib/structuretype.hh"
+
+#include <string.h> // for memcpy()
+#include <iostream>
+#include <iomanip>
+
+
+
+r_GMarray::r_GMarray() throw(r_Error)
+ : r_Object(1),
+ data(0),
+ data_size(0),
+ type_length(0),
+ current_format(r_Array),
+ storage_layout(0)
+{
+ storage_layout = new r_Storage_Layout();
+}
+
+
+
+r_GMarray::r_GMarray(const r_Minterval& initDomain, r_Bytes initLength, r_Storage_Layout* stl) throw (r_Error)
+ : r_Object(1),
+ data(0),
+ data_size(0),
+ domain(initDomain),
+ type_length(initLength),
+ current_format(r_Array),
+ storage_layout(stl)
+{
+ int error = 0;
+ if (domain.dimension() == 0)
+ {
+ error = 1;
+ }
+ else {
+ if (storage_layout == NULL)
+ {
+ storage_layout = new r_Storage_Layout(new r_Aligned_Tiling(initDomain.dimension()));
+ }
+ if (!storage_layout->is_compatible(initDomain, initLength))
+ {
+ error = 2;
+ }
+ }
+ if (error != 0)
+ {
+ RMInit::logOut << "r_GMarray::r_GMarray(" << initDomain << ", " << initLength << ", ";
+ if (storage_layout == NULL)
+ RMInit::logOut << "no storage layout";
+ else
+ RMInit::logOut << *storage_layout;
+ RMInit::logOut << ") ";
+ if (error == 1)
+ {
+ RMInit::logOut << "domain is not initialised";
+ throw r_Error(DOMAINUNINITIALISED);
+ }
+ else {
+ RMInit::logOut << "storage layout is not compatible";
+ throw r_Error(STORAGERLAYOUTINCOMPATIBLEWITHGMARRAY);
+ }
+ }
+ data_size = domain.cell_count() * initLength;
+ data = new char[ data_size ];
+ memset(data, 0, data_size);
+}
+
+
+
+r_GMarray::r_GMarray(const r_GMarray &obj) throw(r_Error)
+ : r_Object(obj, 1),
+ data(0),
+ data_size(0),
+ domain(obj.spatial_domain()),
+ type_length(obj.type_length),
+ current_format(obj.current_format),
+ storage_layout(0)
+{
+ RMDBCLASS("r_GMarray", "r_GMarray(const r_GMarray)", "rasodmg", __FILE__, __LINE__)
+
+ if (obj.data)
+ {
+ data_size = obj.data_size;
+ data = new char[ data_size ];
+
+ memcpy(data, obj.data, (unsigned int)data_size);
+ }
+
+ // clone the storage layout object
+ if (obj.storage_layout)
+ storage_layout = obj.storage_layout->clone();
+ else
+ RMInit::logOut << "copy constructor no storage layout" << endl;
+}
+
+
+
+r_GMarray::r_GMarray(r_GMarray &obj) throw(r_Error)
+ : r_Object(obj, 1),
+ data(obj.data),
+ data_size(obj.data_size),
+ domain(obj.spatial_domain()),
+ type_length(obj.type_length),
+ current_format(obj.current_format),
+ storage_layout(0)
+{
+ RMDBCLASS("r_GMarray", "r_GMarray(r_GMarray)", "rasodmg", __FILE__, __LINE__)
+
+ obj.data_size = 0;
+ obj.data = 0;
+ obj.domain = r_Minterval();
+ obj.type_length = 0;
+
+ // clone the storage layout object
+ if (obj.storage_layout)
+ storage_layout = obj.storage_layout->clone();
+ else
+ RMInit::logOut << "copy constructor (no data) no storage layout" << endl;
+}
+
+
+
+r_GMarray::~r_GMarray()
+{
+ r_deactivate();
+}
+
+
+
+void
+r_GMarray::r_deactivate()
+{
+ RMDBGENTER(2, RMDebug::module_rasodmg, "r_GMarray", "r_deactivate()");
+
+ if (data)
+ {
+ delete[] data;
+ data = 0;
+ }
+
+ // invoke deactivate of members with dynamic memory
+ domain.r_deactivate();
+
+ // delete dynamic members
+ if (storage_layout)
+ {
+ delete storage_layout;
+ storage_layout = 0;
+ }
+
+ RMDBGEXIT(2, RMDebug::module_rasodmg, "r_GMarray", "r_deactivate()");
+}
+
+
+
+const char*
+r_GMarray::operator[] (const r_Point& point) const
+ throw(r_Edim_mismatch, r_Eindex_violation)
+{
+ return &(data[ domain.cell_offset(point)*type_length ]);
+}
+
+
+
+const r_Storage_Layout*
+r_GMarray::get_storage_layout() const
+{
+ return storage_layout;
+}
+
+
+void
+r_GMarray::set_storage_layout(r_Storage_Layout *stl) throw(r_Error)
+{
+ if (!stl->is_compatible(domain, type_length))
+ {
+ RMInit::logOut << "r_GMarray::set_storage_layout(" << *stl << ") gmarray is not compatible with tiling" << endl;
+ RMInit::logOut << "\tgmarray domain : " << spatial_domain() << endl;
+ RMInit::logOut << "\tgmarray type size: " << get_type_length() << endl;
+ throw r_Error(STORAGERLAYOUTINCOMPATIBLEWITHGMARRAY);
+ }
+
+ if (storage_layout != NULL)
+ delete storage_layout;
+
+ storage_layout = stl;
+}
+
+
+
+const r_GMarray&
+r_GMarray::operator=(const r_GMarray& marray)
+{
+ if (this != &marray)
+ {
+ if (data)
+ {
+ delete[] data;
+ data = 0;
+ }
+
+ if (marray.data)
+ {
+ data_size = marray.data_size;
+ data = new char[ data_size ];
+
+ memcpy(data, marray.data, (unsigned int)data_size);
+ }
+
+ if (storage_layout)
+ {
+ delete storage_layout;
+ storage_layout = 0;
+ }
+
+ // this has to be changed to a clone() function in future
+ if (marray.storage_layout)
+ // storage_layout = new r_Storage_Layout(*marray.storage_layout);
+ storage_layout = marray.storage_layout->clone();
+
+ domain = marray.domain;
+ type_length = marray.type_length;
+ current_format = marray.current_format;
+ }
+
+ return *this;
+}
+
+
+
+void
+r_GMarray::insert_obj_into_db()
+{
+ // Nothing is done in that case. r_Marray objects can just be inserted as elements
+ // of a collection which invokes r_GMarray::insert_obj_into_db(const char* collName)
+ // of the r_Marray objects.
+
+ // r_Database::actual_database->communication->insertSingleMDDObj(this);
+ RMInit::logOut << " do nothing " << std::flush;
+}
+
+
+
+void
+r_GMarray::insert_obj_into_db(const char* collName)
+{
+ // Insert myself in database only if I have a type name, otherwise
+ // an exception is thrown.
+ if (!type_name)
+ {
+ r_Error err = r_Error(r_Error::r_Error_DatabaseClassUndefined);
+ throw err;
+ }
+
+ r_Database::actual_database->getComm()->insertMDD(collName, this);
+}
+
+
+
+
+void
+r_GMarray::print_status(std::ostream& s) const
+{
+ const r_Type* typeSchema = (r_Base_Type*)((r_GMarray*)this)->get_type_schema();
+ const r_Base_Type* baseTypeSchema = (r_Base_Type*)((r_GMarray*)this)->get_base_type_schema();
+
+ s << "GMarray" << endl;
+ s << " Oid...................: " << get_oid() << endl;
+ s << " Type Structure........: " << (get_type_structure() ? get_type_structure() : "<nn>") << endl;
+ s << " Type Schema...........: " << std::flush;
+ if (typeSchema)
+ typeSchema->print_status(s);
+ else
+ s << "<nn>" << std::flush;
+ s << endl;
+ s << " Domain................: " << domain << endl;
+ s << " Base Type Schema......: " << std::flush;
+ if (baseTypeSchema)
+ baseTypeSchema->print_status(s);
+ else
+ s << "<nn>" << std::flush;
+ s << endl;
+ s << " Base Type Length......: " << type_length << endl;
+ s << " Data format.......... : " << current_format << endl;
+ s << " Data size (bytes).... : " << data_size << endl;
+}
+
+
+
+void
+r_GMarray::print_status(std::ostream& s, int hexoutput) const
+{
+ print_status(s);
+
+ const r_Type* typeSchema = (r_Base_Type*)((r_GMarray*)this)->get_type_schema();
+ const r_Base_Type* baseTypeSchema = (r_Base_Type*)((r_GMarray*)this)->get_base_type_schema();
+
+ if (domain.dimension())
+ {
+ r_Point p(domain.dimension());
+ bool done = false;
+ r_Dimension i = 0;
+
+ // initialize point
+ for (i = 0; i < domain.dimension(); i++)
+ p << domain[i].low();
+
+ // iterate over all cells
+ while(!done)
+ {
+ //
+ // print cell
+ //
+
+ // get cell address
+ char* cell = data + domain.cell_offset(p) * type_length;
+
+ if (hexoutput)
+ {
+ for (r_Bytes j = 0; j < type_length; j++)
+ s << std::hex << (unsigned int)(unsigned char)(cell[j]);
+ }
+ else {
+ if(baseTypeSchema) baseTypeSchema->print_value(cell, s );
+ else s << "<nn>" << std::flush;
+ }
+
+ s << " ";
+
+ // increment coordinate
+ i = 0;
+ while(++p[i] > domain[i].high())
+ {
+ s << endl;
+ p[i] = domain[i].low();
+ i++;
+ if (i >= domain.dimension())
+ {
+ done = true;
+ break;
+ }
+ }
+ if (i > 1) s << endl;
+ }
+ }
+ else
+ {
+ s << "Cell value " << std::flush;
+
+ // print cell
+ if ((hexoutput) || (!baseTypeSchema))
+ {
+ for (unsigned int j=0; j<type_length; j++)
+ s << std::hex << (unsigned int)(unsigned char)(data[j]);
+ }
+ else {
+ if(baseTypeSchema) baseTypeSchema->print_value(data, s );
+ else s << "<nn>" << std::flush;
+ }
+ s << endl;
+ }
+
+ // turn off hex mode again
+ s << std::dec << std::flush;
+}
+
+
+
+
+r_GMarray* r_GMarray::intersect(r_Minterval where) const
+{
+ r_GMarray* tile = new r_GMarray();
+
+ r_Minterval obj_domain = spatial_domain();
+ r_Dimension num_dims = obj_domain.dimension();
+ r_Bytes tlength = get_type_length();
+
+ char* obj_data = new char[where.cell_count() * tlength];
+ tile->set_spatial_domain(where);
+ tile->set_type_length(tlength);
+ tile->set_array(obj_data);
+ tile->set_array_size(where.cell_count() * tlength);
+
+ r_Bytes block_length = where[num_dims-1].high() - where[num_dims-1].low() + 1;
+ r_Bytes total = where.cell_count()/block_length;
+
+ for (r_Area cell = 0; cell < total; cell++)
+ {
+ r_Point p = where.cell_point(cell*block_length);
+
+ char* dest_off = obj_data;
+ const char* source_off = get_array();
+
+ memcpy((void*) (dest_off + where.cell_offset(p)*tlength),
+ (void*) (source_off + obj_domain.cell_offset(p)*tlength),
+ (size_t) (block_length * tlength));
+ }
+
+ return tile;
+}
+
+
+
+const r_Base_Type*
+r_GMarray::get_base_type_schema()
+{
+ const r_Type* typePtr = r_Object::get_type_schema();
+ const r_Base_Type* baseTypePtr = 0;
+
+ if (typePtr)
+ {
+ if (typePtr->type_id() == r_Type::MARRAYTYPE)
+ {
+ const r_Marray_Type* marrayTypePtr = (const r_Marray_Type*)typePtr;
+ baseTypePtr = &(marrayTypePtr->base_type());
+ }
+ else
+ {
+ //whenever this module is done correctly, it should be checked first, what kind of type we are dealing with. therefore i do not declare a throw clause.
+ RMInit::logOut << "r_GMarray::get_base_type_schema() the type retrieved (" << typePtr->name() << ") was not a marray type" << endl;
+ throw r_Error(NOTANMARRAYTYPE);
+ }
+ }
+
+ return baseTypePtr;
+}
+
diff --git a/rasodmg/gmarray.hh b/rasodmg/gmarray.hh
new file mode 100644
index 0000000..2274e74
--- /dev/null
+++ b/rasodmg/gmarray.hh
@@ -0,0 +1,185 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: gmarray.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_GMarray
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_GMARRAY_
+#define _D_GMARRAY_
+
+#include "rasodmg/object.hh"
+
+#include "raslib/error.hh"
+#include "raslib/minterval.hh"
+#include "raslib/point.hh"
+#include "raslib/type.hh"
+#include "raslib/mddtypes.hh"
+
+#include <iostream>
+
+// forward declarations
+class r_Storage_Layout;
+
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ The class represents a generic MDD in the sense that it
+ is independent of the cell base type. The only information
+ available is the length in bytes of the base type.
+ More specific MDDs including base type information for more
+ type safety are represented by the template subclass \Ref{r_Marray}.
+ Class \Ref{r_Marray} provides a constructor to convert to the base
+ type specific class.
+*/
+
+class r_GMarray : public r_Object
+{
+ public:
+ /// default constructor (no memory is allocated!)
+ r_GMarray() throw(r_Error);
+
+ /// constructor for uninitialized MDD objects
+ r_GMarray(const r_Minterval& init_domain, r_Bytes type_length, r_Storage_Layout* stl = 0) throw (r_Error);
+ /**
+ If a storage layout pointer is provided, the object refered to is
+ taken and memory control moves to the \Ref{r_GMarray} class.
+ The user has to take care, that each creation of \Ref{r_GMarray}
+ objects get a new storage layout object.
+ r_Error is throw if the storage layout does not fit the type length or the dimension of the init domain and when the dimension of the domain is 0 (uninitialised).
+ */
+
+ /// copy constructor
+ r_GMarray(const r_GMarray&) throw(r_Error);
+
+ /// constructor which doesn't copy the data
+ r_GMarray(r_GMarray&) throw(r_Error);
+
+ /// destructor
+ virtual ~r_GMarray();
+
+ /// it is called when an object leaves transient memory (internal use only)
+ virtual void r_deactivate();
+
+ /// assignment: cleanup + copy
+ const r_GMarray& operator= (const r_GMarray&);
+
+ /// subscript operator for read access of a cell
+ const char* operator[](const r_Point&) const
+ throw(r_Edim_mismatch, r_Eindex_violation);
+
+ /// Returns a r_GMarray that is the intersection of the current domain with the specified interval
+ r_GMarray* intersect(r_Minterval where) const;
+
+ //@Man: Read methods
+ //@{
+ ///
+
+ /// gets a pointer to the storage layout object
+ const r_Storage_Layout* get_storage_layout() const;
+ /// getting the spatial domain
+ inline const r_Minterval& spatial_domain() const;
+ /// get the internal representation of the array
+ inline char* get_array();
+ /// get the internal representation of the array for reading
+ inline const char* get_array() const;
+ /// get size of internal array representation in byets
+ inline r_Bytes get_array_size() const;
+ /// get length of cell type in bytes
+ inline r_Bytes get_type_length() const;
+ /// get current data format
+ inline r_Data_Format get_current_format() const;
+
+ /// get base type schema
+ const r_Base_Type* get_base_type_schema();
+
+ ///
+ //@}
+
+ //@Man: Write methods
+ //@{
+ ///
+ /// sets the storage layout object and checks compatibility with the domain
+ void set_storage_layout(r_Storage_Layout *) throw (r_Error);
+ /// set spatial domain
+ inline void set_spatial_domain(const r_Minterval& domain);
+ /// set the internal representation of the array
+ inline void set_array(char*);
+ /// set size of internal memory representation in bytes
+ inline void set_array_size(r_Bytes);
+ /// set length of cell type in bytes
+ inline void set_type_length(r_Bytes);
+ /// set current data format
+ inline void set_current_format(r_Data_Format);
+
+ ///
+ //@}
+
+ //@Man: Methods for database communication (internal use only)
+ //@{
+ ///
+
+ /// inserts an object into the database
+ virtual void insert_obj_into_db();
+ /// insert myself into a specific collection in the database
+ void insert_obj_into_db(const char* collName);
+
+ ///
+ //@}
+
+ /// writes the state of the object to the specified stream
+ virtual void print_status(std::ostream& s = std::cout) const;
+
+ /// writes the state of the object to the specified stream
+ void print_status(std::ostream& s, int hexoutput) const;
+
+ protected:
+ /// spatial domain
+ r_Minterval domain;
+
+ /// pointer to the internal array representation
+ char* data;
+
+ /// size of internal array representation in bytes
+ r_Bytes data_size;
+
+ /// length of the cell base type in bytes
+ r_Bytes type_length;
+
+ /// store current data format
+ r_Data_Format current_format;
+
+ /// pointer to storage layout object
+ r_Storage_Layout* storage_layout;
+};
+
+#include "rasodmg/gmarray.icc"
+
+#endif
diff --git a/rasodmg/gmarray.icc b/rasodmg/gmarray.icc
new file mode 100644
index 0000000..f6453b2
--- /dev/null
+++ b/rasodmg/gmarray.icc
@@ -0,0 +1,119 @@
+/*
+* 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>.
+/
+/**
+ * INLINE SOURCE: gmarray.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_GMarray
+ *
+ * COMMENTS:
+ * None
+*/
+
+
+
+inline const r_Minterval&
+r_GMarray::spatial_domain() const
+{
+ return domain;
+};
+
+
+
+inline char*
+r_GMarray::get_array()
+{
+ return data;
+};
+
+
+inline const char*
+r_GMarray::get_array() const
+{
+ return data;
+}
+
+
+inline void
+r_GMarray::set_array( char* newData )
+{
+ // In case the array already has an array allocated, free it first.
+// if (data != NULL) delete [] data;
+ data = newData;
+};
+
+
+
+inline void
+r_GMarray::set_current_format( r_Data_Format newFormat )
+{
+ current_format = newFormat;
+};
+
+
+
+inline r_Bytes
+r_GMarray::get_type_length() const
+{
+ return type_length;
+};
+
+
+
+inline r_Bytes
+r_GMarray::get_array_size() const
+{
+ return data_size;
+};
+
+
+
+inline r_Data_Format
+r_GMarray::get_current_format() const
+{
+ return current_format;
+};
+
+
+
+inline void
+r_GMarray::set_spatial_domain( const r_Minterval& dom )
+{
+ domain = dom;
+};
+
+
+
+inline void
+r_GMarray::set_type_length( r_Bytes newValue )
+{
+ type_length = newValue;
+}
+
+
+
+inline void
+r_GMarray::set_array_size( r_Bytes newValue )
+{
+ data_size = newValue;
+}
diff --git a/rasodmg/interesttiling.cc b/rasodmg/interesttiling.cc
new file mode 100644
index 0000000..aad8841
--- /dev/null
+++ b/rasodmg/interesttiling.cc
@@ -0,0 +1,809 @@
+/*
+* 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: interesttiling.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Interest_Tiling
+ *
+ * COMMENTS:
+ * None
+*/
+
+#include "rasodmg/interesttiling.hh"
+#include "rasodmg/alignedtiling.hh"
+#include "rasodmg/dirdecompose.hh"
+#include "rasodmg/dirtiling.hh"
+#include "raslib/rminit.hh"
+
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+#include <cstdlib>
+
+#ifdef AIX
+#include <strings.h>
+#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_INTERESTTILING_
+
+#ifdef _VISUALIZE_2D_DECOMP_
+#include "tools/visualtiling2d.hh"
+#endif
+
+// This is a data structure for internal use within interesttiling.cc.
+// It is defined here because of problems with ptrepository.
+// -------------
+// This structure consists of a r_Minterval and a counter. Also, it has
+// some auxiliary constructors.
+
+class Classified_Block
+ {
+ public:
+ int intersection_count; // Intersection count
+ r_Minterval block; // The actual block
+
+ // Default constructor
+ Classified_Block(int count = 0);
+
+ // Constructor with the actual block and the counter
+ Classified_Block(const r_Minterval& b, int count = 0);
+
+ // Same data structure (this operator is needed because of dlist)
+ bool operator==(const Classified_Block& other) const;
+
+ // Different data structure (this operator is needed because of dlist)
+ bool operator!=(const Classified_Block& other) const;
+
+ // Friend of std::ostream (this operator is needed because of dlist)
+ friend std::ostream& operator<<(std::ostream& os, const Classified_Block& block);
+ };
+
+const char*
+r_Interest_Tiling::description = "dimensions, areas of interest, tile size (in bytes) and tile size limit [NOLIMIT|REGROUP|SUBTILING|REGROUPSUBTILING] (ex: \"2;[0:9,0:9];[100:109,0:9];100;REGROUPSUBTILING\")";
+
+const char* r_Interest_Tiling::tilesizelimit_name_nolimit ="NOLIMIT";
+const char* r_Interest_Tiling::tilesizelimit_name_regroup ="REGROUP";
+const char* r_Interest_Tiling::tilesizelimit_name_subtiling ="SUBTILING";
+const char* r_Interest_Tiling::tilesizelimit_name_regroupandsubtiling ="REGROUPSUBTILING";
+const char* r_Interest_Tiling::all_tilesizelimit_names[r_Interest_Tiling::NUMBER]={
+ tilesizelimit_name_nolimit,
+ tilesizelimit_name_regroup,
+ tilesizelimit_name_subtiling,
+ tilesizelimit_name_regroupandsubtiling
+ };
+
+r_Interest_Tiling::Tilesize_Limit
+r_Interest_Tiling::get_tilesize_limit_from_name(const char* name)
+{
+
+ if(!name) {
+ RMInit::logOut << "r_Interest_Tiling::get_tilesize_limit_from_name(" << (name?name: "NULL") << ")" << endl;
+ return r_Interest_Tiling::NUMBER;
+ }
+
+ unsigned int i=r_Interest_Tiling::NUMBER;
+
+ for (i=0; i<(unsigned int)r_Interest_Tiling::NUMBER; i++)
+ {
+ if (strcasecmp(name, all_tilesizelimit_names[i]) == 0)
+ break;
+ }
+ return (r_Interest_Tiling::Tilesize_Limit)i;
+}
+
+const char*
+r_Interest_Tiling::get_name_from_tilesize_limit(Tilesize_Limit tsl)
+{
+ static const char* unknown="UNKNOWN";
+ unsigned int idx = (unsigned int)tsl;
+
+ if (idx >= (unsigned int)r_Interest_Tiling::NUMBER)
+ return unknown;
+
+ return all_tilesizelimit_names[idx];
+}
+
+r_Interest_Tiling::r_Interest_Tiling(const char* encoded) throw (r_Error)
+ : r_Dimension_Tiling(0,0)
+{
+ if(!encoded)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << (encoded?encoded: "NULL") << ")" << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ std::vector<r_Minterval> vectInterestAreas;
+ r_Interest_Tiling::Tilesize_Limit tileSizeLimit;
+ r_Dimension tileD=0;
+ r_Bytes tileS=0, lenToConvert=0;
+ const char *pStart=NULL, *pRes=NULL, *pTemp=NULL, *pEnd=NULL;
+ char *pToConvert=NULL;
+
+
+ pStart=encoded;
+ pEnd=pStart+strlen(pStart);
+ pTemp=pStart;
+ pRes=strstr(pTemp,COLON);
+
+ if(!pRes)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding tile dimension from \"" << pTemp << "\"." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with dimension
+ 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_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding tile dimension from \"" << pToConvert << "\"." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if (tileD < 0)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding tile dimension from \"" << pToConvert << "\", is negative." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //skip COLON && free buffer
+ delete[] pToConvert;
+ if(pRes != (pEnd-1))
+ pRes++;
+ else
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding interest areas, end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //parse interest areas
+ pTemp=pRes;
+ pRes=strstr(pTemp,COLON);
+
+ if(!pRes)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding interest areas." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ while(pRes)
+ {
+ //is interest areas?
+ if(*pTemp != *LSQRBRA)
+ break;
+
+ //copy parsed interest area
+ lenToConvert=pRes-pTemp;
+ pToConvert=new char[lenToConvert+1];
+ memcpy(pToConvert, pTemp, lenToConvert);
+ pToConvert[lenToConvert]='\0';
+
+ //add to vector
+ try
+ {
+ r_Minterval a(pToConvert);
+ vectInterestAreas.push_back(a);
+ }
+ catch(r_Error& err)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding interest area from \"" << pToConvert << "\"." << endl;
+ RMInit::logOut << "Error " << err.get_errorno() << " : " << err.what() << endl;
+ delete [] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //skip COLON
+ delete[] pToConvert;
+ if(pRes != (pEnd-1))
+ pRes++;
+ else
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding interest areas, end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //try next item
+ pTemp=pRes;
+ pRes=strstr(pTemp, COLON);
+ }
+
+ if(vectInterestAreas.empty())
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding interest areas, no interest areas specified." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with tile size
+ lenToConvert=pRes-pTemp;
+ pToConvert=new char[lenToConvert+1];
+ memcpy(pToConvert, pTemp, lenToConvert);
+ pToConvert[lenToConvert]='\0';
+
+ tileS=strtol(pToConvert, (char**)NULL, DefaultBase);
+ if (!tileS)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding tile size from \"" << pToConvert << "\"." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if (tileS < 0)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding tile size from \"" << pToConvert << "\", is negative." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //skip COLON && free buffer
+ delete[] pToConvert;
+ if(pRes != (pEnd-1))
+ pRes++;
+ else
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding tile size limit, end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ pTemp=pRes;
+
+ tileSizeLimit=r_Interest_Tiling::get_tilesize_limit_from_name(pTemp);
+ if(tileSizeLimit==r_Interest_Tiling::NUMBER)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << encoded << "): Error decoding tile size limit from \"" << pTemp << "\"." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ iareas = vectInterestAreas;
+ ts_strat = tileSizeLimit;
+ dimension = tileD;
+ tile_size = tileS;
+}
+
+r_Interest_Tiling::r_Interest_Tiling(r_Dimension dim, const std::vector<r_Minterval>& interest_areas, r_Bytes ts, Tilesize_Limit strat) throw (r_Error)
+ : r_Dimension_Tiling(dim, ts),
+ iareas(interest_areas),
+ ts_strat(strat)
+{
+ for (std::vector<r_Minterval>::iterator it = iareas.begin(); it != iareas.end(); it++)
+ if (it->dimension() != dimension)
+ {
+ RMInit::logOut << "r_Interest_Tiling::r_Interest_Tiling(" << dim << ", " << interest_areas << ", " << ts << ", " << strat << ") the interest area domain " << *it << " does not match the dimension of this tiling scheme (" << dimension << ")" << endl;
+ throw r_Edim_mismatch(dimension, it->dimension());
+ }
+}
+
+r_Interest_Tiling::~r_Interest_Tiling()
+{
+}
+
+r_Tiling* r_Interest_Tiling::clone() const
+{
+ r_Tiling* copy = new r_Interest_Tiling(dimension, iareas, tile_size, ts_strat);
+ return copy;
+}
+
+void r_Interest_Tiling::print_status(std::ostream& os) const
+{
+ os << "r_Interest_Tiling[ ";
+ r_Dimension_Tiling::print_status(os);
+ os << " interest areas = " << iareas << ", tiling strategy = " << ts_strat << " ]";
+}
+
+r_Tiling_Scheme
+r_Interest_Tiling::get_tiling_scheme() const
+ {
+ return r_InterestTiling;
+ }
+
+static int r_Range_comp(const void *elem1, const void *elem2)
+{
+ r_Range e1 = *((r_Range*) elem1);
+ r_Range e2 = *((r_Range*) elem2);
+
+ if (e1 == e2)
+ return 0;
+
+ if (e1 < e2)
+ return -1;
+ else
+ return +1;
+}
+
+std::vector<r_Dir_Decompose>*
+r_Interest_Tiling::make_partition(const r_Minterval& domain) const
+{
+ r_Dimension dim = domain.dimension();
+ int total = 2 * iareas.size();
+
+ // We need one decomp from each dimension
+ std::vector<r_Dir_Decompose>* part = new std::vector<r_Dir_Decompose>(dim);
+
+ // We have at most (number of interest areas + 2) intervals
+ r_Range* intervals = new r_Range[total + 2];
+
+ // Create iterator for interest areas
+ std::vector<r_Minterval>::const_iterator it = iareas.begin();
+ int total_iareas = iareas.size();
+
+
+ // For all dimensions
+ for (r_Dimension i = 0; i < dim; i++)
+ {
+ it = iareas.begin(); // Reset iterator
+ intervals[0] = domain[i].low(); // Input lower domain limit
+ intervals[total+1] = domain[i].high(); // Input higher domain limit
+
+
+ for (int j = 1; j < total + 1; j += 2, ++it) // For all possible intervals
+ {
+ if ((*it)[i].low()-1 <= domain[i].low()) // Input low iarea limit
+ intervals[j] = domain[i].low();
+ else
+ intervals[j] = (*it)[i].low()-1;
+
+ intervals[j+1] = (*it)[i].high(); // Input higher iarea limit
+ }
+
+ // Sort the table
+ qsort((void*) intervals, total+2, sizeof(r_Range), r_Range_comp);
+
+ // Create partition using the limits table
+ for (int k=0; k<total+2; k++) // all limits must be checked
+ {
+ if (k == total+1) // if on the last limit...
+ ((*part)[i]) << intervals[k]; // input it
+ else // else
+ if (intervals[k] != intervals[k+1]) // if it is unique
+ ((*part)[i]) << intervals[k]; // input it
+ }
+ }
+
+ // Free memory
+ delete [] intervals;
+
+ // Return result
+ return part;
+}
+
+std::vector<r_Minterval>*
+r_Interest_Tiling::group(std::vector<r_Minterval>& blocks, r_Bytes typelen, Blocks_Type btype) const
+{
+ r_Bytes tilesize = get_tile_size();
+ int joins = 0;
+ bool group_blocks = true;
+
+ // The list of threated blocks
+ std::vector<r_Minterval>* treated = new std::vector<r_Minterval>;
+
+ // An iterator for the blocks list
+ std::vector<r_Minterval>::iterator blocks_it = blocks.begin();
+
+ // The current block
+ r_Minterval current_block;
+
+ // For all the blocks in list
+ while (!blocks.empty())
+ {
+ // Get first block from list
+ current_block = blocks.back();
+ blocks.pop_back();
+
+ //this is neccessary when the compiler optimizes out the .end() check
+ unsigned int numberOfLevels = blocks.size();
+ for (blocks_it = blocks.begin(); blocks_it != blocks.end(); blocks_it++)
+ {
+ if (numberOfLevels == 0)
+ {
+ RMInit::logOut << "r_Interest_Tiling::group() the for loop was incorrectly optimized. breaking the loop." << endl;
+ break;
+ }
+ r_Minterval aux = *blocks_it;
+
+ // In principle two blocks can't be merged
+ group_blocks = false;
+
+ // If they can be merged
+ if (current_block.is_mergeable(aux))
+ {
+ std::vector<r_Minterval>::iterator ia_it = blocks.begin();
+
+ switch (btype)
+ {
+ case BLOCKS_A:
+
+ group_blocks = true;
+
+ // Check if the two blocks belong exaclty to the same iareas
+ for (; ia_it != blocks.end(); ia_it++)
+ {
+ if (aux.intersects_with(*ia_it) != current_block.intersects_with(*ia_it))
+ {
+ group_blocks = false;
+ break;
+ }
+ }
+
+ break;
+
+ case BLOCKS_B:
+
+ for (; ia_it != blocks.end(); ia_it++) // For all iareas
+ {
+ // Find the one this block intersects
+ if (current_block.intersects_with(*ia_it))
+ {
+ // Check if the other area intersects it
+ if (!aux.intersects_with(*ia_it))
+ group_blocks = false;
+ else
+ group_blocks = true;
+
+ break;
+ }
+ }
+
+ if (!group_blocks)
+ break;
+
+ group_blocks = false;
+
+ case BLOCKS_C: // Falls in (this is, also applies to B);
+
+ // Only on this two strategies, tilesize should be looked at
+ if ((ts_strat == REGROUP) || (ts_strat == REGROUP_AND_SUBTILING))
+ {
+ // If the resulting size isn't larger than tilesize
+ if ((current_block.cell_count()+aux.cell_count()) * typelen
+ < get_tile_size())
+ group_blocks = true;
+ }
+ else
+ group_blocks = true;
+
+ break;
+ }
+ }
+
+ // take care of the iterator advance, if is possible
+ if (group_blocks)
+ {
+ // Merge them
+ blocks.erase(blocks_it); // Automatically advances to next block
+ // take care of the size of the blocks
+ numberOfLevels--;
+ current_block.closure_with(aux);
+ ++joins;
+ }
+ else
+ numberOfLevels--;
+ }
+
+ // Update the treated list with the current block
+ treated->push_back(current_block);
+ }
+
+ std::vector<r_Minterval>* result = 0;
+
+ // If there was joins, the algoritm must be repeted
+ if (joins != 0)
+ {
+ result = group(*treated, typelen, btype);
+ delete treated;
+ }
+ else
+ {
+ result = treated;
+ }
+
+ // Return the result
+ return result;
+}
+
+std::vector<r_Minterval>*
+r_Interest_Tiling::compute_tiles(const r_Minterval& domain, r_Bytes typelen) const throw (r_Error)
+{
+ r_Dimension num_dims = domain.dimension(); // Dimensionality of dom
+if (domain.dimension() != dimension)
+ {
+ RMInit::logOut << "r_Interest_Tiling::compute_tiles(" << domain << ", " << typelen << ") dimension (" << dimension << ") does not match dimension of object to tile (" << num_dims << ")" << endl;
+ throw r_Edim_mismatch(dimension, num_dims);
+ }
+if (typelen > tile_size)
+ {
+ RMInit::logOut << "r_Interest_Tiling::compute_tiles(" << domain << ", " << typelen << ") tile size (" << tile_size << ") is smaller than type length (" << typelen << ")" << endl;
+ throw r_Error(TILESIZETOOSMALL);
+ }
+
+#ifdef _VISUALIZE_2D_DECOMP_ // User wants a visual
+ static int count; // Number of decomps
+ ++count; // Update num decomps
+ // of the 2D decomp.
+ Visual_Tiling_2D* vis;
+ if (domain.dimension() == 2)
+ {
+ // Create an object for visualization
+ char fname[80];
+ sprintf(fname, "2D_decomp_int_%d.ppm", count);
+ vis = new Visual_Tiling_2D(domain, fname);
+ }
+
+#endif
+
+
+ // *** Main algoritm ***
+
+ // The result
+ std::vector<r_Minterval>* result = new std::vector<r_Minterval>;
+
+ // Create a partition for dir tiling
+ std::vector<r_Dir_Decompose>* part = make_partition(domain);
+
+ // Perform dirtiling
+ r_Dir_Tiling *dir_tiling= NULL;
+ std::vector<r_Minterval>* dir_domain=NULL;
+
+ try
+ {
+ dir_tiling=new r_Dir_Tiling(num_dims, *part, tile_size, r_Dir_Tiling::WITHOUT_SUBTILING);
+
+ // Compute all tiles (directional tiles)
+ dir_domain = dir_tiling->compute_tiles(domain, typelen);
+
+ delete dir_tiling;
+ }
+ catch(r_Error& err)
+ {
+ delete result;
+ delete part;
+ if(dir_tiling)
+ delete dir_tiling;
+ throw;
+ }
+
+ // Get an interator for interest areas
+ //std::vector<r_Minterval>::iterator interest_area;
+
+ // Create a list for holding the classifed blocks
+ std::vector<Classified_Block> part_domain;
+
+ // Finds how many intersections exist between a block an the interest areas
+ for (std::vector<r_Minterval>::iterator dir_block = dir_domain->begin(); dir_block != dir_domain->end(); dir_block++)
+ {
+ Classified_Block b(*dir_block, 0);
+
+ for (std::vector<r_Minterval>::const_iterator interest_area = iareas.begin(); interest_area != iareas.end(); interest_area++)
+ {
+ if (b.block.intersects_with(*interest_area))
+ ++b.intersection_count;
+ }
+
+ part_domain.push_back(b);
+ }
+
+ // Lists used for grouping blocks
+ std::vector<r_Minterval> Out;
+ std::vector<r_Minterval> In_Unique;
+ std::vector<r_Minterval> In_Common;
+
+ // Divide blocks into lists according to their number of intersections
+ for (std::vector<Classified_Block>::iterator class_block = part_domain.begin(); class_block != part_domain.end(); class_block++)
+ {
+ switch ((*class_block).intersection_count)
+ {
+ case 0:
+ Out.push_back((*class_block).block);
+ break;
+ case 1:
+ In_Unique.push_back((*class_block).block);
+ break;
+ default:
+ In_Common.push_back((*class_block).block);
+ break;
+ }
+ }
+
+
+ // Group blocks
+ std::vector<r_Minterval>* Blocks_A = group(In_Common, typelen, BLOCKS_A);
+ std::vector<r_Minterval>* Blocks_B = group(In_Unique, typelen, BLOCKS_B);
+ std::vector<r_Minterval>* Blocks_C = group(Out, typelen, BLOCKS_C);
+
+
+ std::vector<r_Minterval>::iterator it_A = Blocks_A->begin();
+ std::vector<r_Minterval>::iterator it_B = Blocks_B->begin();
+ std::vector<r_Minterval>::iterator it_C = Blocks_C->begin();
+
+ // If may be necessary to perform sub-tiling
+ if ((ts_strat == SUB_TILING) || (ts_strat == REGROUP_AND_SUBTILING))
+ {
+ // Variable to hold result of sub-tiling
+ std::vector<r_Minterval>* subtiles = 0;
+
+ // We need an array to hold the 3 iterators of the resulting blocks
+ std::vector<r_Minterval>::iterator* blocks_it[3];
+ std::vector<r_Minterval>* blocks_vec[3];
+
+ // Put iterators on the list
+ blocks_it[0] = &it_A;
+ blocks_it[1] = &it_B;
+ blocks_it[2] = &it_C;
+
+ blocks_vec[0] = Blocks_A;
+ blocks_vec[1] = Blocks_B;
+ blocks_vec[2] = Blocks_C;
+
+ // For all the lists (Blocs_A, Blocks_B and Blocks_C)
+ for (int j=0; j<3; j++)
+ {
+ // Reset iterator to the begin
+ (*blocks_it[j]) = blocks_vec[j]->begin();
+
+ // Tile each block if necessary
+ for (; *blocks_it[j] != blocks_vec[j]->end(); (*blocks_it[j])++)
+ {
+ if ((**blocks_it[j]).cell_count()*typelen > get_tile_size())
+ {
+ // Create a specification of a regular n-dim cube grid
+ r_Minterval specs(num_dims);
+ for (r_Dimension i=0; i<num_dims; i++)
+ {
+ specs << r_Sinterval((r_Range)0, (**blocks_it[j])[i].high() - (**blocks_it[j])[i].low());
+ }
+
+ // Class for performing sub-tiling
+ r_Aligned_Tiling subtiling(specs, get_tile_size());
+
+ subtiles = subtiling.compute_tiles(**blocks_it[j], typelen);
+ for (std::vector<r_Minterval>::iterator it = subtiles->begin(); it != subtiles->end(); it++)
+ {
+ result->push_back(*it);
+
+#ifdef _VISUALIZE_2D_DECOMP_
+ if (domain.dimension() == 2)
+ (*vis) << (*it);
+#endif
+ }
+
+ delete subtiles;
+ }
+ else // No subtiling needed
+ {
+ // Insert block as it is
+ result->push_back(**blocks_it[j]);
+
+#ifdef _VISUALIZE_2D_DECOMP_
+ if (domain.dimension() == 2)
+ (*vis) << (**blocks_it[j]);
+#endif
+ }
+ }
+ }
+
+#ifdef _VISUALIZE_2D_DECOMP_
+ if (domain.dimension() == 2)
+ {
+ vis->set_pen(255, 255, 0);
+
+ interest_area.seek_begin();
+ while (interest_area.not_done())
+ {
+ (*vis) << (*interest_area);
+ ++interest_area;
+ }
+ }
+#endif
+
+ }
+ else
+ {
+ // The result is just the sum of all blocks
+
+ result->insert(result->end(), Blocks_A->begin(), Blocks_A->end());
+ result->insert(result->end(), Blocks_B->begin(), Blocks_B->end());
+ result->insert(result->end(), Blocks_C->begin(), Blocks_C->end());
+
+ // Visualization
+
+#ifdef _VISUALIZE_2D_DECOMP_
+ if (domain.dimension() == 2)
+ {
+ vis->set_pen(255, 255, 0);
+ for (it_A.seek_begin(); it_A.not_done(); it_A++)
+ (*vis) << *it_A;
+
+ vis->set_pen(0, 255, 0);
+ for (it_B.seek_begin(); it_B.not_done(); it_B++)
+ (*vis) << *it_B;
+
+ vis->set_pen(0, 0, 255);
+ for (it_C.seek_begin(); it_C.not_done(); it_C++)
+ (*vis) << *it_C;
+ }
+#endif
+ }
+
+ // *** End of the main algorithm ***
+
+ // *** Clean up ***
+
+ delete part;
+ delete dir_domain;
+ delete Blocks_A;
+ delete Blocks_B;
+ delete Blocks_C;
+
+#ifdef _VISUALIZE_2D_DECOMP_
+ if (domain.dimension() == 2)
+ delete vis;
+#endif
+
+ // Return result
+
+ return result;
+}
+
+
+
+std::ostream& operator<<(std::ostream& os, const Classified_Block block);
+
+
+Classified_Block::Classified_Block(int count)
+ : intersection_count(count)
+ {
+ }
+
+Classified_Block::Classified_Block(const r_Minterval& b, int count)
+ : intersection_count(count),
+ block(b)
+ {
+ }
+
+
+bool Classified_Block::operator==(const Classified_Block& other) const
+{
+ return (this->block == other.block)
+ && (this->intersection_count == other.intersection_count);
+}
+
+bool Classified_Block::operator!=(const Classified_Block& other) const
+{
+ return !(*this == other);
+}
+
+
+std::ostream& operator<<(std::ostream& os, const Classified_Block block)
+{
+ os << "CBlock(" << block.intersection_count << "x: " << block.block << ")";
+
+ return os;
+}
diff --git a/rasodmg/interesttiling.hh b/rasodmg/interesttiling.hh
new file mode 100644
index 0000000..944ada8
--- /dev/null
+++ b/rasodmg/interesttiling.hh
@@ -0,0 +1,183 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: dirtiling.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Interest_Tiling
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_INTERESTTILING_HH_
+#define _R_INTERESTTILING_HH_
+
+class r_Dir_Decompose;
+class r_Interest_Tiling;
+#include "rasodmg/tiling.hh"
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+ This class implements the "Interesting Areas" tiling algorithm.
+ The user specifies which areas are of interest to him and tiling is
+ performed accordingly.
+
+ Example of usage:
+ The user says that [10:20, 50:60] and [18:50, 65:70] are of interest
+ to him in the [0:1000, 0:1000] domain. Tiling should be done according
+ to this setting. To specify this with this class the following code
+ would work:
+
+ ...
+
+ r_Minterval domain(2);
+ domain << r_Sinterval(0L, 1000L) << r_Sinterval(0L, 1000L);
+
+ r_Minteval interest1(2);
+ interest1 << r_Sinterval(10L, 20L) << r_Sinterval(50L, 60L);
+
+ r_Minterval interest2(2);
+ interest2 << r_Sinterval(18L, 50L) << r_Sinterval(65L, 70L);
+
+ std::vector<r_Minterval> interest_areas;
+ interest_areas.insert_element(interest1);
+ interest_areas.insert_element(interest2);
+
+ r_Interest_Tiling(interest_areas);
+
+ ...
+*/
+
+class r_Interest_Tiling : public r_Dimension_Tiling
+{
+ public:
+
+ /// Possible strategies to limit the tilesize
+ enum Tilesize_Limit {NO_LIMIT, REGROUP, SUB_TILING, REGROUP_AND_SUBTILING, NUMBER};
+
+ /// read everything from an encoded string
+ /// e.g. "2;[0:9,0:9];[100:109,0:9];100;REGROUPSUBTILING"
+ r_Interest_Tiling(const char* encoded) throw (r_Error);
+
+ r_Interest_Tiling(r_Dimension dim,
+ const std::vector<r_Minterval>& interest_areas,
+ r_Bytes ts = RMInit::clientTileSize,
+ Tilesize_Limit strat = SUB_TILING) throw (r_Error);
+ /**
+ It takes as parameter a list containing the areas of interest to
+ the user and also the tilesize to be used.
+ The constructor also takes as parameter the tilesize limitation
+ strategy, that can be the following:
+
+ NO_LIMIT: The generated blocks can have any size.
+ REGROUP: Only when performing grouping/merging of blocks, the
+ size of the resulting block of two merges is checked
+ against tilesize. If it's bigger, they are not merged.
+ Blocks larger than tilesize may exist (for instance,
+ if the user specifies an interest area larger then
+ tilesize).
+ SUB_TILING: In this strategie, regrouping is done regardless of the
+ size of the generated blocks. After all the blocks are
+ created, sub-tiling is performed on those whose size is
+ larger than tilesize.
+ REGROUP_AND_SUBTILING: This combines the last two strategies. When
+ merging blocks, blocks larger than tilesize are never
+ created and, when the final blocks are all created,
+ sub-tiling is performed on those whose size is larger
+ then tilesize.
+ An exception is thrown when the dimensions of the domains does not match the
+ specified dimension.
+ */
+
+ virtual ~r_Interest_Tiling();
+
+ std::vector<r_Minterval>* compute_tiles(const r_Minterval& obj_domain, r_Bytes cell_size) const throw (r_Error);
+
+ virtual void print_status(std::ostream& os) const;
+
+ virtual r_Tiling* clone() const;
+
+ virtual r_Tiling_Scheme get_tiling_scheme() const;
+
+ //@ManMemo: Module: {\bf raslib}
+ /**
+ Get a tilesize limit for a tilisize limit name
+ */
+ static r_Interest_Tiling::Tilesize_Limit get_tilesize_limit_from_name(const char* name);
+ //@ManMemo: Module: {\bf raslib}
+ /**
+ Get a tilisize limit name for a tilesize limit
+ */
+ static const char* get_name_from_tilesize_limit(Tilesize_Limit tsl);
+
+ static const char* description;
+
+ protected: // methods.
+
+ /// Given a domain and a set of interest areas (internal) gener. partition
+ std::vector<r_Dir_Decompose>* make_partition(const r_Minterval& domain) const;
+
+ /// The Block types (A, B or C)
+ enum Blocks_Type {BLOCKS_A, BLOCKS_B, BLOCKS_C };
+ /**
+ A Blocks ---> Blocks that belong to two or more interest zones
+ (non-groupable)
+ B Blocks ---> Blocks within the same interest zone
+ (groupable by interest zone)
+ C Blocks ---> Blocks outside interest zones
+ (groupable)
+ */
+
+ /// Merge as many blocks together in a list as possible
+ std::vector<r_Minterval>* group(std::vector<r_Minterval>& blocks, r_Bytes typelen, Blocks_Type btype) const;
+ /**
+ Parameters: the block list, the lenght of the base cells and
+ the type of the block (A, B or C)
+ */
+
+ /// Tilesize limitation strategie
+ Tilesize_Limit ts_strat;
+
+ /// Interest areas
+ std::vector<r_Minterval> iareas;
+
+
+ //@ManMemo: Module: {\bf raslib}
+ /**
+ The names of all tilesizelimit types, to avoid redundant storage and inconsistencies.
+ The variable name convention is the prefix tilisizelimit_name_ followed by the name
+ of the data format in lower case, i.e. for NOLIMIT tilisizelimit_name_nolimit.
+ In addition there's an array of names all_tilesizelimit_names where the tilesize limit
+ can be used as index to get the name.
+ */
+ static const char* tilesizelimit_name_nolimit;
+ static const char* tilesizelimit_name_regroup;
+ static const char* tilesizelimit_name_subtiling;
+ static const char* tilesizelimit_name_regroupandsubtiling;
+
+ static const char* all_tilesizelimit_names[r_Interest_Tiling::NUMBER];
+};
+
+#endif
diff --git a/rasodmg/iterator.cc b/rasodmg/iterator.cc
new file mode 100644
index 0000000..cd9e167
--- /dev/null
+++ b/rasodmg/iterator.cc
@@ -0,0 +1,216 @@
+/*
+* 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: iterator.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Iterator
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsiditerator[] = "@(#)rasodmg, r_Iterator: $Id: iterator.cc,v 1.18 2002/08/23 11:18:44 schatz Exp $";
+
+#include <iostream>
+using namespace std;
+
+#include "rasodmg/iterator.hh"
+
+#ifdef EARLY_TEMPLATE
+#ifndef __EXECUTABLE__
+#define __EXECUTABLE__
+#define ITERATOR_NOT_SET
+#endif
+#endif
+
+#include "rasodmg/collection.hh"
+
+#ifdef ITERATOR_NOT_SET
+#undef __EXECUTABLE__
+#endif
+
+template<class T>
+r_Iterator<T>::r_Iterator()
+{
+ // use default constructor only with assignment operator!
+ collection = 0;
+ ptr = 0;
+ ndone = 0;
+}
+
+template<class T>
+r_Iterator<T>::r_Iterator( const r_Iterator<T>& iter )
+{
+ collection = iter.collection;
+ ptr = iter.ptr;
+ ndone = iter.ndone;
+}
+
+template<class T>
+r_Iterator<T>::r_Iterator( r_Collection<T>& source, int removed_objects )
+{
+ collection = &source;
+ // sorry for this awful cast but there is
+ // no standard conversion of r_Collection<T>::CNode* to r_Collection::CNode*
+ if( removed_objects )
+ ptr = (typename r_Collection<T>::CNode*)source.removed_objects;
+ else
+ ptr = (typename r_Collection<T>::CNode*)source.coll;
+
+ ndone = (ptr->elem != 0);
+}
+
+template<class T>
+r_Iterator<T>::~r_Iterator()
+{
+}
+
+template<class T>
+r_Iterator<T>&
+r_Iterator<T>::operator=( const r_Iterator<T>& iter )
+{
+ if( this != &iter )
+ {
+ collection = iter.collection;
+ ptr = iter.ptr;
+ ndone = iter.ndone;
+ }
+
+ return *this;
+}
+
+template<class T>
+int
+r_Iterator<T>::is_equal(const r_Iterator<T>& iter) const
+{
+ if ( collection == iter.collection)
+ if ( ptr == iter.ptr )
+ return 1;
+ return 0;
+}
+
+
+template<class T>
+int
+operator==( const r_Iterator<T>& iter1, const r_Iterator<T>& iter2 )
+{
+ return iter1.is_equal(iter2);
+}
+
+template<class T>
+int
+operator!=( const r_Iterator<T>& iter1, const r_Iterator<T>& iter2 )
+{
+ return !iter1.is_equal(iter2);
+}
+
+template<class T>
+r_Iterator<T>&
+r_Iterator<T>::operator++()
+{
+ // ++prefix operator
+
+ if ( !ndone )
+ throw r_Error( r_Error::r_Error_IteratorExhausted );
+ if ( ptr->next != 0 )
+ ptr = ptr->next;
+ else
+ ndone = 0;
+
+ return *this;
+}
+
+template<class T>
+r_Iterator<T>
+r_Iterator<T>::operator++( int )
+{
+ // postfix++ operator
+ // create a copy of this, increment the original and return the copy
+ r_Iterator<T> result( *this );
+
+ operator++();
+
+ return result;
+}
+
+template<class T>
+T
+r_Iterator<T>::operator*()
+ throw( r_Error )
+{
+ if ( !ndone || ptr->elem == 0 )
+ {
+ r_Error err = r_Error( r_Error::r_Error_IteratorExhausted );
+ throw err;
+ }
+
+ // The following line was return *(ptr->elem) but the HP compiler had problems
+ // while instantiating the code. CNode::elem was of a different type than T.
+ return *((T*)ptr->elem);
+}
+
+template<class T>
+T
+r_Iterator<T>::get_element() const
+ throw( r_Error )
+{
+ if ( !ndone || ptr->elem == 0 )
+ throw r_Error( r_Error::r_Error_IteratorExhausted );
+ else
+ return *(ptr->elem);
+}
+
+template<class T>
+int
+r_Iterator<T>::next( T& element )
+{
+ if ( !ndone || ptr->elem == 0 ) return 0;
+ element = *(ptr->elem);
+ advance();
+ return 1;
+}
+
+template<class T>
+void
+r_Iterator<T>::reset( int removed_objects )
+{
+ if( removed_objects )
+ ptr = (typename r_Collection<T>::CNode*)collection->removed_objects;
+ else
+ ptr = (typename r_Collection<T>::CNode*)collection->coll;
+
+ ndone = (ptr->elem != 0);
+}
+
+template<class T>
+void
+r_Iterator<T>::advance()
+{
+ if ( !ndone )
+ throw r_Error( r_Error::r_Error_IteratorExhausted );
+ if ( ptr->next != 0 )
+ ptr = ptr->next;
+ else
+ ndone = 0;
+}
diff --git a/rasodmg/iterator.hh b/rasodmg/iterator.hh
new file mode 100644
index 0000000..995e7b6
--- /dev/null
+++ b/rasodmg/iterator.hh
@@ -0,0 +1,137 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: iterator.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Iterator
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_ITERATOR_
+#define _D_ITERATOR_
+
+#include "raslib/error.hh"
+
+#ifdef __VISUALC__
+template <class T> class r_Collection;
+#else
+#include "rasodmg/collection.hh"
+#endif
+
+//@ManMemo: Module: {\bf rasodmg}
+
+
+
+/*@Doc:
+
+ The template class \Ref{r_Iterator} defines the generic
+ behavior for iteration. All iterators use a consistent protocol
+ for sequentially returning each element from the collection over
+ which the iteration is defined.
+ When an iterator is constructed, it is either initialized with
+ another iterator or is set to null. When an iterator is constructed
+ via the {\tt create_iterator()} method defined in \Ref{r_Collection},
+ the iterator is initailized to point to the first element, if there
+ is one.
+*/
+
+template <class T>
+class r_Iterator
+{
+ public:
+ /// default constructor
+ r_Iterator();
+ /// copy constructor
+ r_Iterator( const r_Iterator<T>& iter );
+ /// constructor getting the collection on which to iterate (used for {\tt r_Collection::create_iterator()})
+ r_Iterator( r_Collection<T>& source, int removed_objects=0 );
+ /**
+ Creates an iterator which points to the first element of the element collection. If
+ {\tt removed_objects} ist set to 1, the iterator points to the first element of
+ the list containing the removed objects (for internal use).
+ */
+
+ /// destructor
+ ~r_Iterator();
+
+ /// assignment operator
+ r_Iterator<T>& operator=( const r_Iterator<T>& iter );
+ /// comparisons: equal if they point to the same element in the same collection,
+ /// not equal if they point to different collections or elements
+ int is_equal( const r_Iterator<T>& iter ) const;
+
+ /// prefix incrementor
+ r_Iterator<T>& operator++();
+ /// postfix incrementor
+ r_Iterator<T> operator++( int );
+
+ /// re-initialize the iterator to the start of iteration for the same collection
+ void reset( int removed_objects=0 );
+ /**
+ Resets the iterator to point to the first element of the element collection. If
+ {\tt removed_objects} ist set to 1, the iterator points to the first element of
+ the list containing the removed objects (for internal use).
+ */
+
+ /// returns 1 if there are more elements to be visited in the iteration and 0 if iteration is complete
+ inline int not_done() const;
+ /// advances one element
+ void advance();
+
+ /// the dereference operator gets the actual element
+ T operator*() throw( r_Error );
+ /// gets the actual element
+ T get_element() const throw( r_Error );
+
+ /// gets the actual element, advances one element, and returns whether iteration is complete or not
+ int next( T& element );
+
+ /// replaces the actual element (can only be used with r_List)
+ void replace_element( const T& element );
+
+ private:
+ /// flag for end of iteration
+ int ndone;
+ /// pointer to the collection on which is iterated
+ r_Collection<T>* collection;
+ /// pointer to the actual element
+ typename r_Collection<T>::CNode* ptr;
+
+};
+
+#include "iterator.icc"
+
+#ifdef EARLY_TEMPLATE
+#ifdef __EXECUTABLE__
+#ifdef __VISUALC__
+#include "iterator.cpp"
+#else
+#include "iterator.cc"
+#endif
+#endif
+#endif
+
+#endif
diff --git a/rasodmg/iterator.icc b/rasodmg/iterator.icc
new file mode 100644
index 0000000..5bd4974
--- /dev/null
+++ b/rasodmg/iterator.icc
@@ -0,0 +1,39 @@
+/*
+* 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>.
+/
+/**
+ * INLINE SOURCE: iterator.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Iterator
+ *
+ * COMMENTS:
+ * None
+*/
+
+
+template<class T>
+inline int
+r_Iterator<T>::not_done() const
+{
+ return ndone;
+}
diff --git a/rasodmg/marray.cc b/rasodmg/marray.cc
new file mode 100644
index 0000000..403c91f
--- /dev/null
+++ b/rasodmg/marray.cc
@@ -0,0 +1,354 @@
+/*
+* 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: marray.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Marray
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsidmarray[] = "@(#)rasodmg, r_Marray: $Id: marray.cc,v 1.36 2002/08/23 11:18:44 schatz Exp $";
+
+#include "rasodmg/marray.hh"
+
+#ifdef __VISUALC__
+#ifndef __EXECUTABLE__
+#define __EXECUTABLE__
+#define MARRAY_NOT_SET
+#endif
+#endif
+
+#include "rasodmg/database.hh"
+#include "clientcomm/clientcomm.hh"
+
+#ifdef COLLECTION_NOT_SET
+#undef __EXECUTABLE__
+#endif
+
+#include "raslib/rmdebug.hh"
+
+#include <string.h> // for memcpy()
+#include <iostream>
+#include <iomanip>
+
+
+
+template<class T>
+r_Marray<T>::r_Marray() throw(r_Error)
+ : r_GMarray()
+{
+}
+
+
+
+template<class T>
+r_Marray<T>::r_Marray( const r_Minterval& initDomain, r_Storage_Layout* stl ) throw(r_Error)
+ : r_GMarray( initDomain, sizeof(T), stl )
+{
+}
+
+
+
+template<class T>
+r_Marray<T>::r_Marray( const r_Minterval& initDomain, const T& value, r_Storage_Layout* stl ) throw(r_Error)
+ : r_GMarray( initDomain, sizeof(T), stl )
+{
+ T* dataPtr = (T*)data;
+
+ for( unsigned long i=0; i<domain.cell_count(); i++ )
+ dataPtr[i] = value;
+}
+
+
+
+template<class T>
+r_Marray<T>::r_Marray( const r_Minterval& initDomain, r_InitFunction function, r_Storage_Layout* stl ) throw(r_Error)
+ : r_GMarray( initDomain, sizeof(T), stl )
+{
+ r_Dimension d;
+ int done = 0;
+ r_Point pt( domain.dimension() );
+
+ // memory pointer of type T
+ T* dataPtr = (T*)data;
+
+ // initialize the iterating point to the lowest values in each dimension
+ for( d=0; d<pt.dimension(); d++ )
+ pt[d] = domain[d].low();
+
+ // iterate point pt through the spatial domain and apply the
+ // initializing function for each point
+ while(!done)
+ {
+ // execute function on cell
+ dataPtr[domain.cell_offset( pt )] = (*function)( pt );
+
+ // increment coordinate
+ d = 0;
+ while( ++pt[d] > domain[d].high() )
+ {
+ pt[d] = domain[d].low();
+ d++;
+ if(d >= domain.dimension())
+ {
+ done = 1;
+ break;
+ }
+ }
+ }
+}
+
+
+
+template<class T>
+r_Marray<T>::r_Marray( const r_Marray<T> &obj ) throw(r_Error)
+ : r_GMarray( obj )
+{
+ RMDBCLASS( "r_Marray<T>", "r_Marray<T>( const r_Marray<T>& )", "rasodmg", __FILE__, __LINE__ )
+}
+
+
+
+template<class T>
+r_Marray<T>::r_Marray( r_GMarray &obj ) throw(r_Error)
+ : r_GMarray( obj )
+{
+}
+
+
+
+template<class T>
+r_Marray<T>::~r_Marray()
+{
+}
+
+
+
+template<class T>
+const r_Marray<T> &r_Marray<T>::operator=( const r_Marray<T> &marray )
+{
+ return (r_Marray<T> &) r_GMarray::operator=( marray );
+}
+
+
+
+template<class T>
+r_Marray<T>
+r_Marray<T>::operator[] ( long cordnt ) const
+ throw( r_Eindex_violation )
+{
+ // check if self does not just represent a cell
+ if( domain.dimension() == 0 )
+ throw( r_Eindex_violation( cordnt, 0, 0 ) );
+
+ // check if the index is valid
+ if( cordnt < domain[0].low() || cordnt > domain[0].high() )
+ throw( r_Eindex_violation( cordnt, domain[0].low(), domain[0].high() ) );
+
+ // build a new spatial domain
+ r_Minterval newDomain( domain.dimension()-1 );
+
+ // and initialize it
+ for( int i=0; i<newDomain.dimension(); i++ )
+ newDomain[i] = domain[i+1];
+
+ // build a new Marray
+ r_Marray<T> newMDD( newDomain );
+
+ // and fill it with data
+ unsigned long newCellCount = newDomain.cell_count();
+ unsigned long byteCount = ( newDomain.dimension() ? newDomain.cell_count() : 1 ) * type_length;
+ T* dataPtr = (T*)data; // typed pointer to the data
+
+ memcpy( newMDD.data, &(dataPtr[(cordnt-domain[0].low())*newCellCount]), (unsigned int)byteCount );
+
+ return newMDD;
+}
+
+
+
+template<class T>
+r_Marray<T>
+r_Marray<T>::operator[] ( const r_Minterval& mint ) const
+ throw( r_Edim_mismatch )
+{
+ unsigned long offset;
+ r_Point pt;
+ int pt_valid;
+
+ // first test dimensionality
+ if( domain.dimension() != mint.dimension() )
+ throw( r_Edim_mismatch( domain.dimension(), mint.dimension() ) );
+
+ // build a new Marray with undefined cells
+ r_Marray<T> newMDD( mint );
+ T* typedDataPtr = (T*)newMDD.data;
+
+ // iterate through the domain and fill the values where available
+ for( offset=0; offset<mint.cell_count(); offset++ )
+ {
+ pt = mint.cell_point(offset);
+
+ // Test if pt is a valid index in the spatial domain of the
+ // self object.
+ pt_valid = 1;
+ for( int dim=0; dim<domain.dimension() && pt_valid; dim++ )
+ pt_valid &= pt[dim] >= domain[dim].low() && pt[dim] <= domain[dim].high();
+
+ if( pt_valid )
+ typedDataPtr[offset] = operator[](pt);
+
+ // The points where pt_valid is not true are undefined, so nothing has to be
+ // done in the catch clause.
+ // Attention: Purify is reporting that unitialized memory is read when accessing
+ // these points.
+ }
+
+ return newMDD;
+}
+
+
+
+template<class T>
+const T&
+r_Marray<T>::operator[] ( const r_Point& point ) const
+ throw( r_Edim_mismatch, r_Eindex_violation )
+{
+ // first test dimensionality
+ if( point.dimension() != domain.dimension() )
+ throw( r_Edim_mismatch( point.dimension(), domain.dimension() ) );
+
+ T* typedDataPtr = (T*)data;
+
+ try
+ {
+ return typedDataPtr[ domain.cell_offset( point ) ];
+ }
+ catch( ... ) // exception can be r_Eindex_violation
+ {
+ throw; // rethrow it
+ }
+}
+
+
+
+template<class T>
+T&
+r_Marray<T>::operator[] ( const r_Point& point )
+ throw( r_Edim_mismatch, r_Eindex_violation )
+{
+ // first test dimensionality
+ if( point.dimension() != domain.dimension() )
+ throw( r_Edim_mismatch( point.dimension(), domain.dimension() ) );
+
+ T* typedDataPtr = (T*)data;
+
+ try
+ {
+ return typedDataPtr[ domain.cell_offset( point ) ];
+ }
+ catch( ... ) // exception can be r_Eindex_violation
+ {
+ throw; // rethrow it
+ }
+}
+
+
+
+template<class T>
+r_Marray<T>::operator T()
+ throw( r_Eno_cell )
+{
+ // check if the spatial domain of self is really zero
+ if( domain.dimension() > 0 || data == 0 )
+ throw r_Eno_cell();
+
+ return *((T*)data);
+}
+
+
+
+template<class T>
+void
+r_Marray<T>::print_status( std::ostream& s ) const
+{
+ r_GMarray::print_status( s );
+
+ /*
+
+ The following code part prints the content of the array by piping
+ each cell into the specified output stream. This implementation needs
+ the stream operator to be defined for each template type T.
+
+ if( domain.dimension() )
+ {
+ r_Point p(domain.dimension());
+ int done = 0;
+ r_Dimension i = 0;
+
+ // initialize point
+ for(i = 0; i < domain.dimension(); i++)
+ p << domain[i].low();
+
+ s << "Domain: " << domain << endl;
+
+ // iterate over all cells
+ while(!done)
+ {
+ // print cell
+ // if( hex_output )
+ // s << setw(8) << hex << (int)operator[]( p );
+ // else
+ s << setw(8) << operator[]( p );
+
+
+ // increment coordinate
+ i = 0;
+ while( ++p[i] > domain[i].high() )
+ {
+ s << endl;
+ p[i] = domain[i].low();
+ i++;
+ if(i >= domain.dimension())
+ {
+ done = 1;
+ break;
+ }
+ }
+ if(i > 1) s << endl;
+ }
+ }
+ else
+ // print cell
+ // if( hex_output )
+ // s << "Cell value " << setw(8) << hex << (int)*((T*)data) << endl;
+ // else
+ s << "Cell value " << setw(8) << *((T*)data) << endl;
+ */
+}
+
+
+
diff --git a/rasodmg/marray.hh b/rasodmg/marray.hh
new file mode 100644
index 0000000..8b5e5ea
--- /dev/null
+++ b/rasodmg/marray.hh
@@ -0,0 +1,145 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: marray.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Marray
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_MARRAY_
+#define _D_MARRAY_
+
+#include "rasodmg/gmarray.hh"
+
+#include <iostream>
+
+using namespace std;
+
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ The central class of the library for representing an MDD
+ object is named r_Marray. Through overloading operators,
+ the handling of an MDD object is similar to the usage of
+ a normal C or C++ array from the programmers point of view.
+
+*/
+
+template<class T>
+class r_Marray : public r_GMarray
+{
+ public:
+ /// function type for initialization function
+ typedef T (*r_InitFunction)(const r_Point&);
+
+ /// default constructor (no memory is allocated!)
+ r_Marray() throw(r_Error);
+
+ /// constructor for uninitialized MDD objects
+ r_Marray( const r_Minterval&, r_Storage_Layout* stl = 0 ) throw(r_Error);
+ /**
+ If a storage layout pointer is provided, the object refered to is
+ taken and memory control moves to the \Ref{r_Marray} class.
+ The user has to take care, that each creation of \Ref{r_Marray}
+ objects get a new storage layout object.
+ */
+
+ /// constructor for constant MDD objects
+ r_Marray( const r_Minterval&, const T&, r_Storage_Layout* stl = 0 ) throw(r_Error);
+ /**
+ If a storage layout pointer is provided, the object refered to is
+ taken and memory control moves to the \Ref{r_Marray} class.
+ The user has to take care, that each creation of \Ref{r_Marray}
+ objects get a new storage layout object.
+ */
+
+ /// constructor with initializing function
+ r_Marray( const r_Minterval&, r_InitFunction, r_Storage_Layout* stl = 0 ) throw(r_Error);
+ /**
+ If a storage layout pointer is provided, the object refered to is
+ taken and memory control moves to the \Ref{r_Marray} class.
+ The user has to take care, that each creation of \Ref{r_Marray}
+ objects get a new storage layout object.
+ */
+
+ /// copy constructor
+ r_Marray( const r_Marray<T>& ) throw(r_Error);
+
+ /// constructor getting an object of type r_GMarray
+ r_Marray( r_GMarray& ) throw(r_Error);
+ /*
+ This constructor is used for converting general \Ref{r_GMarray} objects
+ to cell type safe \Ref{r_Marray} objects. Care has to be taken because
+ the memory of the \Ref{r_GMarray} can not be used anymore; it is passed
+ to the \Ref{r_Marray<T>} object.
+ */
+
+ /// destructor
+ virtual ~r_Marray();
+
+ /// assignment: cleanup + copy
+ const r_Marray& operator= ( const r_Marray& );
+
+ /// subscript operator for projection in the 1st dimension
+ r_Marray<T> operator[]( long ) const
+ throw(r_Eindex_violation);
+
+ /// subscript operator for restriction/extension combination
+ r_Marray<T> operator[]( const r_Minterval& ) const
+ throw( r_Edim_mismatch );
+
+ /// subscript operator for read access of a cell
+ const T& operator[]( const r_Point& ) const
+ throw(r_Edim_mismatch, r_Eindex_violation);
+
+ /// subscript operator for write access of a cell
+ T& operator[]( const r_Point& )
+ throw(r_Edim_mismatch, r_Eindex_violation);
+
+ /// cast operator for converting to base type for cell access
+ operator T()
+ throw( r_Eno_cell );
+
+ /// writes the state of the object to the specified stream
+ virtual void print_status( std::ostream& s = cout ) const;
+};
+
+#include "rasodmg/marray.icc"
+
+#ifdef EARLY_TEMPLATE
+#ifdef __EXECUTABLE__
+#ifdef __VISUALC__
+#include "rasodmg/marray.cpp"
+#else
+#include "rasodmg/marray.cc"
+#endif
+#endif
+#endif
+
+#endif
diff --git a/rasodmg/marray.icc b/rasodmg/marray.icc
new file mode 100644
index 0000000..98796a3
--- /dev/null
+++ b/rasodmg/marray.icc
@@ -0,0 +1,31 @@
+/*
+* 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>.
+/
+/**
+ * INLINE SOURCE: marray.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Marray
+ *
+ * COMMENTS:
+ * None
+*/
diff --git a/rasodmg/object.cc b/rasodmg/object.cc
new file mode 100644
index 0000000..8b047dd
--- /dev/null
+++ b/rasodmg/object.cc
@@ -0,0 +1,603 @@
+/*
+* 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: object.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Object
+ *
+ * COMMENTS:
+ * None
+*/
+
+#include "mymalloc/mymalloc.h"
+
+static const char rcsid[] = "@(#)rasodmg, r_Object: $Id: object.cc,v 1.37 2002/08/19 14:09:32 schatz Exp $";
+
+#include "raslib/rmdebug.hh"
+#include "raslib/type.hh"
+#include "raslib/error.hh"
+
+#include "rasodmg/object.hh"
+
+#ifdef __VISUALC__
+#ifndef __EXECUTABLE__
+#define __EXECUTABLE__
+#define OBJECT_NOT_SET
+#endif
+#endif
+
+#include "rasodmg/transaction.hh"
+#include "rasodmg/database.hh"
+#include "clientcomm/clientcomm.hh"
+
+#ifdef OBJECT_NOT_SET
+#undef __EXECUTABLE__
+#endif
+
+#include <iostream>
+
+
+// At the beginning, next and last object types/status are not specified.
+r_Object::ObjectStatus r_Object::next_object_status = r_Object::no_status;
+r_Object::ObjectType r_Object::next_object_type = r_Object::no_object;
+char* r_Object::next_object_type_name = 0;
+r_OId r_Object::next_object_oid = r_OId();
+r_Object::ObjectType r_Object::last_object_type = r_Object::no_object;
+
+
+
+r_Object::r_Object()
+ : object_status( next_object_status ),
+ object_name(0),
+ type_name(0),
+ type_structure(0),
+ type_schema(0),
+ oid()
+{
+ RMDBCLASS( "r_Object", "r_Object()", "rasodmg", __FILE__, __LINE__ )
+
+ if( next_object_type_name ) type_name = strdup( next_object_type_name );
+
+ if( next_object_type == persistent_object )
+ RMInit::logOut << "Error: A peristent object is constructed with default constructor." << std::endl;
+ else
+ object_type = transient_object;
+
+ internal_obj_type = 0;
+
+ // reset next object type/status
+ r_Object::next_object_type = no_object;
+ r_Object::next_object_status = no_status;
+ r_Object::next_object_type_name = 0;
+ r_Object::next_object_oid = r_OId();
+}
+
+
+
+r_Object::r_Object( unsigned short objType ) throw(r_Error)
+ : object_status( next_object_status ),
+ object_name(0),
+ type_name(0),
+ type_structure(0),
+ type_schema(0),
+ oid()
+{
+ RMDBCLASS( "r_Object", "r_Object( unsigned short )", "rasodmg", __FILE__, __LINE__ )
+
+ if( next_object_type_name ) type_name = strdup( next_object_type_name );
+
+ if( next_object_type == persistent_object )
+ {
+ if( r_Transaction::actual_transaction == 0 )
+ {
+ RMInit::logOut << "Error: Tried to create a persistent object outside a transaction." << std::endl;
+ throw r_Error(r_Error::r_Error_TransactionNotOpen);
+ }
+
+ object_type = persistent_object;
+
+ switch( object_status )
+ {
+ case created:
+ // In case the object is newly created, get a new oid and assign it to the object.
+ oid = r_Database::actual_database->get_new_oid( objType );
+ break;
+ case read:
+ case transient:
+ // In case the object is read from db, use the oid stored in next_object_oid.
+ oid = next_object_oid;
+ break;
+ default:
+ RMDBGONCE(0, RMDebug::module_raslib, "r_Object", "r_Object(objType) bad object_status " << object_status);
+ break;
+ }
+
+ // Add the object to the list of persistent objects in the current transaction.
+ if( oid.is_valid() )
+ r_Transaction::actual_transaction->add_object_list( r_Ref<r_Object>( oid, this ) );
+ else
+ r_Transaction::actual_transaction->add_object_list( r_Ref<r_Object>( this ) );
+
+ }
+ else
+ object_type = transient_object;
+
+ internal_obj_type = objType;
+
+ // reset next object type/status
+ r_Object::next_object_type = no_object;
+ r_Object::next_object_status = no_status;
+ r_Object::next_object_type_name = 0;
+ r_Object::next_object_oid = r_OId();
+}
+
+
+
+/* OBSOLETE
+r_Object::r_Object( unsigned short objType, const char* name ) throw(r_Error)
+ : object_status( next_object_status ),
+ object_name( strdup(name) ),
+ type_name(0),
+ type_structure(0),
+ type_schema(0),
+ oid()
+{
+ RMANDEBUGOUT( "r_Object::r_Object( const char* name)" )
+
+ if( next_object_type_name ) type_name = strdup( next_object_type_name );
+
+ if( next_object_type == persistent_object )
+ {
+ if( r_Transaction::actual_transaction == 0 )
+ {
+ RMInit::logOut << "Error: Tried to create a persistent object outside a transaction." << std::endl;
+ throw r_Error(r_Error::r_Error_TransactionNotOpen);
+ }
+
+ object_type = persistent_object;
+
+ // get a new oid and assign it to the object
+ // oid = r_Database::actual_database->get_new_oid( objType );
+
+ // add the object to the list of persistent objects in the actual transaction
+ r_Transaction::actual_transaction->add_object_list( r_Ref<r_Object>( this ) );
+ }
+ else
+ object_type = transient_object;
+
+ // reset next object type/status
+ r_Object::next_object_type = no_object;
+ r_Object::next_object_status = no_status;
+ r_Object::next_object_type_name = 0;
+ r_Object::next_object_oid = r_OId();
+}
+*/
+
+
+r_Object::r_Object( const r_Object& obj, unsigned short objType ) throw(r_Error)
+ : object_status( next_object_status ),
+ object_name(0),
+ type_name(0),
+ type_structure(0),
+ type_schema(0),
+ oid()
+{
+ RMDBCLASS( "r_Object", "r_Object( const r_Object& )", "rasodmg", __FILE__, __LINE__ )
+
+ if( next_object_type_name ) type_name = strdup( next_object_type_name );
+
+ if( next_object_type == persistent_object )
+ {
+ if( r_Transaction::actual_transaction == 0 )
+ {
+ RMInit::logOut << "Error: Tried to create a persistent object outside a transaction." << std::endl;
+ throw r_Error(r_Error::r_Error_TransactionNotOpen);
+ }
+
+ object_type = persistent_object;
+
+ switch( object_status )
+ {
+ case created:
+ // In case the object is newly created, get a new oid and assign it to the object.
+ oid = r_Database::actual_database->get_new_oid( objType );
+ break;
+ case read:
+ case transient:
+ // In case the object is read from db, use the oid stored in next_object_oid.
+ oid = next_object_oid;
+ break;
+ default:
+ RMDBGONCE(0, RMDebug::module_raslib, "r_Object", "r_Object(obj, objType) bad object_status " << object_status);
+ break;
+ }
+
+ // Add the object to the list of persistent objects in the actual transaction.
+ if( oid.is_valid() )
+ r_Transaction::actual_transaction->add_object_list( r_Ref<r_Object>( oid, this ) );
+ else
+ r_Transaction::actual_transaction->add_object_list( r_Ref<r_Object>( this ) );
+ }
+ else
+ object_type = transient_object;
+
+ internal_obj_type = objType;
+
+ // reset next object type/status
+ r_Object::next_object_type = no_object;
+ r_Object::next_object_status = no_status;
+ r_Object::next_object_type_name = 0;
+ r_Object::next_object_oid = r_OId();
+
+ if( obj.object_name )
+ object_name = strdup( obj.object_name );
+
+ if( obj.type_name && !type_name )
+ type_name = strdup( obj.type_name );
+
+ if( obj.type_structure )
+ type_structure = strdup( obj.type_structure );
+}
+
+void
+r_Object::set_type_schema(const r_Type* tyy) throw (r_Error)
+ {
+ if (type_schema)
+ {
+ RMInit::logOut << "r_Object::set_type_schema(" << tyy->name() << ") this object has already a type" << std::endl;
+ throw r_Error(ILLEGALARGUMENT);
+ }
+ type_schema = tyy->clone();
+ }
+
+
+/*************************************************************
+ * Method name...: ~r_Object()
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: Destructor.
+ ************************************************************/
+
+r_Object::~r_Object()
+{
+ RMDBCLASS( "r_Object", "~r_Object()", "rasodmg", __FILE__, __LINE__ )
+
+ // Free memory in the transient case. In the persistent case, r_deactivate()
+ // is invoked at the commit/abort point.
+ if( test_type( transient_object ) )
+ r_deactivate();
+
+ object_status = deleted;
+
+ // store the object type for the delete operator
+ r_Object::last_object_type = object_type;
+}
+
+
+
+/*************************************************************
+ * Method name...: r_deactivate()
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: This method is called when the object leaves
+ * the application cache. It frees all dynamic
+ * memory allocated within the class.
+ ************************************************************/
+void
+r_Object::r_deactivate()
+{
+ RMDBCLASS( "r_Object", "r_deactivate()", "rasodmg", __FILE__, __LINE__ )
+
+ if( type_schema )
+ {
+ delete type_schema;
+ type_schema = 0;
+ }
+
+ if( object_name )
+ {
+ free( object_name );
+ object_name = 0;
+ }
+
+ if( type_name )
+ {
+ free( type_name );
+ type_name = 0;
+ }
+
+ if( type_structure )
+ {
+ delete [] type_structure;
+ type_structure = 0;
+ }
+
+ oid.r_deactivate();
+}
+
+
+
+/*************************************************************
+ * Method name...: operator new( size_t size )
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: New operator set the next_object_type and
+ * allocates memory for the object.
+ ************************************************************/
+void*
+r_Object::operator new( size_t size )
+{
+ RMDBCLASS( "r_Object", "operator new( size_t )", "rasodmg", __FILE__, __LINE__ )
+
+ r_Object::next_object_type = transient_object;
+ r_Object::next_object_status = created;
+ r_Object::next_object_type_name = 0;
+ r_Object::next_object_oid = r_OId();
+
+ void* a = mymalloc( size );
+ return a;
+}
+
+
+
+/*************************************************************
+ * Method name...: operator new( size_t size,
+ * r_Database *database,
+ * const char* type_name )
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: New operator set the next_object_type and
+ * allocates memory for the object.
+ ************************************************************/
+void*
+r_Object::operator new( size_t size, r_Database* /*database*/, const char* type_name )
+{
+ RMDBCLASS( "r_Object", "operator new( size_t, r_Database, const char* )", "rasodmg", __FILE__, __LINE__ )
+
+ r_Object::next_object_type = persistent_object;
+ r_Object::next_object_status = created;
+ r_Object::next_object_type_name = (char*)type_name;
+ r_Object::next_object_oid = r_OId();
+
+ void* a = mymalloc( size );
+ return a;
+}
+
+
+
+void*
+r_Object::operator new( size_t size, const char* type_name )
+{
+ RMDBCLASS( "r_Object", "operator new( size_t, const char* )", "rasodmg", __FILE__, __LINE__ )
+
+ r_Object::next_object_type = transient_object;
+ r_Object::next_object_status = created;
+ r_Object::next_object_type_name = (char*)type_name;
+ r_Object::next_object_oid = r_OId();
+
+ void* a = mymalloc( size );
+ return a;
+}
+
+
+
+/*************************************************************
+ * Method name...: operator delete( void* obj_ptr )
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: Delete operator.
+ * Transient objects are deleted immediately from
+ * main memory.
+ * Persistent objects have been marked as deleted in
+ * the destructor. Further accesses through a r_Ref raise
+ * an exception. Main memory is freed after the transaction
+ * commits.
+ ************************************************************/
+void
+r_Object::operator delete( void* obj_ptr )
+{
+ RMDBCLASS( "r_Object", "operator delete()", "rasodmg", __FILE__, __LINE__ )
+
+ if( r_Object::last_object_type == transient_object )
+ free( obj_ptr );
+
+ r_Object::last_object_type = no_object;
+}
+
+
+
+/*************************************************************
+ * Method name...: test_status( ObjectStatus status )
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: Tests if status matches the object status. If so
+ * in returns 1, otherwise 0.
+ ************************************************************/
+int
+r_Object::test_status( ObjectStatus status )
+{
+ return ( status == object_status );
+}
+
+
+
+/*************************************************************
+ * Method name...: test_type( ObjectType type )
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: Tests if type matches the object type. If so
+ * in returns 1, otherwise 0.
+ ************************************************************/
+int
+r_Object::test_type( ObjectType type )
+{
+ return ( type == object_type );
+}
+
+
+
+/*************************************************************
+ * Method name...: operator new( size_t size,
+ * r_Database *database,
+ * ObjectStatus status )
+ *
+ * Arguments.....:
+ * none
+ * Return value..:
+ * none
+ * Description...: New operator set the next_object_type to
+ * persistent object and the next_object_status to the
+ * given status. Memory for the object is allocated.
+ ************************************************************/
+void*
+r_Object::operator new( size_t size, r_Database* /*database*/, ObjectStatus status, const r_OId& oid )
+{
+ RMDBCLASS( "r_Object", "operator new( size_t, r_Database, ObjectStatus )", "rasodmg", __FILE__, __LINE__ )
+
+ r_Object::next_object_type = persistent_object;
+ r_Object::next_object_status = status;
+ r_Object::next_object_type_name = 0;
+ r_Object::next_object_oid = oid;
+
+ void* a = mymalloc( size );
+ return a;
+}
+
+
+
+const r_Type*
+r_Object::get_type_schema()
+{
+ if( !type_schema )
+ {
+ // If type structure not known then try to get it from the server
+ if ( (type_structure == NULL) || (strlen(type_structure) == 0) )
+ {
+ ClientComm::r_Type_Type typeType = (ClientComm::r_Type_Type)0;
+
+ // we need an open database and an active transaction
+ if ( r_Database::actual_database == NULL ) return NULL;
+ else
+ {
+ if ( r_Database::actual_database->get_status() == r_Database::not_open )
+ return NULL;
+ }
+ if ( r_Transaction::actual_transaction == NULL) return NULL;
+ else
+ {
+ if ( r_Transaction::actual_transaction->get_status() != r_Transaction::active )
+ return NULL;
+ }
+
+ // set the object type and contact the database if the type name is defined.
+ if ( internal_obj_type == 1 ) typeType = ClientComm::r_MDDType_Type;
+ else if ( internal_obj_type == 2 ) typeType = ClientComm::r_SetType_Type;
+ if ( (type_name == NULL) || (strlen(type_name) == 0) || (typeType == 0) )
+ return NULL;
+
+ try {
+ type_structure = r_Database::actual_database->getComm()->getTypeStructure( type_name, typeType );
+ }
+ catch(r_Error& errObj) {
+ RMInit::logOut << "r_Object::get_type_schema() failed retriving typestructure" << std::endl;
+ RMInit::logOut << "Error " << errObj.get_errorno() << " : " << errObj.what() << std::endl;
+ return NULL;
+ }
+ }
+
+ type_schema = r_Type::get_any_type( type_structure );
+ }
+ return type_schema;
+}
+
+
+
+void
+r_Object::update_obj_in_db()
+{
+ RMInit::logOut << " dummy implementation " << std::flush;
+}
+
+
+
+void
+r_Object::load_obj_from_db()
+{
+ RMInit::logOut << " dummy implementation " << std::flush;
+}
+
+
+
+void
+r_Object::delete_obj_from_db()
+{
+ RMDBCLASS( "r_Object", "delete_obj_from_db()", "rasodmg", __FILE__, __LINE__ )
+
+ if( object_name && strlen( object_name ) )
+ {
+ RMInit::logOut << object_name << "... " << std::flush;
+
+ // delete myself from the database
+ r_Database::actual_database->getComm()->deleteCollByName( object_name );
+ }
+ else
+ {
+ RMInit::logOut << "no name - take oid ... " << std::flush;
+
+ if( oid.get_local_oid() )
+ // delete myself from the database
+ r_Database::actual_database->getComm()->deleteObjByOId( oid );
+ else
+ RMInit::logOut << " no oid ... FAILED" << std::flush;
+ }
+}
+
+
+void
+r_Object::initialize_oid( const r_OId& initOId )
+{
+ oid = initOId;
+}
+
diff --git a/rasodmg/object.hh b/rasodmg/object.hh
new file mode 100644
index 0000000..d5fcbeb
--- /dev/null
+++ b/rasodmg/object.hh
@@ -0,0 +1,240 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: object.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Object
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_OBJECT_
+#define _D_OBJECT_
+
+#include "raslib/error.hh"
+#include "raslib/oid.hh"
+#include "raslib/rminit.hh"
+
+#include <stdlib.h>
+
+// forward declarations
+class r_Database;
+class r_Type;
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ Through inheritance of this class, the type definer specifies that
+ the subclass is capable of having persistent as well as transient
+ instances.
+
+ {\bf Attention: }Right now, just the classes \Ref{r_Set} and \Ref{r_Marray}
+ inherit from \Ref{r_Object} which, therefore, are the only persistent
+ capable classes. In fact, just objects of type {\tt r_Set<r_Ref<r_Marray<...>>>}
+ can be made persitent right now.
+
+*/
+
+class r_Object
+{
+ public:
+ /// default constructor
+ r_Object();
+
+ /// constructor getting objType
+ r_Object( unsigned short objType ) throw(r_Error);
+ /**
+ {\tt objType} specifies the type of the object (1=Marray, 2=Collection).
+ This is needed for oid allocation and propably dropped in future.
+ */
+
+ /// copy constructor
+ r_Object( const r_Object&, unsigned short objType=0 ) throw(r_Error);
+ /**
+ {\tt objType} specifies the type of the object (1=Marray, 2=Collection).
+ This is needed for oid allocation and propably dropped in future.
+ */
+
+ /// virtual destructor
+ virtual ~r_Object();
+
+ /// mark the object as modified
+ inline void mark_modified();
+
+ /// new operator for transient objects
+ void* operator new( size_t size );
+
+ /// new operator for persistent objects
+ void* operator new( size_t size, r_Database *database, const char* type_name = 0 );
+
+ /// new operator for transient objects carrying type information
+ void* operator new( size_t size, const char* type_name );
+
+ /// delete operator
+ void operator delete( void* obj_ptr );
+
+ /// set object type by name
+ inline void set_type_by_name( const char* name ) throw(r_Error);
+ /**
+ With this method a type name has to be given by the user for each
+ object which he wants to make persistent. The type name is the name
+ introduced in the RasDL file. If an object without a valid type
+ name is made persistent, an error occurs while committing the
+ transaction.
+
+ NOTE: This method is updated. Use {\tt void* operator new( size_t size,
+ r_Database *database, const char* type_name )} instead.
+ */
+
+ /// set object type by name
+ inline void set_type_structure( const char* name ) throw(r_Error);
+
+ /// get object type name
+ inline const char* get_type_name() const;
+
+ /// get object type structure
+ inline const char* get_type_structure() const;
+
+ /// get oid
+ inline const r_OId& get_oid() const;
+
+ /// get type schema
+ const r_Type* get_type_schema();
+
+ void set_type_schema(const r_Type* type) throw (r_Error);
+
+ //@Man: Methods and types for internal use only:
+ //@{
+ ///
+
+ /// object life status
+ enum ObjectStatus { no_status, deleted, created, modified, read, transient };
+ /**
+ created - The object was created in the current transaction and has to be stored in the database.
+ deleted - The object was deleted. It is still in main memory and in the database. It is going to
+ be removed at the end of the transaction.
+ modified - Object was modified and has to be updated in the database.
+ read - The object was read from the database without modifying it afterwards.
+ transient - The object belongs to a declarative query result. In most cases, it has no persistent
+ counterpart in the db. It is NOT considered in the update phase.
+ */
+
+ /// object types
+ enum ObjectType { no_object, persistent_object, transient_object };
+
+ ///
+ /// inserts an object into the database
+ virtual void insert_obj_into_db()=0;
+ /// inserts an object into a specific collection in the database
+ virtual void insert_obj_into_db( const char* )=0;
+ /// updates an object in database
+ virtual void update_obj_in_db();
+ /// load an object from the database
+ virtual void load_obj_from_db();
+ /// deletes an object from the database
+ void delete_obj_from_db();
+
+ ///
+ /// initialize oid of the object
+ void initialize_oid( const r_OId& initOId );
+
+ ///
+ /// it is called when an object comes into transient memory
+ virtual void r_activate() {;};
+ /// it is called when an object leaves transient memory
+ virtual void r_deactivate();
+
+ ///
+ /// test object status returns 1 if it matches
+ int test_status( ObjectStatus status );
+ /// gets the status of the object
+ inline ObjectStatus get_status() const;
+
+ ///
+ /// set object name. object name should contain only [a-zA-Z0-9_]
+ inline void set_object_name( const char* name ) throw(r_Error);
+ /// get object name
+ inline const char* get_object_name() const;
+
+ ///
+ /// new operator for activating an object (status = read)
+ void* operator new( size_t size, r_Database *database, ObjectStatus status, const r_OId& oid );
+
+ ///
+ //@}
+
+ protected:
+ /// test object type returns 1 if it matches
+ int test_type( ObjectType type );
+
+ /// stores object name if it has one
+ char* object_name;
+
+ /// stores object type name if it has one
+ char* type_name;
+
+ /// store type structure as string if it has one
+ char* type_structure;
+
+ /// pointer to type schema (built on request)
+ r_Type* type_schema;
+
+ /// internal object type (1 marray, 2 collection)
+ unsigned short internal_obj_type;
+
+ private:
+ /// right now, the object life status is either deleted, created, or read
+ ObjectStatus object_status;
+
+ /// persistent_object or transient_object
+ ObjectType object_type;
+
+ /// object identifier
+ r_OId oid;
+
+ /// holds the next object type between new operation and constructor
+ static ObjectType next_object_type;
+
+ /// holds the next object status between new operation and constructor
+ static ObjectStatus next_object_status;
+
+ /// holds the next object type name between new operation and constructor
+ static char* next_object_type_name;
+
+ /// holds the next object oid between new operation and constructor
+ static r_OId next_object_oid;
+
+ /// holds the last object type between destructor and delete operator
+ static ObjectType last_object_type;
+};
+
+#include "rasodmg/object.icc"
+
+#endif
+
+
+
+
diff --git a/rasodmg/object.icc b/rasodmg/object.icc
new file mode 100644
index 0000000..b210d95
--- /dev/null
+++ b/rasodmg/object.icc
@@ -0,0 +1,151 @@
+/*
+* 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>.
+/
+/**
+ * INLINE SOURCE: object.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Object
+ *
+ * COMMENTS:
+ * None
+*/
+
+#include <string.h>
+
+
+inline void
+r_Object::mark_modified()
+{
+ if( object_status == no_status ||
+ object_status == read )
+ object_status = modified;
+};
+
+
+
+inline void
+r_Object::set_object_name( const char* name ) throw(r_Error)
+{
+ if(!name) {
+ //null pointer
+ RMInit::logOut << "r_Object::set_object_name(name) name is null!" << std::endl;
+ throw r_Error(INVALIDOBJECTNAME);
+ }
+
+ const char* cptr=name;
+
+ //check if the name contains only [a-zA-Z0-9_]
+ while(*cptr) {
+ if( ((*cptr >= 'a') && (*cptr <='z')) ||
+ ((*cptr >= 'A') && (*cptr <='Z')) ||
+ ((*cptr >= '0') && (*cptr <='9')) ||
+ (*cptr == '_') )
+ cptr++;
+ else
+ break;
+ }
+
+ if(*cptr) {
+ //invalid character in object name
+ RMInit::logOut << "r_Object::set_object_name(" << name << ") invalid name!" << std::endl;
+ throw r_Error(INVALIDOBJECTNAME);
+ }
+
+ if( object_name )
+ free( object_name );
+
+ object_name = strdup( name );
+};
+
+
+inline void
+r_Object::set_type_by_name( const char* name ) throw(r_Error)
+{
+ if(!name) {
+ //null pointer
+ RMInit::logOut << "r_Object::set_type_by_name(name) name is null!" << std::endl;
+ throw r_Error(r_Error:: r_Error_NameInvalid);
+ }
+
+ if( type_name )
+ free( type_name );
+
+ type_name = strdup( name );
+};
+
+
+inline void
+r_Object::set_type_structure( const char* name ) throw(r_Error)
+{
+ if(!name) {
+ //null pointer
+ RMInit::logOut << "r_Object::type_structure(name) name is null!" << std::endl;
+ throw r_Error(r_Error:: r_Error_NameInvalid);
+ }
+
+ if( type_structure )
+ delete [] type_structure;
+
+ type_structure = new char[strlen(name) + 1];
+ strcpy(type_structure, name);
+};
+
+
+inline const char*
+r_Object::get_type_name() const
+{
+ return type_name;
+};
+
+
+inline const char*
+r_Object::get_object_name() const
+{
+ return object_name;
+}
+
+
+inline const char*
+r_Object::get_type_structure() const
+{
+ if (type_structure != NULL)
+ return type_structure;
+ else
+ return "";
+};
+
+
+inline r_Object::ObjectStatus
+r_Object::get_status() const
+{
+ return object_status;
+};
+
+
+inline const r_OId&
+r_Object::get_oid() const
+{
+ return oid;
+}
+
+
diff --git a/rasodmg/oqlquery.cc b/rasodmg/oqlquery.cc
new file mode 100644
index 0000000..4b1a3f1
--- /dev/null
+++ b/rasodmg/oqlquery.cc
@@ -0,0 +1,628 @@
+/*
+* 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: oqlquery.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_OQL_Query
+ * FUNCTION: r_oql_execute()
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsid[] = "@(#)rasodmg, r_OQL_Query and r_oql_execute(): $Id: oqlquery.cc,v 1.25 2002/08/28 12:21:57 coman Exp $";
+
+#include "rasodmg/oqlquery.hh"
+
+#include <string.h>
+#include <ctype.h> // isdigit()
+#ifdef __VISUALC__
+#include <strstrea.h>
+#else
+#include <strstream>
+#endif
+
+#ifdef __VISUALC__
+#ifndef __EXECUTABLE__
+#define __EXECUTABLE__
+#define OQLQUERY_NOT_SET
+#endif
+#endif
+
+#include "rasodmg/database.hh"
+#include "rasodmg/transaction.hh"
+#include "rasodmg/set.hh"
+#include "rasodmg/gmarray.hh"
+
+#include "raslib/rmdebug.hh"
+#include "clientcomm/clientcomm.hh"
+
+#ifdef OQLQUERY_NOT_SET
+#undef __EXECUTABLE__
+#endif
+
+r_OQL_Query::r_OQL_Query()
+ : queryString(0),
+ parameterizedQueryString(0),
+ mddConstants(0)
+{
+}
+
+
+r_OQL_Query::r_OQL_Query( const char* s )
+ : queryString(0),
+ mddConstants(0)
+{
+ parameterizedQueryString = new char[strlen(s)+1];
+ strcpy( parameterizedQueryString, s );
+
+ reset_query();
+}
+
+
+r_OQL_Query::r_OQL_Query( const r_OQL_Query& q )
+ : queryString(0),
+ parameterizedQueryString(0),
+ mddConstants(0)
+{
+ // copy the query string
+ if(q.queryString) {
+ queryString = new char[strlen(q.queryString)+1];
+ strcpy( queryString, q.queryString);
+ }
+
+ // copy the parameterized query string
+ if(q.parameterizedQueryString) {
+ parameterizedQueryString = new char[strlen(q.parameterizedQueryString)+1];
+ strcpy( parameterizedQueryString, q.parameterizedQueryString );
+ }
+
+ if( q.mddConstants ) {
+ mddConstants = new r_Set< r_GMarray* >( *(q.mddConstants) );
+ }
+}
+
+
+r_OQL_Query::~r_OQL_Query()
+{
+ if( queryString )
+ delete[] queryString;
+ queryString = 0;
+
+ if( parameterizedQueryString )
+ delete[] parameterizedQueryString;
+ parameterizedQueryString = 0;
+
+ if( mddConstants )
+ delete mddConstants;
+ mddConstants = 0;
+}
+
+
+const r_OQL_Query&
+r_OQL_Query::operator=( const r_OQL_Query& q )
+{
+ if( this != &q )
+ {
+ // clean up and copy the query string
+
+ if( queryString )
+ {
+ delete[] queryString;
+ queryString = 0;
+ }
+
+ if( q.queryString )
+ {
+ queryString = new char[strlen(q.queryString)+1];
+ strcpy( queryString, q.queryString );
+ }
+
+ if( mddConstants )
+ {
+ delete mddConstants;
+ mddConstants = 0;
+ }
+
+ if( q.mddConstants )
+ {
+ mddConstants = new r_Set< r_GMarray* >( *(q.mddConstants) );
+ }
+
+ // clean up and copy the parameterized query string
+ if( parameterizedQueryString )
+ {
+ delete[] parameterizedQueryString;
+ parameterizedQueryString = 0;
+ }
+
+ if( q.parameterizedQueryString )
+ {
+ parameterizedQueryString = new char[strlen(q.parameterizedQueryString)+1];
+ strcpy( parameterizedQueryString, q.parameterizedQueryString );
+ }
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( const char* s ) throw( r_Error )
+{
+ try
+ {
+ replaceNextArgument( s );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_Char c ) throw( r_Error )
+{
+ char valueString[2];
+
+ valueString[0] = c;
+ valueString[1] = '\0';
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_Short s ) throw( r_Error )
+{
+ char valueString[256];
+
+ std::ostrstream valueStream( valueString, 256 );
+
+ valueStream << s << std::ends;
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_UShort us ) throw( r_Error )
+{
+ char valueString[256];
+
+ std::ostrstream valueStream( valueString, 256 );
+
+ valueStream << us << std::ends;
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_Long l ) throw( r_Error )
+{
+ char valueString[256];
+
+ std::ostrstream valueStream( valueString, 256 );
+
+ valueStream << l << std::ends;
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_ULong ul ) throw( r_Error )
+{
+ char valueString[256];
+
+ std::ostrstream valueStream( valueString, 256 );
+
+ valueStream << ul << std::ends;
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_Point pt ) throw( r_Error )
+{
+ char valueString[256];
+
+ std::ostrstream valueStream( valueString, 256 );
+
+ valueStream << pt << std::ends;
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_Sinterval in ) throw( r_Error )
+{
+ char valueString[256];
+
+ std::ostrstream valueStream( valueString, 256 );
+
+ valueStream << in << std::ends;
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_Minterval in ) throw( r_Error )
+{
+ char valueString[256];
+
+ std::ostrstream valueStream( valueString, 256 );
+
+ valueStream << in << std::ends;
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ return *this;
+}
+
+
+r_OQL_Query&
+r_OQL_Query::operator<<( r_GMarray& in ) throw( r_Error )
+{
+ // determine number of next mdd (starting with 0)
+ unsigned long mddNo = 0;
+ if( mddConstants )
+ mddNo = mddConstants->cardinality();
+
+ char valueString[256];
+ std::ostrstream valueStream( valueString, 256 );
+ valueStream << "#MDD" << mddNo << "#" << std::ends;
+
+ try
+ {
+ replaceNextArgument( valueString );
+ }
+ catch( ... )
+ {
+ throw;
+ }
+
+ // save reference to in
+ if( !mddConstants )
+ mddConstants = new r_Set< r_GMarray* >();
+
+ mddConstants->insert_element( &in );
+
+ return *this;
+}
+
+
+
+
+int
+r_OQL_Query::is_update_query() const
+{
+ return !is_retrieval_query();
+}
+
+
+
+int
+r_OQL_Query::is_retrieval_query() const
+{
+ int returnValue = 0;
+
+ if( parameterizedQueryString )
+ returnValue = strstr( parameterizedQueryString, "select" ) ||
+ strstr( parameterizedQueryString, "SELECT" );
+
+ return returnValue;
+}
+
+
+
+void
+r_OQL_Query::reset_query()
+{
+ if( queryString )
+ delete[] queryString;
+
+ queryString = new char[strlen(parameterizedQueryString)+1];
+ strcpy( queryString, parameterizedQueryString );
+
+ if( mddConstants )
+ {
+ delete mddConstants;
+ mddConstants = 0;
+ }
+}
+
+
+void
+r_OQL_Query::replaceNextArgument( const char* valueString )
+ throw( r_Error )
+{
+ char* argumentBegin=NULL;
+ char* argumentEnd=NULL;
+ char* argumentVal=NULL;
+ int argumentLength=0;
+ char* tmpString=NULL;
+ int length=0;
+
+ // locate the next argument in the query string
+
+ argumentBegin = argumentEnd = strchr( queryString, '$' );
+
+ if( !argumentBegin )
+ {
+ r_Error err = r_Error( r_Error::r_Error_QueryParameterCountInvalid );
+ throw err;
+ }
+
+ // while( *argumentEnd != ' ' && *argumentEnd != '\0' )
+ argumentEnd++;
+
+ //is digit or invalid argument format
+ if(!isdigit(*argumentEnd))
+ throw r_Error( QUERYPARAMETERINVALID );
+
+ while( isdigit(*argumentEnd) && *argumentEnd != ' ' && *argumentEnd != '\0' )
+ argumentEnd++;
+
+ argumentLength = argumentEnd - argumentBegin;
+ argumentVal = new char[ argumentLength + 1];
+ strncpy(argumentVal, argumentBegin, argumentLength);
+ argumentVal[argumentLength] = '\0';
+
+ while(true)
+ {
+ // allocate a new query string and fill it
+ tmpString = queryString;
+ length = strlen(queryString) - argumentLength + strlen(valueString);
+ queryString = new char[ length + 1 ];
+
+ *argumentBegin = '\0';
+ std::ostrstream queryStream( queryString, length + 1 );
+
+ queryStream << tmpString << valueString << argumentEnd << std::ends;
+
+ //update the reference
+ argumentEnd=queryString+strlen(tmpString)+strlen(valueString);
+
+ //remove buffer
+ delete[] tmpString;
+
+ //search again for this parameter
+ argumentEnd = argumentBegin = strstr( argumentEnd, argumentVal );
+
+ //end string?
+ if(argumentBegin == NULL)
+ break;
+
+ //skip $
+ argumentEnd++;
+
+ //is digit or invalid argument format
+ if(!isdigit(*argumentEnd))
+ {
+ delete [] argumentVal;
+ throw r_Error( QUERYPARAMETERINVALID );
+ }
+
+ //skip digits
+ while( isdigit(*argumentEnd) && *argumentEnd != ' ' && *argumentEnd != '\0' )
+ argumentEnd++;
+ }
+
+ delete[] argumentVal;
+}
+
+
+
+// HP COMPILER BUG
+// The iterator type needs a typedef because otherwise the compiler creates a duplicate
+// definition for each instance of the following template function.
+typedef r_Iterator<r_GMarray*> r_Iterator_r_GMarray;
+
+void r_oql_execute( r_OQL_Query& query, r_Set< r_Ref_Any > &result )
+ throw( r_Error )
+{
+ if( r_Database::actual_database == 0 || r_Database::actual_database->get_status() == r_Database::not_open )
+ {
+ r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
+ throw err;
+ }
+
+ if( r_Transaction::actual_transaction == 0 || r_Transaction::actual_transaction->get_status() != r_Transaction::active )
+ {
+ r_Error err = r_Error( r_Error::r_Error_TransactionNotOpen );
+ throw err;
+ }
+
+ try
+ {
+ r_Database::actual_database->getComm()->executeQuery( query, result );
+ }
+ catch( ... )
+ {
+ throw; // re-throw the exception
+ }
+
+ // reset the arguments of the query object
+ query.reset_query();
+}
+
+
+
+void r_oql_execute( r_OQL_Query& query, r_Set< r_Ref< r_GMarray > > &result )
+ throw( r_Error )
+{
+ if( r_Database::actual_database == 0 || r_Database::actual_database->get_status() == r_Database::not_open )
+ {
+ r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
+ throw err;
+ }
+
+ if( r_Transaction::actual_transaction == 0 || r_Transaction::actual_transaction->get_status() != r_Transaction::active )
+ {
+ r_Error err = r_Error( r_Error::r_Error_TransactionNotOpen );
+ throw err;
+ }
+
+ try
+ {
+ r_Set< r_Ref_Any > genericSet;
+
+
+ r_Database::actual_database->getComm()->executeQuery( query, genericSet );
+
+ const r_Type* typeSchema = genericSet.get_element_type_schema();
+
+ if( !typeSchema || typeSchema->type_id() != r_Type::MARRAYTYPE )
+ {
+ r_Error err( r_Error::r_Error_TypeInvalid );
+ throw err;
+ }
+
+ //
+ // iterate through the generic set and build a specific one
+ //
+ result.set_type_by_name( genericSet.get_type_name() );
+ result.set_type_structure( genericSet.get_type_structure() );
+
+ r_Iterator< r_Ref_Any > iter;
+ for( iter=genericSet.create_iterator(); iter.not_done(); iter++ )
+ result.insert_element( r_Ref<r_GMarray>(*iter) );
+ }
+ catch( ... )
+ {
+ throw; // re-throw the exception
+ }
+
+ // reset the arguments of the query object
+ query.reset_query();
+}
+
+
+
+void r_oql_execute( r_OQL_Query& query )
+ throw( r_Error )
+{
+ if( r_Database::actual_database == 0 || r_Database::actual_database->get_status() == r_Database::not_open )
+ {
+ r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
+ throw err;
+ }
+
+ if( r_Transaction::actual_transaction == 0 || r_Transaction::actual_transaction->get_status() != r_Transaction::active )
+ {
+ r_Error err = r_Error( r_Error::r_Error_TransactionNotOpen );
+ throw err;
+ }
+
+ try
+ {
+ r_Database::actual_database->getComm()->executeQuery( query );
+ }
+ catch( ... )
+ {
+ throw; // re-throw the exception
+ }
+
+ // reset the arguments of the query object
+ query.reset_query();
+}
+
diff --git a/rasodmg/oqlquery.hh b/rasodmg/oqlquery.hh
new file mode 100644
index 0000000..8da0935
--- /dev/null
+++ b/rasodmg/oqlquery.hh
@@ -0,0 +1,251 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: oqlquery.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_OQL_Query
+ * FUNCTION: r_oql_execute()
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_OQL_QUERY_
+#define _D_OQL_QUERY_
+
+#include "raslib/error.hh"
+
+#include "raslib/odmgtypes.hh"
+#include "rasodmg/marray.hh"
+#include "raslib/point.hh"
+#include "raslib/sinterval.hh"
+#include "raslib/minterval.hh"
+
+template <class T> class r_Set;
+template <class T> class r_Ref;
+class r_Ref_Any;
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ The global function \Ref{r_oql_execute} is used to invoke RasML
+ queries. The query statement is represented through an object
+ of class \Ref{r_OQL_Query} which is the first argument of the function.
+ The constructor gets a parameterized query string where #$i#
+ indicates the i-th parameter. The overloaded stream input
+ operators allows to insert the parameter values to the query, at
+ the same time preserving their respective types. If any of the
+ #$i# are not followed by a right operant construction argument at
+ the point \Ref{r_oql_execute} is called, a \Ref{r_Error} exception object
+ of kind {\tt r_Error_QueryParameterCountInvalid} is thrown.
+ Once a query has been executed via \Ref{r_oql_execute}, the arguments
+ associated with the #$i# parameters are cleared and new arguments
+ must be supplied.
+
+ The copy constructor and assignment operator copy all the underlying
+ data structures associated with the query, based upon the parameters
+ that have been passed to the query at the point the operation is
+ performed.
+
+ The stream operators raise a \Ref{r_Error} exception of type
+ {\tt r_Error_QueryParameterCountInvalid} if the number of arguments is
+ exceeded.
+
+*/
+
+class r_OQL_Query
+{
+ public:
+ /// default constructor
+ r_OQL_Query();
+
+ /// constructor getting the query string
+ r_OQL_Query( const char* s );
+
+ /// copy constructor
+ r_OQL_Query( const r_OQL_Query& q );
+
+ /// destructor
+ ~r_OQL_Query();
+
+ /// assignment operator
+ const r_OQL_Query& operator=( const r_OQL_Query& q );
+
+ //@Man: Stream input operators for every parameter type:
+ //@{
+ ///
+ r_OQL_Query& operator<<( const char* s ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_Char c ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_Short s ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_UShort us ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_Long l ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_ULong ul ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_Point pt ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_Sinterval in ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_Minterval in ) throw( r_Error );
+ ///
+ r_OQL_Query& operator<<( r_GMarray& in ) throw( r_Error );
+ ///
+ //@}
+
+ /// returns true if the current query is an update one
+ int is_update_query() const;
+
+ /// returns true if the current query is an update one
+ int is_retrieval_query() const;
+
+ //@Man: Methods for internal use:
+ //@{
+ /// resets the expandation of the query string
+ void reset_query();
+ /// gets the expanded query string
+ inline const char* get_query() const;
+ /// get mdd constants
+ inline const r_Set< r_GMarray* >* get_constants() const;
+ /// gets the parameterized query string
+ inline const char* get_parameterized_query() const;
+ ///
+ //@}
+
+ private:
+ /// method replaces the next argument with the delivered valueString
+ void replaceNextArgument( const char* valueString ) throw( r_Error );
+
+ /// storage for the expanded query string
+ char* queryString;
+
+ /// storage for the parameterized query string
+ char* parameterizedQueryString;
+
+ /// list for MDD constants
+ r_Set< r_GMarray* >* mddConstants;
+};
+
+
+
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+ The free standing function \Ref{r_oql_execute} is called to execute a retrieval query.
+ The first parameter, {\tt query}, is a reference to a \Ref{r_OQL_Query} object specifying
+ the query to execute. The second parameter, {\tt result}, is used for returning the
+ result of the query. The query result is of type {\tt r_Set< r_Ref_Any >}.
+
+ If the function is not called within the scope of an opened database, a \Ref{r_Error}
+ exception of kind {\tt r_Error_DatabaseClosed} is raised. If it is called outside any
+ transaction, the exception is of kind {\tt r_Error_TransactionNotOpen}.
+
+ A complete list of all possible error kinds is given by the following table.
+
+ \begin{tabular}{lll}
+ r_Error_ClientUnknown && Client is not known by the server (earlier communication problems).\\
+ r_Error_DatabaseClosed && No database is not opened.\\
+ r_Error_TransactionNotOpen && Call is not within an active transaction.\\
+ r_Error_QueryParameterCountInvalid && At least one of the query parameters is not supplied with a value.\\
+ r_Error_TransferFailed && Other communication problem. \\
+ r_Error_QueryExecutionFailed && The execution of the query failed (further information is available
+ in an error object of type {\tt r_Equery_execution}).\\
+ r_Error_TypeInvalid && Result base type doesn't match the template type. \\
+ \end{tabular}
+*/
+
+void r_oql_execute( r_OQL_Query& query, r_Set< r_Ref_Any > &result )
+throw( r_Error );
+
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+ The funcetion is used to execute retrieval queries with the result set being
+ of type {\tt r_Set< r_Ref< r_GMarray > >}. The function is supported for
+ compatibility reasons only. We suggest to use the general function
+ \Ref{r_oql_execute} able to maintain query results of any type.
+*/
+void r_oql_execute( r_OQL_Query& query, r_Set< r_Ref< r_GMarray > > &result )
+throw( r_Error );
+
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+ The free standing function \Ref{r_oql_execute} is called to execute an update query.
+ The first parameter, {\tt query}, is a reference to a \Ref{r_OQL_Query} object specifying
+ the query to execute.
+
+ If the function is not called within the scope of an opened database, a \Ref{r_Error}
+ exception of kind {\tt r_Error_DatabaseClosed} is raised. If it is called outside any
+ transaction, the exception is of kind {\tt r_Error_TransactionNotOpen}.
+
+ A complete list of all possible error kinds is given by the following table.
+
+ \begin{tabular}{lll}
+ r_Error_ClientUnknown && Client is not known by the server (earlier communication problems).\\
+ r_Error_DatabaseClosed && No database is not opened.\\
+ r_Error_TransactionNotOpen && Call is not within an active transaction.\\
+ r_Error_QueryParameterCountInvalid && At least one of the query parameters is not supplied with a value.\\
+ r_Error_TransferFailed && Other communication problem. \\
+ r_Error_QueryExecutionFailed && The execution of the query failed (further information is available
+ in an error object of type {\tt r_Equery_execution}).\\
+ \end{tabular}
+*/
+
+void r_oql_execute( r_OQL_Query& query )
+throw( r_Error );
+
+#include "rasodmg/oqlquery.icc"
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rasodmg/oqlquery.icc b/rasodmg/oqlquery.icc
new file mode 100644
index 0000000..6d6b225
--- /dev/null
+++ b/rasodmg/oqlquery.icc
@@ -0,0 +1,52 @@
+/*
+* 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>.
+/
+/**
+ * INLINE SOURCE: oqlquery.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_OQL_Query
+ *
+ * COMMENTS:
+ *
+*/
+
+
+inline const char*
+r_OQL_Query::get_query() const
+{
+ return (const char*)queryString;
+};
+
+
+inline const r_Set< r_GMarray* >*
+r_OQL_Query::get_constants() const
+{
+ return mddConstants;
+};
+
+
+inline const char*
+r_OQL_Query::get_parameterized_query() const
+{
+ return (const char*)parameterizedQueryString;
+};
diff --git a/rasodmg/partinsert.cc b/rasodmg/partinsert.cc
new file mode 100644
index 0000000..566f287
--- /dev/null
+++ b/rasodmg/partinsert.cc
@@ -0,0 +1,199 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: partinsert.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Partial_Insert
+ *
+ * COMMENTS:
+ * None
+*/
+
+#include <string.h>
+#include <stdio.h>
+#include <vector>
+
+#include "raslib/rminit.hh"
+#include "raslib/rmdebug.hh"
+#include "raslib/minterval.hh"
+#include "raslib/error.hh"
+#include "rasodmg/storagelayout.hh"
+#include "rasodmg/alignedtiling.hh"
+#include "rasodmg/gmarray.hh"
+#include "rasodmg/database.hh"
+#include "rasodmg/oqlquery.hh"
+#include "rasodmg/partinsert.hh"
+
+
+
+// format string for creating collections; parameters: collection name, set type
+const char *r_Partial_Insert::format_create = "CREATE COLLECTION %s %s";
+// format string for updating the MDD; parameters: collection name, local oid
+const char *r_Partial_Insert::format_update = "UPDATE %s AS x SET x ASSIGN $1 WHERE OID(x) = %f";
+
+
+r_Partial_Insert::r_Partial_Insert( r_Database &usedb, const char *collname, const char *mddtype, const char *settype, const r_Storage_Layout &stl ) : mydb(usedb)
+{
+ init_share(collname, mddtype, settype);
+ mystl = stl.clone();
+}
+
+
+r_Partial_Insert::r_Partial_Insert( r_Database &usedb, const char *collname, const char *mddtype, const char *settype, const r_Minterval &dom, unsigned int tsize ) : mydb(usedb)
+{
+ init_share(collname, mddtype, settype);
+ r_Aligned_Tiling *tilingObj = new r_Aligned_Tiling(dom, tsize * dom.cell_count());
+ mystl = new r_Storage_Layout(tilingObj);
+}
+
+
+r_Partial_Insert::r_Partial_Insert( const r_Partial_Insert &src ) : mydb(src.mydb)
+{
+ init_share(src.collName, src.mddType, src.setType);
+ mystl = src.mystl->clone();
+}
+
+
+r_Partial_Insert::~r_Partial_Insert( void )
+{
+ if (collName != NULL)
+ delete [] collName;
+ if (mddType != NULL)
+ delete [] mddType;
+ if (setType != NULL)
+ delete [] setType;
+ if (mystl != NULL)
+ delete mystl;
+}
+
+
+void r_Partial_Insert::init_share( const char *collname, const char *mddtype, const char *settype )
+{
+ collName = new char[strlen(collname)+1];
+ strcpy(collName, collname);
+ mddType = new char[strlen(mddtype)+1];
+ strcpy(mddType, mddtype);
+ setType = new char[strlen(settype)+1];
+ strcpy(setType, settype);
+ doUpdate = 0;
+}
+
+int r_Partial_Insert::update( r_GMarray *mddPtr,
+ r_Data_Format transferFormat,
+ const char* transferFormatParams,
+ r_Data_Format storageFormat,
+ const char* storageFormatParams
+ )
+{
+ RMDBGENTER(0, RMDebug::module_rasodmg, "r_Partial_Insert", "update()");
+ try {
+ mddPtr->set_storage_layout(mystl->clone());
+ mddPtr->set_type_by_name(mddType);
+ }
+ catch (r_Error &err) {
+ RMInit::logOut << "r_Partial_Insert::update(): unable to set storage_layout for the currend MDD: "
+ << err.what() << endl;
+ return -1;
+ }
+
+ if (doUpdate == 0)
+ {
+ char *queryBuffer = new char[strlen(format_create) + strlen(collName) + strlen(setType)];
+ sprintf(queryBuffer, format_create, collName, setType);
+ // first try creating the collection
+ try
+ {
+ // this is basically 3 bytes to long, but that doesn't matter
+ myta.begin();
+ mydb.set_transfer_format(transferFormat, transferFormatParams);
+ mydb.set_storage_format(storageFormat, storageFormatParams);
+ r_OQL_Query query(queryBuffer);
+ r_oql_execute(query);
+ myta.commit();
+ RMDBGMIDDLE(0, RMDebug::module_rasodmg, "r_Partial_Insert", "update(): created new collection " << collName << " with type " << setType );
+ }
+ catch (r_Error &err)
+ {
+ RMDBGMIDDLE(0, RMDebug::module_rasodmg, "r_Partial_Insert", "update(): can't create collection: " << err.what() );
+ myta.abort();
+ // failure to create the collection is not an error
+ }
+ delete [] queryBuffer;
+
+ // now create the root object
+ try
+ {
+ myta.begin();
+ mydb.set_transfer_format(transferFormat, transferFormatParams);
+ mydb.set_storage_format(storageFormat, storageFormatParams);
+ r_Ref<r_GMarray> mddp = new (&mydb, mddType) r_GMarray(*mddPtr);
+ r_Ref<r_Set<r_Ref<r_GMarray> > > mddCollPtr;
+ mddCollPtr = (r_Ref<r_Set<r_Ref<r_GMarray> > >)(mydb.lookup_object(collName));
+ mddCollPtr->insert_element(mddp);
+ myOId = mddp->get_oid();
+ myta.commit();
+ RMDBGMIDDLE(0, RMDebug::module_rasodmg, "r_Partial_Insert", "update(): reated root object OK, oid = " << myOId );
+ doUpdate = 1;
+ }
+ catch (r_Error &err)
+ {
+ RMInit::logOut << "r_Partial_Insert::update(): unable to create root object: "
+ << err.what() << endl;
+ myta.abort();
+ return -1;
+ }
+ }
+ else
+ {
+ char *queryBuffer = new char[strlen(format_update) + strlen(collName) + 32];
+ sprintf(queryBuffer, format_update, collName, myOId.get_local_oid());
+
+ // try the update
+ try
+ {
+ myta.begin();
+ mydb.set_transfer_format(transferFormat, transferFormatParams);
+ mydb.set_storage_format(storageFormat, storageFormatParams);
+ RMDBGMIDDLE(1, RMDebug::module_rasodmg, "r_Partial_Insert", "update(): QUERY: " << queryBuffer );
+ r_OQL_Query query(queryBuffer);
+ query << (*mddPtr);
+ r_oql_execute(query);
+ myta.commit();
+ RMDBGMIDDLE(0, RMDebug::module_rasodmg, "r_Partial_Insert", "update(): update object OK" );
+ }
+ catch (r_Error &err)
+ {
+ RMInit::logOut << "r_Partial_Insert::update(): failed to update marray: "
+ << err.what() << endl;
+ myta.abort();
+ delete [] queryBuffer;
+ RMDBGEXIT(1, RMDebug::module_rasodmg, "r_Partial_Insert", "failed");
+ return -1;
+ }
+ delete [] queryBuffer;
+ }
+ RMDBGEXIT(1, RMDebug::module_rasodmg, "r_Partial_Insert", "update(): exiting OK" );
+
+ return 0;
+}
diff --git a/rasodmg/partinsert.hh b/rasodmg/partinsert.hh
new file mode 100644
index 0000000..013124c
--- /dev/null
+++ b/rasodmg/partinsert.hh
@@ -0,0 +1,109 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: partinsert.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Partial_Insert
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_PARTIAL_INSERT_
+#define _R_PARTIAL_INSERT_
+
+
+#include "raslib/mddtypes.hh"
+#include "raslib/oid.hh"
+#include "rasodmg/transaction.hh"
+
+
+class r_Minterval;
+class r_Storage_Layout;
+class r_GMarray;
+class r_Database;
+
+
+//@ManMemo: {\bf rasodmg}
+
+/*@Doc:
+ Class for inserting an MDD into the database stripwise, as in most of
+ our insert tools.
+*/
+
+class r_Partial_Insert
+{
+ public:
+ /// constructor receiving all necessary parameters. The storage layout is copied
+ r_Partial_Insert( r_Database &usedb, const char *collname, const char *mddtype,
+ const char *settype, const r_Storage_Layout &stl );
+ /// alternative constructor for regular tiling
+ r_Partial_Insert( r_Database &usedb, const char *collname, const char *mddtype,
+ const char *settype, const r_Minterval &dom, unsigned int tsize );
+ /// copy constructor
+ r_Partial_Insert( const r_Partial_Insert &src );
+ /// destructor
+ ~r_Partial_Insert( void );
+
+ /// update the marray; no transaction should be activated, this is done internally.
+ int update( r_GMarray *mddPtr,
+ r_Data_Format transferFormat = r_Array,
+ const char* transferFormatParams = NULL,
+ r_Data_Format storageFormat = r_Array,
+ const char* storageFormatParams = NULL
+ );
+ /*
+ The marray may be modified in small aspects such as base type name and storage layout.
+ The "transferFormat, transferFormatParams" are used to set the transfer compression used
+ for the communications of client with the server.
+ The "storageFormat, storageFormatParams" are used to set the storage format used for
+ MDD created by the client in the RasDaMan database.
+ */
+
+ protected:
+ /// shared init code
+ void init_share( const char *collname, const char *mddtype, const char *settype );
+
+ /// the marray's OId
+ r_OId myOId;
+ /// the collection name
+ char *collName;
+ /// the MDD type name
+ char *mddType;
+ /// the set type name
+ char *setType;
+ /// the database
+ r_Database &mydb;
+ /// the storage layout
+ r_Storage_Layout *mystl;
+ /// the transaction object
+ r_Transaction myta;
+ /// do we have to do an insert or an update?
+ int doUpdate;
+ /// format strings for queries
+ static const char *format_create;
+ static const char *format_update;
+};
+
+#endif
diff --git a/rasodmg/polycutout.cc b/rasodmg/polycutout.cc
new file mode 100644
index 0000000..78f3d75
--- /dev/null
+++ b/rasodmg/polycutout.cc
@@ -0,0 +1,709 @@
+/*
+* 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: polycutout.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_PolygonCutOut
+ *
+ * COMMENTS:
+ *
+ * This class is intended to perform the polygon cut out operation
+ * Except for the r_PolygonCutOut class, everything else is just
+ * for internal use
+ * Attention: this version works good (I hope :-) but has just a tiny geometrical problem:
+ * as usual in discrete space, lines are build up by little horiontal segments.
+ * Edges are considered to be inside, except the first little segment of a line.
+ * This is only for avoiding a bigger problem, I will develop a better algorythm
+*/
+
+/*
+This module is intended to perform polygon cut out operation. It supports the exact ESRI specifications
+regarding "clean" polygons, this means: not self intersecting, closed, if you walk from an point to the
+next of edge the inside is on the right. It also supports multiple rings, but the outer one has to have
+the "inside" inside.
+Don't forget that the rasdaman coordinates are with x left->right and y top->down, or at least
+I have considered them so because of the usual coordinates of tiffs
+*/
+
+static const char rcsid[] = "@(#)rasodmg, r_PolygonCutOut: $Id: polycutout.cc,v 1.11 2002/10/09 09:58:05 hoefner Exp $";
+
+#include "rasodmg/polycutout.hh"
+#include "rasodmg/marray.hh"
+#include "raslib/miter.hh"
+
+#include <math.h>
+
+r_SegmentIterator::r_SegmentIterator(r_Point &s,r_Point &e)
+ {
+ start = s;
+ end = e;
+ reset();
+ }
+
+void r_SegmentIterator::reset()
+ {
+ dx = end[0] - start[0];
+ dy = end[1] - start[1];
+
+ if( dx >= 0)
+ { if( dy >= 0 )
+ { if( dx >= dy ) { cadran = 0;}
+ else { cadran = 1; swap(dx,dy);}
+ }
+ else
+ { dy = -dy;
+ if( dx >= dy ) { cadran = 7;}
+ else { cadran = 6; swap(dx,dy);}
+ }
+ }
+ else
+ { dx = -dx;
+ if( dy >= 0 )
+ { if( dx >= dy ) { cadran = 3;}
+ else { cadran = 2; swap(dx,dy);}
+ }
+ else
+ { dy = -dy;
+ if( dx >= dy ) { cadran = 4;}
+ else { cadran = 5; swap(dx,dy);}
+ }
+ }
+ cx = 0;
+ cy = 0;
+ beta = 0;
+// std::cout<<"reset: ["<<start<<','<<end<<"] cadran="<<cadran<<" dx="<<dx<<" dy="<<dy<<std::endl;
+ }
+
+r_Point r_SegmentIterator::next()
+ {
+ r_Point resultat = createCurrentPoint();
+ //prepare next
+ cx++;
+ beta += dy;
+ if( (beta<<1) > dx ) { beta -= dx; cy++;}
+ return resultat;
+ }
+
+bool r_SegmentIterator::hasMore()
+ {
+// std::cout<<"hasMore: cx="<<cx<<" lim="<<dx+1<<std::endl;
+ return (cx <= dx ) ? true : false;
+ }
+
+int r_SegmentIterator::cosFunc() // limited use,1000 * cos(alfa)
+ { // use local variables
+ double ldx = end[0] - start[0];
+ double ldy = end[1] - start[1];
+
+ double num = ldx*ldx + ldy*ldy;
+ if(num == 0) return 0;
+
+ return (1000 * ldx)/sqrt(num);
+ }
+
+void r_SegmentIterator::swap(r_Range &x, r_Range &y)
+ {
+ r_Range temp = x;
+ x=y;
+ y=temp;
+ }
+
+r_Point r_SegmentIterator::createCurrentPoint()
+ {
+// std::cout<<" cCP: "<<cx<<':'<<cy<<std::endl;
+ r_Range rcx = cx;
+ r_Range rcy = cy;
+ switch(cadran)
+ { case 0: break;
+ case 1: swap(rcx,rcy); break;
+ case 2: swap(rcx,rcy); rcx=-rcx; break;
+ case 3: rcx=-rcx; break;
+ case 4: rcx=-rcx; rcy=-rcy; break;
+ case 5: swap(rcx,rcy); rcx=-rcx; rcy=-rcy; break;
+ case 6: swap(rcx,rcy); rcy=-rcy; break;
+ case 7: rcy=-rcy; break;
+ }
+ //std::cout<<"cCP: cx="<<cx<<" cy="<<cy<<" rx="<<rcx<<" ry="<<rcy<<" cadran="<<cadran<<std::endl;
+ return r_Point(start[0] + rcx, start[1] + rcy);
+ }
+
+
+
+r_Line::r_Line()
+ {
+ a = b = c = 0;
+ }
+
+r_Line::r_Line(double nA,double nB,double nC)
+ {
+ a = nA; b = nB; c = nC;
+ }
+
+r_Line::r_Line(r_Point &s,r_Point &e)
+ {
+ a = e[1] - s[1];
+ b = s[0] - e[0];
+ c = (double)e[0]*(double)s[1] - (double)s[0]*(double)e[1];
+ }
+
+double r_Line::getA() { return a; }
+double r_Line::getB() { return b; }
+double r_Line::getC() { return c; }
+
+float r_Line::ecuatia(r_Point &p)
+ {
+ return a * p[0] + b * p[1] + c;
+ }
+
+ostream& operator<<(ostream& os,r_Line &l)
+ {
+ return os<<"{L"<<l.a<<','<<l.b<<','<<l.c<<'}';
+ }
+
+
+
+
+r_PolygonCutOut::r_PolygonCutOut()
+ {
+ table = 0;
+ usedCount = 0;
+ mArray = 0;
+
+ imgWidth = 0;
+ imgHeight = 0;
+ imgX = 0;
+ imgY = 0;
+ tableWidth = 0;
+ tableHeight = 0;
+ }
+r_PolygonCutOut::~r_PolygonCutOut()
+ {
+ clearTables();
+ }
+
+void r_PolygonCutOut::setMArray(r_GMarray& myArray)
+ {
+ mArray = &myArray;
+
+ r_Minterval currDomain;
+ currDomain = mArray->spatial_domain();
+
+ imgX = currDomain[0].low();
+ imgY = currDomain[1].low();
+
+ imgWidth = currDomain[0].get_extent();
+ imgHeight = currDomain[1].get_extent();
+ }
+
+void r_PolygonCutOut::addPolygon(const r_Polygon &p)
+ {
+ polygons.push_back(p);
+ }
+
+bool r_PolygonCutOut::compute()
+ {
+//std::cout<<"PCO: compute in"<<std::endl;
+ if(!imgWidth || !imgHeight || polygons.size()==0) return false;
+
+//std::cout<<"PCO: initTable - in"<<std::endl;
+ initTable();
+//std::cout<<"PCO: initTable - out"<<std::endl;
+
+ list<r_Polygon>::iterator polyIter = polygons.begin();
+
+ for(int i = 0; i < polygons.size(); i++, polyIter++)
+ {
+ r_Polygon &currPolygon = *polyIter;
+
+ const std::vector<r_Edge>& edges = currPolygon.getEdges();
+ std::vector<r_Edge>::const_iterator edgeIterator = edges.begin();
+
+ for(int j = 0; j < edges.size(); j++,edgeIterator++)
+ {
+ r_Point start = edgeIterator->getStart();
+ r_Point end = edgeIterator->getEnd();
+
+ if(start == end) continue; //avoid such edges, causes problems
+
+ int inside = -computeInside(start,end); // minus because rasdaman coord are flipped
+ // we have to see if this is correct like this or not
+
+ //std::cout<<"compute edge "<<j<<" ["<<start<<"-"<<end<<"] inside="<<inside<<std::endl;
+ if(inside == 0 ) computeOneHorSegment(start,end);
+ else computeOneSegment(start,end,inside);
+ }
+ }
+ for(int line=0;line<tableHeight;line++)
+ { ordonateLine(line);
+ minimizeLine(line);
+ }
+//print();
+// std::cout<<"PCO: compute out"<<std::endl;
+ return true;
+ }
+
+bool r_PolygonCutOut::initTable()
+ {
+ clearTables();
+ tableWidth = computeTableWidth();
+ tableHeight= imgHeight;
+
+//std::cout<<"PCO: initTable: "<<tableWidth<<','<<tableHeight<<std::endl;
+ table = new TablePoint[tableWidth*tableHeight];
+ usedCount = new int[tableHeight];
+
+ // if(table==NULL || usedCount==NULL) std::cout<<"sunt nule"<<std::endl;
+
+ for(int i=0;i<tableWidth*tableHeight;i++)
+ {
+ table[i].x =-1;
+ table[i].inside= 0;
+ table[i].cosFunc= 0;
+ }
+
+ for(int j=0;j<tableHeight;j++)
+ usedCount[j]=0;
+
+ return true;
+ }
+
+void r_PolygonCutOut::clearTables()
+ {
+ if(table) delete[] table;
+ table = NULL;
+ if(usedCount) delete[] usedCount;
+ usedCount =NULL;
+ }
+int r_PolygonCutOut::computeTableWidth()
+ {
+ // once it was: tableWidth = poly->getCountNodes() + poly->countHorizontalEdges() + 2;
+
+ list<r_Polygon>::iterator iter=polygons.begin();
+
+ int nodes = 0;
+ int horizEdges = 0;
+
+ for(int i=0;i<polygons.size();i++, iter++)
+ {
+ r_Polygon &polygon = *iter;
+
+ nodes += polygon.countEdges();
+ horizEdges += polygon.countHorizontalEdges();
+ }
+ return nodes + horizEdges; // niet + 2;
+ }
+
+void r_PolygonCutOut::ordonateLine(int line)
+ {
+ int count=usedCount[line];
+ TablePoint *tLine = &getTP(line,0);
+ bool change=false;
+ do{
+ change=false;
+ for(int i=0;i<count-1;i++)
+ { bool swap=false;
+
+ if(tLine[i].x > tLine[i+1].x) swap=true;
+ if(tLine[i].x == tLine[i+1].x &&
+ tLine[i].inside != tLine[i+1].inside &&
+ tLine[i].cosFunc > tLine[i+1].cosFunc)
+ swap=true;
+ if(swap)
+ { TablePoint temp = tLine[i];
+ tLine[i] = tLine[i+1];
+ tLine[i+1] = temp;
+ change = true;
+ }
+ }
+ }while(change);
+
+ for(int j=0;j<count-1;j++)
+ { if(tLine[j] == tLine[j+1])
+ tLine[j].inside=0;
+ }
+
+ }
+
+void r_PolygonCutOut::minimizeLine(int line)
+ {
+ int count=usedCount[line];
+ if(count <= 2) return; //nothing to do
+
+ int inside = 0;
+ TablePoint *tLine = &getTP(line,0);
+
+ int level=0;
+ for(int i=0;i<count-1;i++)
+ {
+ if(level==0) { inside=tLine[i].inside;
+ level++;
+ continue;
+ }
+
+ if(tLine[i].inside==inside) level++;
+ else level--;
+
+ if(level!=0) tLine[i].inside=0; // means disabled
+ }
+
+ int s,d;
+ for(s=0,d=0;s<count;s++)
+ {
+ if(tLine[s].inside==0) continue;
+ if(s!=d) tLine[d]=tLine[s];
+ d++;
+ }
+ usedCount[line]=d;
+ }
+
+void r_PolygonCutOut::computeOneSegment(r_Point start, r_Point end, int inside)
+ {
+ int lastLine = -1;
+ int lastX = -1;
+ r_SegmentIterator segiter(start,end);
+
+ int cosFunc=segiter.cosFunc();
+ int cosNow = cosFunc; // first point: cosFunc, lastPoint -cosFunc, rest 0
+
+ bool firstLine = true;
+ bool lastPoint = false;
+ // this firstLine-lastPoint are here only top be sure that the first and the last point are in the table
+ // and not replaced by neighbours
+ while(segiter.hasMore())
+ { r_Point cp = segiter.next();
+ if(segiter.hasMore()==false) // last point
+ {
+ cosNow=-cosFunc;
+ lastPoint = true;
+ }
+
+ r_Range coordX = cp[0];
+ r_Range coordY = cp[1];
+
+ int tableLine = coordY - imgY;
+
+ if(tableLine>=0 && tableLine < tableHeight)
+ {
+ if(tableLine != lastLine)
+ { addPoint(tableLine,coordX,inside,cosNow);
+
+ if(lastLine != -1) firstLine = false;
+ }
+ else if(firstLine == false)
+ {
+ if(inside > 0 && coordX < lastX) replacePoint(tableLine,coordX,inside,cosNow);
+ else if(inside < 0 && coordX > lastX) replacePoint(tableLine,coordX,inside,cosNow);
+ else if(lastPoint) replacePoint(tableLine,coordX,inside,cosNow);
+ }
+ }
+
+ cosNow = 0;
+ lastLine = tableLine;
+ lastX = coordX;
+ }
+ }
+
+void r_PolygonCutOut::computeOneHorSegment(r_Point start, r_Point end)
+ {
+ r_SegmentIterator segiter(start,end);
+ int cosFunc=segiter.cosFunc();
+
+ r_Range startX = start[0];
+ r_Range endX = end[0];
+ r_Range commonY = start[1];
+
+ int tableLine = commonY - imgY;
+
+ if(tableLine>=0 && tableLine < tableHeight)
+ {
+ if(startX <= endX)
+ { addPoint(tableLine,startX, 1, cosFunc);
+ addPoint(tableLine,endX, -1,-cosFunc);
+ }
+ else { // in this case cosFunc < 0
+ addPoint(tableLine,endX, 1,-cosFunc);
+ addPoint(tableLine,startX,-1, cosFunc);
+ }
+ }
+ }
+
+int r_PolygonCutOut::computeInside(r_Point start, r_Point end)
+ {
+ r_Line line(start,end);
+ r_Point control(start[0]+1,start[1]);
+ float f = line.ecuatia(control);
+ if(f==0) return 0;
+ if(f<0 ) return -1;
+ return 1;
+ }
+
+
+r_PolygonCutOut::TablePoint& r_PolygonCutOut::getTP(int line, int column)
+ {
+ TablePoint *tp = table + (line * tableWidth + column);
+ return *tp;
+ }
+
+void r_PolygonCutOut::print(int onlyLine)
+ {
+ std::cout<<"r_PolygonCutOut::print: "<<tableWidth<<':'<<tableHeight<<std::endl;
+
+ if(onlyLine==-1) // print all
+ {
+ for(int i=0;i<tableHeight;i++)
+ printLine(i);
+ }
+ else
+ {
+ if(0<=onlyLine && onlyLine <tableHeight) printLine(onlyLine);
+ else std::cout<<"Line "<<onlyLine<<" doesn't exist"<<std::endl;
+ }
+ }
+
+void r_PolygonCutOut::printLine(r_Range line)
+ {
+ int count=usedCount[line];
+ TablePoint *tp = &getTP(line,0);
+
+ std::cout<<"line "<<line<<'('<<count<<") ";
+ for(int i=0;i<count;i++)
+ { char inside='0';
+ if(tp[i].inside==-1) inside='-';
+ if(tp[i].inside==1 ) inside='+';
+
+ std::cout<<'['<<tp[i].x<<','<<inside<<','<<tp[i].cosFunc<<']';
+ }
+ std::cout<<std::endl;
+ }
+
+void r_PolygonCutOut::addPoint(int tableLine,r_Range coordX, int inside,int cosFunc)
+ {
+ int which = usedCount[tableLine];
+ TablePoint *tp = &getTP(tableLine,which);
+
+ tp->x = coordX;
+ tp->inside = inside;
+ tp->cosFunc = cosFunc;
+ usedCount[tableLine]++;
+ }
+
+void r_PolygonCutOut::replacePoint(int tableLine,r_Range coordX,int inside, int cosFunc)
+ {
+ int which = usedCount[tableLine]-1;
+ TablePoint *tp = &getTP(tableLine,which);
+ tp->x = coordX;
+ tp->inside = inside;
+ tp->cosFunc = cosFunc;
+ }
+
+bool r_PolygonCutOut::TablePoint::operator==(r_PolygonCutOut::TablePoint &tp)
+ { return (x==tp.x && inside==tp.inside) ? true: false;
+ }
+
+
+// debug only int lastline = -1;
+void
+r_PolygonCutOut::eraseLine( r_Range x1, r_Range x2, r_Range y, const string& bgr ) throw(r_Error)
+{
+ // can heapen if we are outside the domain of the array
+ if(x2 < x1) return;
+
+ //if(lastline != y && x1 != 0)
+ // std::cout<<"Erasing line: y="<<y<<" ["<<x1<<","<<x2<<"]"<<std::endl;
+ //lastline = y;
+
+ r_Minterval eraseDom(2);
+ eraseDom << r_Sinterval(x1, x2) << r_Sinterval(y, y);
+ r_Minterval arrayDom = mArray->spatial_domain();
+ r_Bytes typeSize = mArray->get_type_length();
+ r_Bytes bgrSize = bgr.size();
+ const char *bgrContent=bgr.c_str();
+ char *currCell=NULL;
+
+
+ // Grrr. In RasDaMan the y are stored close together. So the whole fillPolygon
+ // should have been organised by x instead of y. Well, for now I just use an
+ // r_Miter here.
+
+ r_Miter eraseIter( &eraseDom, &arrayDom, typeSize, mArray->get_array() );
+ while( !eraseIter.isDone() ) {
+ currCell = eraseIter.nextCell();
+ // FIXME This potentially wont work for all types. I just set every byte to 0.
+ if(bgr.empty())
+ memset(currCell, 0, typeSize);
+ else
+ {
+ if( typeSize != bgrSize)
+ throw r_Error( r_Error::r_Error_TypeInvalid );
+ memmove(currCell, bgrContent, bgrSize);
+ }
+ }
+}
+
+
+bool
+r_PolygonCutOut::fillMArrayOutside(const string& bgr ) throw(r_Error)
+{
+ if( compute() == false ) return false;
+
+ r_Minterval currDomain = mArray->spatial_domain();
+
+ r_Range imgMinX = imgX;
+ r_Range imgMaxX = currDomain[0].high();
+
+ for(int lineY = 0; lineY < tableHeight ; lineY++)
+ {
+ r_Range coordY = imgY + lineY;
+
+ int countUsed = usedCount[lineY];
+
+ if(countUsed==0)
+ { // polygon didn't touch this line, so all line is outside
+ eraseLine(imgMinX, imgMaxX, coordY, bgr);
+ continue;
+ }
+
+ TablePoint *tp = &getTP(lineY, 0);
+
+ r_Range xLeft = imgMinX-1;
+ r_Range xRight = imgMaxX+1;
+ bool erase = false;
+
+ if( tp[countUsed-1].x < imgMinX)
+ { // the whole polygon is on the left of this line so we have to erase the whole line
+ eraseLine( imgMinX, imgMaxX, coordY, bgr);
+ continue;
+ }
+
+ if( tp[0].x > imgMaxX)
+ { // the whole polygon is on the right of this line so we have to erase the whole line
+ eraseLine( imgMinX, imgMaxX, coordY, bgr);
+ continue;
+ }
+
+ for(int i=0;i<countUsed; i++, tp++)
+ {
+ if(tp->x < imgMinX) continue;
+
+ if(tp->inside == -1)
+ { // inside is <-, so outside is ->
+ xLeft = tp->x;
+ if(xLeft > imgMaxX) break;
+
+ if(i == countUsed-1)
+ { xRight = imgMaxX+1; erase = true;
+ }
+ }
+
+ if(tp->inside == 1)
+ { // inside is ->, so outside is <-
+ xRight = tp->x > imgMaxX ? imgMaxX+1 : tp->x;
+ erase = true;
+ }
+
+ if(erase)
+ { eraseLine( xLeft+1, xRight-1, coordY, bgr);
+ erase = false;
+ }
+ }
+
+ }
+ clearTables();
+ return true;
+ }
+
+/*
+ Attention, this two functions look very similar, but with have significant differences
+ One of them is the absence of some -1 or +1 in the next function. This is important
+ because we consider the edges to be "inside", and the edges are in the table, so
+ erasing the inside is erase [start,end] and erasing the outside is erase [start+1,end-1]
+*/
+
+bool
+r_PolygonCutOut::fillMArrayInside(const string& bgr ) throw(r_Error)
+{
+ if( compute() == false ) return false;
+
+ r_Minterval currDomain = mArray->spatial_domain();
+
+ r_Range imgMinX = imgX;
+ r_Range imgMaxX = currDomain[0].high();
+
+ for(int lineY = 0; lineY < tableHeight ; lineY++)
+ {
+ r_Range coordY = imgY + lineY;
+
+ int countUsed = usedCount[lineY];
+
+ if(countUsed==0)
+ { // polygon didn't touch this line, so all line is outside
+ continue;
+ }
+
+ TablePoint *tp = &getTP(lineY, 0);
+
+ r_Range xLeft = imgMinX;
+ r_Range xRight = imgMaxX;
+ bool erase = false;
+
+ if( tp[countUsed-1].x < imgMinX)
+ { // the whole polygon is on the left of this line so we have to erase the whole line
+ continue;
+ }
+
+ if( tp[0].x > imgMaxX)
+ { // the whole polygon is on the right of this line so we have to erase the whole line
+ continue;
+ }
+
+ for(int i=0;i<countUsed; i++, tp++)
+ {
+ if(tp->x < imgMinX) continue;
+
+ if(tp->inside == 1)
+ { // inside is ->, so outside is <-
+ xLeft = tp->x;
+ if(xLeft > imgMaxX) break;
+
+ if(i == countUsed-1)
+ { xRight = imgMaxX; erase = true;
+ }
+ }
+
+ if(tp->inside == -1)
+ { // inside is <-, so outside is ->
+ xRight = tp->x > imgMaxX ? imgMaxX : tp->x;
+ erase = true;
+ }
+
+ if(erase)
+ { eraseLine( xLeft, xRight, coordY, bgr);
+ erase = false;
+ }
+ }
+
+ }
+ clearTables();
+ return true;
+ }
diff --git a/rasodmg/polycutout.hh b/rasodmg/polycutout.hh
new file mode 100644
index 0000000..fc2e258
--- /dev/null
+++ b/rasodmg/polycutout.hh
@@ -0,0 +1,162 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: polycutout.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_PolygonCutOut
+ *
+ * COMMENTS:
+ *
+ * This class is intended to perform the polygon cut out operation
+ * Except for the r_PolygonCutOut class, everything else is just
+ * for internal use
+ * Attention: this version works good (I hope :-) but has just a tiny geometrical problem:
+ * as usual in discrete space, lines are build up by little horiontal segments.
+ * Edges are considered to be inside, except the first little segment of a line.
+ * This is only for avoiding a bigger problem, I will develop a better algorythm
+*/
+
+/*
+ This module is intended to perform polygon cut out operation. It supports the exact ESRI specifications
+ regarding "clean" polygons, this means: not self intersecting, closed, if you walk from an point to the
+ next of edge the inside is on the right. It also supports multiple rings, but the outer one has to have
+ the "inside" inside.
+ Don't forget that the rasdaman coordinates are with x left->right and y top->down, or at least
+ I have considered them so because of the usual coordinates of tiffs
+*/
+
+#ifndef _R_POLYGON_CUT_OUT_HH
+#define _R_POLYGON_CUT_OUT_HH
+
+#include <iosfwd>
+#include <vector>
+#include <list>
+#include <string>
+using std::string;
+using std::list;
+using std::vector;
+using std::ostream;
+
+#include "raslib/point.hh"
+#include "raslib/minterval.hh"
+#include "rasodmg/polygon.hh"
+
+
+//@ManMemo: Module: {\bf rasodmg}
+
+
+class r_SegmentIterator
+ {
+ public:
+ r_SegmentIterator(r_Point&,r_Point&);
+ void reset();
+ r_Point next();
+ bool hasMore();
+ int cosFunc(); // limited use,1000 * cos(alfa)
+ private:
+ void swap(r_Range&, r_Range&);
+ r_Point createCurrentPoint();
+
+ r_Point start;
+ r_Point end;
+ int cadran;
+
+ r_Range dx,dy;
+ r_Range cx,cy;
+ int beta;
+ };
+
+class r_Line
+ {
+ public:
+ r_Line();
+ r_Line(double,double,double);
+ r_Line(r_Point&,r_Point&);
+ double getA();
+ double getB();
+ double getC();
+ float ecuatia(r_Point&);
+ private:
+ double a,b,c;
+ friend ostream& operator<<(ostream&,r_Line&);
+ };
+
+
+class r_PolygonCutOut
+ {
+ public:
+ r_PolygonCutOut();
+ ~r_PolygonCutOut();
+ void setImageSize(r_Range width, r_Range height);
+
+ void setMArray(r_GMarray& myArray);
+ void addPolygon(const r_Polygon&);
+
+ bool fillMArrayInside(const string& bgr = "") throw(r_Error);
+ bool fillMArrayOutside(const string& bgr = "") throw(r_Error);
+
+ // just for debugging
+ void print(int onlyLine=-1);
+ void printLine(r_Range line);
+
+ private:
+ bool compute();
+ void eraseLine( r_Range, r_Range, r_Range y, const string& bgr ) throw(r_Error);
+
+ r_Range imgWidth,imgHeight;
+ r_Range imgX,imgY; // - the origin of the mdd domain
+
+ r_GMarray *mArray;
+
+ std::list<r_Polygon> polygons;
+
+ struct TablePoint
+ { r_Range x;
+ int inside; // where the inside is, -1 left, +1 right, 0 hor. line
+ int cosFunc;
+ bool operator==(TablePoint&);
+ };
+
+ r_Range tableWidth;
+ r_Range tableHeight;
+ TablePoint *table;
+ int *usedCount;
+ TablePoint& getTP(r_Range line, r_Range column);
+
+ bool initTable();
+ void clearTables();
+ int computeTableWidth();
+
+
+ int computeInside(r_Point start, r_Point end);
+ void computeOneSegment(r_Point start, r_Point end, int inside);
+ void computeOneHorSegment(r_Point start, r_Point end);
+ void ordonateLine(int line);
+ void minimizeLine(int line);
+ void replacePoint(r_Range line,r_Range col,int inside, int cosFunc);
+ void addPoint(r_Range line,r_Range col,int inside, int cosFunc);
+
+ };
+
+#endif
diff --git a/rasodmg/polygon.cc b/rasodmg/polygon.cc
new file mode 100644
index 0000000..755593f
--- /dev/null
+++ b/rasodmg/polygon.cc
@@ -0,0 +1,879 @@
+/*
+* 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: polygon.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Polygon
+ *
+ * PURPOSE:
+ * This class maintains 2-D polygon sequences.
+ * It knows about them being closed or not.
+ * Input syntax (see constructor) is:
+ * polygon ::= point+
+ * point ::= '[' int ',' int ']'
+ * int ::= ASCII-integer
+ *
+ * COMMENTS:
+ * - see comment in shrinkPoly() about a potential error source
+ * - r_Error::r_Error_General should be replaced with more specific exception
+ *
+*/
+
+#include "rasodmg/polygon.hh"
+
+#include <set>
+#include <algorithm>
+#include <math.h>
+
+#if defined(SOLARIS)
+#include <strings.h>
+#endif
+
+using std::sort;
+//causes problems compiling on old red hat
+//using std::iterator;
+
+#include "raslib/miter.hh"
+#include "rasodmg/marray.hh"
+
+#include "debug/debug.hh"
+
+static const char rcsid[] = "@(#)rasodmg, r_Polygon: $Header: /home/rasdev/CVS-repository/rasdaman/rasodmg/polygon.cc,v 1.28 2003/12/27 23:02:56 rasdev Exp $";
+
+#ifndef LONG_MAX
+const int LONG_MAX = (1<<31) - 1;
+#endif
+#ifndef LONG_MIN
+const int LONG_MIN = (1<<31); // due to overflow
+#endif
+
+// ------------------------------------------------------------------
+// r_Edge
+// ------------------------------------------------------------------
+
+r_Edge::r_Edge(const r_Point& newStart, const r_Point& newEnd) :
+ start(newStart), end(newEnd)
+{
+}
+
+const r_Point&
+r_Edge::getStart() const
+{
+ return start;
+}
+
+const r_Point&
+r_Edge::getEnd() const
+{
+ return end;
+}
+
+double
+r_Edge::getInvSlope() const
+{
+ return (((double)end[0] - start[0]) / (end[1] - start[1]));
+}
+
+double
+r_Edge::getSlope() const
+{
+ return (((double)end[1] - start[1]) / (end[0] - start[0]));
+}
+
+double
+r_Edge::getCurrX(r_Range y) const
+{
+ double currX=0.0;
+ if(end[1]==start[1])
+ currX=end[0];
+ else
+ currX=getInvSlope()*(y - start[1]) + start[0];
+ return currX;
+}
+
+double
+r_Edge::getCurrY(r_Range x) const
+{
+ double currY=0.0;
+ if(end[0]==start[0])
+ currY=end[1];
+ else
+ currY=getSlope()*(x - start[0]) + start[1];
+ return currY;
+}
+
+void
+r_Edge::print_status( std::ostream& s ) const
+{
+ start.print_status(s);
+ s << "->";
+ end.print_status(s);
+}
+
+
+bool
+r_Edge::isHorizontal() const
+{
+ return start[1] == end[1] ? true:false;
+}
+
+// ------------------------------------------------------------------
+// r_Polygon
+// ------------------------------------------------------------------
+
+const r_Dimension r_Polygon::polyPointDim=2;
+
+r_Polygon::r_Polygon(const char* init) throw (r_Error)
+ : closed(false),
+ firstPointSet(false)
+{
+ ENTER( "r_Polygon::r_Polygon, init=" << init );
+
+ if (init == NULL)
+ {
+ TALK( "r_Polygon::r_Polygon(" << (init?init: "NULL") << ")" );
+ RMInit::logOut << "r_Polygon::r_Polygon(" << (init?init: "NULL") << ")" << std::endl;
+ throw r_Error(POLYGONWRONGINITSTRING);
+ }
+ const int POINTBUFFERLEN=512;
+ const char* endPos = NULL;
+ size_t pointLen = 0;
+ char pointBuffer[POINTBUFFERLEN];
+ const char* startPos = index(init, '[');
+ if (startPos == NULL)
+ {
+ TALK( "r_Polygon::r_Polygon(" << init << ") the init string has to start with a '['" );
+ RMInit::logOut << "r_Polygon::r_Polygon(" << init << ") the init string has to start with a '['" << std::endl;
+ throw r_Error(POLYGONWRONGINITSTRING);
+ }
+
+ // while (true)
+ do
+ {
+ endPos = index(startPos, ']');
+ if (endPos == NULL)
+ {
+ TALK( "r_Polygon::r_Polygon(" << init << ") the init string has to contain valid r_Point definitions" );
+ RMInit::logOut << "r_Polygon::r_Polygon(" << init << ") the init string has to contain valid r_Point definitions" << std::endl;
+ throw r_Error(POLYGONWRONGINITSTRING);
+ }
+ pointLen = endPos - startPos;
+ if (pointLen >= POINTBUFFERLEN)
+ {
+ TALK( "r_Polygon::r_Polygon(" << init << ") the definition of one r_Point is too long, only 2 dimensions are allowed" );
+ RMInit::logOut << "r_Polygon::r_Polygon(" << init << ") the definition of one r_Point is too long, only 2 dimensions are allowed" << std::endl;
+ throw r_Error(POLYGONWRONGINITSTRING);
+ }
+ memset(pointBuffer, 0, POINTBUFFERLEN);
+ strncpy(pointBuffer, startPos, pointLen + 1);
+ addPoint(r_Point(pointBuffer));
+ startPos = index(endPos, '[');
+ // was an endless loop with break, changed it to a 'nice' loop -- PB 2003-sep-12
+ // if (startPos == NULL)
+ // break;
+ } while( startPos != NULL);
+
+ LEAVE( "r_Polygon::r_Polygon" );
+}
+
+r_Polygon::r_Polygon(r_Range x, r_Range y) : closed(false), firstPointSet(true)
+{
+ firstPoint = r_Point(x, y);
+ currPoint = firstPoint;
+}
+
+r_Polygon::r_Polygon() : closed(false), firstPointSet(false)
+{
+}
+
+r_Polygon::r_Polygon(const r_Polygon& old)
+{
+ closed=old.closed;
+ firstPointSet=old.firstPointSet;
+ firstPoint=old.firstPoint;
+ currPoint=old.currPoint;
+
+ edges=old.edges;
+}
+
+r_Polygon&
+r_Polygon::operator=(const r_Polygon& old)
+{
+ if(this!=&old)
+ {
+ closed=old.closed;
+ firstPointSet=old.firstPointSet;
+ firstPoint=old.firstPoint;
+ currPoint=old.currPoint;
+
+ edges=old.edges;
+ }
+ return *this;
+}
+
+void
+r_Polygon::addPoint(const r_Point& newPoint) throw(r_Error)
+{
+ if (newPoint.dimension() != polyPointDim)
+ {
+ RMInit::logOut << "r_Polygon::addPoint(" << newPoint << ") only " << polyPointDim << " dimensional r_Points allowed" << std::endl;
+ throw r_Error(POLYGONWRONGPOINTDIMENSION);
+ }
+
+ if(closed)
+ {
+ RMInit::logOut << "r_Polygon::addPoint(" << newPoint << ") polygon closed" << std::endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ if(firstPointSet)
+ {
+ // add an edge from currentPoint to newPoint
+ edges.push_back(r_Edge(currPoint, newPoint));
+ currPoint = newPoint;
+
+ //check if we have the first point
+ checkFistPoint();
+ }
+ else
+ {
+ firstPoint = newPoint;
+ currPoint = newPoint;
+ firstPointSet = true;
+ }
+}
+
+void
+r_Polygon::addPointXY(r_Range x, r_Range y) throw(r_Error)
+{
+ r_Point newPoint(x, y);
+ addPoint(newPoint);
+}
+
+void
+r_Polygon::close()
+{
+ if (closed)
+ return;
+
+ // add the final edge from currentPoint to firstPoint
+ edges.push_back(r_Edge(currPoint, firstPoint));
+ closed = true;
+}
+
+const std::vector<r_Edge>&
+r_Polygon::getEdges() const throw(r_Error)
+{
+ // if the polygon is not closed we raise an exception.
+ if(!closed)
+ {
+ // TO DO: This should be an internal error sometimes.
+ RMInit::logOut << "r_Polygon::getEdges() polygon opened" << std::endl;
+ throw(r_Error(r_Error::r_Error_General));
+ }
+
+ return edges;
+}
+
+std::vector<r_Point>
+r_Polygon::getPoints() const throw(r_Error)
+{
+ if(!closed)
+ {
+ // TO DO: This should be an internal error sometimes.
+ RMInit::logOut << "r_Polygon::getPoints() polygon opened" << std::endl;
+ throw(r_Error(r_Error::r_Error_General));
+ }
+
+ std::vector<r_Point> retVal;
+ std::vector<r_Edge>::const_iterator iter, iterEnd;
+ for(iter = edges.begin(), iterEnd=edges.end(); iter != iterEnd; ++iter)
+ {
+ retVal.push_back((*iter).getStart());
+ }
+ return retVal;
+}
+
+r_Polygon::r_Polygon_Type
+r_Polygon::detectPolygonType() const throw(r_Error)
+{
+ const unsigned int minNoEdges=3;
+ std::vector<r_Point> points=getPoints();
+ unsigned int i=0,j=0, k=0, n=0;
+ unsigned int flag = 0;
+ double z;
+
+ n=points.size();
+
+ //check if is at least a triangle
+ if (n < minNoEdges)
+ return r_Polygon::UNKNOWN;
+
+ //check if is a polygon in 2D
+ for (i=0; i<n; i++)
+ if (points[i].dimension()!=polyPointDim)
+ return r_Polygon::UNKNOWN;
+
+ //check sign of vertice
+ for (i=0; i<n; i++)
+ {
+ j = (i + 1) % n;
+ k = (i + 2) % n;
+ z = (points[j][1] - points[i][1]) * (points[k][0] - points[j][0]);
+ z -= (points[j][0] - points[i][0]) * (points[k][1] - points[j][1]);
+ if (z < 0)
+ flag |= 1;
+ else if (z > 0)
+ flag |= 2;
+ if (flag == 3)
+ return r_Polygon::CONCAVE;
+ }
+
+ if (flag != 0)
+ return r_Polygon::CONVEX;
+ else
+ return r_Polygon::UNKNOWN;
+}
+
+void
+r_Polygon::checkFistPoint()
+ {
+ if (firstPoint == currPoint)
+ closed = true;
+ else
+ closed = false;
+ }
+
+void
+r_Polygon::print_status( std::ostream& s ) const
+{
+
+ std::vector<r_Edge>::const_iterator iter = edges.begin();
+ std::vector<r_Edge>::const_iterator iterEnd = edges.end();
+ s << "{";
+ while (iter!=iterEnd)
+ {
+ iter->print_status(s);
+ s << ", ";
+ ++iter;
+ }
+ s << "} ";
+ if (closed)
+ s << "closed";
+ else //does not matter, because open will crash ...
+ s << "opened";
+
+}
+
+std::ostream& operator<<( std::ostream& s, const r_Polygon& d )
+{
+ d.print_status( s );
+ return s;
+}
+
+void
+r_Polygon::fillMArray( r_GMarray& myArray, bool fillInside, const std::string& bgr ) const throw(r_Error)
+{
+ if(!closed)
+ {
+ // TO DO: This should be an internal error sometimes.
+ RMInit::logOut << "r_Polygon::fillMArray(...) polygon opened" << std::endl;
+ throw(r_Error(r_Error::r_Error_General));
+ }
+
+ // This code currently is not optimised. For every scanline all edges are checked.
+ // Normally you would keep a list of currently relevant edges and manage deletes
+ // and additions to this table by presorting. Anyway, focus was on correctnes
+ // for the time being and even that was not really easy.
+
+ // all edges of the poly except for horizontal ones.
+ std::set<r_Edge, EdgeSortCriterion> sortedEdges;
+ // the X values of the edges in the current scanline.
+ std::vector<double> currXVals;
+ // just to save some typing.
+ r_Minterval myDom = myArray.spatial_domain();
+ unsigned long typeSize = myArray.get_type_length();
+
+ // build sortedEdges (sorted after startPoint y, startPoint x).
+ std::vector<r_Edge>::const_iterator iter, iterEnd;
+ for(iter = edges.begin(), iterEnd=edges.end(); iter != iterEnd; ++iter)
+ sortedEdges.insert(*iter);
+
+ // now the actual filling is done. Remember that we only draw the outside!
+ // we iterate through the whole y range
+ for(r_Range y = myDom[1].low(); y <= myDom[1].high(); y++)
+ {
+ // update the currXVals by iterating through all edges.
+ for(std::multiset<r_Edge, EdgeSortCriterion>::const_iterator itera = sortedEdges.begin(); itera != sortedEdges.end(); itera++)
+ {
+ if( (*itera).getStart()[1] <= y && y <= (*itera).getEnd()[1] ||
+ (*itera).getEnd()[1] <= y && y <= (*itera).getStart()[1] )
+ {
+ currXVals.push_back((*itera).getCurrX(y));
+ }
+ }
+ // sort them.
+ sort(currXVals.begin(), currXVals.end());
+ // currently we can only draw concave polygons anyway (see below).
+ // So this is heavily simplified! Check version 1.3 for a
+ // blueprint of how it should look like.
+ if(fillInside)
+ {
+ if(currXVals.size() >= 1)
+ {
+ // currXVals is sorted, so just draw from the first to the last.
+ eraseLine(rint(currXVals.front()), rint(currXVals.back()), y, myArray, bgr);
+ }
+ }
+ else
+ {
+ // currXVals is sorted, so just draw from low to the first and
+ // from the last to high.
+ // This only works correctly if the polygon is clipped
+ // to the area of the image.
+ if(currXVals.size() >= 1)
+ {
+ eraseLine(myDom[0].low(), rint(currXVals.front())-1.0, y, myArray, bgr);
+ eraseLine(rint(currXVals.back())+1.0, myDom[0].high(), y, myArray, bgr);
+ }
+ else
+ {
+ eraseLine(myDom[0].low(), myDom[0].high(), y, myArray, bgr);
+ }
+ }
+ // Note:
+ // Couldn't get it working with an even/odd inside rule. Reason: If you
+ // want to do this correctly you have to classify two edges meeting into
+ // different categories to decide if they have to be put into currXVals
+ // once or twice. Otherwise you get problems. With this simplified version
+ // only convex polygons are filled correctly!
+
+ // delete the old currXVals
+ currXVals.clear();
+ }
+}
+
+r_Minterval
+r_Polygon::getBoundingBox() const throw(r_Error)
+{
+ if(!closed)
+ {
+ // TO DO: This should be an internal error sometimes.
+ TALK( "r_Polygon::getBoundingBox() polygon opened" );
+ RMInit::logOut << "r_Polygon::getBoundingBox() polygon opened" << std::endl;
+ throw(r_Error(r_Error::r_Error_General));
+ }
+
+ r_Minterval retVal(2);
+ r_Range minX = LONG_MAX;
+ r_Range maxX = LONG_MIN;
+ r_Range minY = LONG_MAX;
+ r_Range maxY = LONG_MIN;
+ r_Range currMinX=0, currMaxX=0, currMinY=0, currMaxY=0;
+ std::vector<r_Edge>::const_iterator iter, iterEnd;
+
+ for(iter = edges.begin(), iterEnd=edges.end(); iter != iterEnd; ++iter)
+ {
+ currMinX = (*iter).getStart()[0] < (*iter).getEnd()[0] ? (*iter).getStart()[0] : (*iter).getEnd()[0];
+ currMaxX = (*iter).getStart()[0] > (*iter).getEnd()[0] ? (*iter).getStart()[0] : (*iter).getEnd()[0];
+ currMinY = (*iter).getStart()[1] < (*iter).getEnd()[1] ? (*iter).getStart()[1] : (*iter).getEnd()[1];
+ currMaxY = (*iter).getStart()[1] > (*iter).getEnd()[1] ? (*iter).getStart()[1] : (*iter).getEnd()[1];
+ minX = currMinX < minX ? currMinX : minX;
+ maxX = currMaxX > maxX ? currMaxX : maxX;
+ minY = currMinY < minY ? currMinY : minY;
+ maxY = currMaxY > maxY ? currMaxY : maxY;
+ }
+ retVal << r_Sinterval(minX, maxX) << r_Sinterval(minY, maxY);
+ return retVal;
+}
+
+void
+r_Polygon::clip(const r_Minterval& clipDom) throw(r_Error)
+{
+ if(!closed)
+ {
+ // TO DO: This should be an internal error sometimes.
+ TALK( "r_Polygon::getBoundingBox() polygon opened" );
+ RMInit::logOut << "r_Polygon::getBoundingBox() polygon opened" << std::endl;
+ throw(r_Error(r_Error::r_Error_General));
+ }
+
+ std::vector<r_Point> pointList;
+
+ // Disjunct polygons used to crash the program.
+ // check if the bounding box of the polygon overlaps the clipDom
+ if(clipDom.intersects_with(getBoundingBox()))
+ {
+ // We just clip all 4 edges
+ for(int s = r_Polygon::top; s <= r_Polygon::right; ++s)
+ {
+ pointList=clip1Side(clipDom, (r_Polygon::Side)s);
+ if(pointList.empty()) // do we have intersection points?
+ {
+ // return a polygon with one line only. This should delete everything.
+ pointList.push_back(r_Point(clipDom[0].low(), clipDom[1].low()));
+ pointList.push_back(r_Point(clipDom[0].low(), clipDom[1].high()));
+ }
+ fromPoints(pointList);
+ pointList.clear();
+ }
+ }
+ else
+ {
+ // return a polygon with one line only. This should delete everything.
+ pointList.push_back(r_Point(clipDom[0].low(), clipDom[1].low()));
+ pointList.push_back(r_Point(clipDom[0].low(), clipDom[1].high()));
+ fromPoints(pointList);
+ }
+}
+
+
+void
+r_Polygon::scale(const r_Point& origin, const r_Minterval& mddDom,
+ const r_Minterval& clipDom, const double& scaleFactor) throw(r_Error)
+{
+ r_Dimension dim = origin.dimension();
+ std::vector<r_Point> oldPoints = getPoints();
+ std::vector<r_Point>::const_iterator iter = oldPoints.begin();
+ std::vector<r_Point>::const_iterator iterEnd = oldPoints.end();
+ std::vector<r_Point> newPoints;
+ r_Point tmpPoint(dim);
+ r_Range coord=0;
+
+ // iterate through all points
+ while( iter != iterEnd )
+ {
+ // currently only 2-D, but who knows
+ for (int i=0; i<dim; i++)
+ {
+ coord = (*iter)[i];
+ // This is yet another copy of the code in tile.cc (another one is
+ // in fastscale.cc). Hope it is exact enough if I do not do the
+ // correction for seamless tiling as done in Tile::getScaleDomain().
+ coord = (r_Range)(origin[i] + floor((coord - origin[i]) * scaleFactor));
+ // This domain thing is driving me crazy. Ok, now we still have to
+ // shift the domain so that it coincides with the origin of the
+ // MInterval used for clipping later (i.e. the domain of the MDD
+ // object which will be later filled using the polygon. See
+ // fastscale.cc, r_Fast_Scale<T>::get_scaled_image().
+ coord = coord + mddDom[i].high() - clipDom[i].high();
+ tmpPoint[i] = coord;
+ }
+ newPoints.push_back(tmpPoint);
+ ++iter;
+ }
+ fromPoints(newPoints);
+}
+
+
+void
+r_Polygon::scale(const r_Point& origin, const double& scaleFactor) throw(r_Error)
+{
+ r_Dimension dim = origin.dimension();
+ std::vector<r_Point> oldPoints = getPoints();
+ std::vector<r_Point>::const_iterator iter = oldPoints.begin();
+ std::vector<r_Point>::const_iterator iterEnd = oldPoints.end();
+ std::vector<r_Point> newPoints;
+ r_Point tmpPoint(dim);
+ r_Range coord=0;
+
+ //std::cout << "Polygon bounding box " << getBoundingBox() << std::endl;
+
+ // iterate through all points
+ while( iter != iterEnd )
+ {
+ // currently only 2-D, but who knows
+ for (int i=0; i<dim; i++)
+ {
+ coord = (*iter)[i];
+ // scaling is done in this way:
+ // translate to 0, scale and translate back
+ coord = origin[i]+(r_Range)floor((coord-origin[i]) * scaleFactor);
+ tmpPoint[i] = coord;
+ }
+ newPoints.push_back(tmpPoint);
+ ++iter;
+ }
+ fromPoints(newPoints);
+
+ //std::cout << "Polygon bounding box " << getBoundingBox() << std::endl;
+}
+
+void
+r_Polygon::mirror(const r_Minterval& mddDom) throw(r_Error)
+{
+ r_Dimension dim = mddDom.dimension();
+ std::vector<r_Point> oldPoints = getPoints();
+ std::vector<r_Point>::const_iterator iter = oldPoints.begin();
+ std::vector<r_Point>::const_iterator iterEnd = oldPoints.end();
+ std::vector<r_Point> newPoints;
+ r_Point tmpPoint(dim);
+ r_Range y=0;
+
+ // iterate through all points
+ while( iter != iterEnd )
+ {
+ y = mddDom[1].high() - (*iter)[1];
+ tmpPoint = (*iter);
+ tmpPoint[1] = y;
+ newPoints.push_back(tmpPoint);
+ ++iter;
+ }
+ fromPoints(newPoints);
+}
+
+void
+r_Polygon::fromPoints(const std::vector<r_Point>& newPoints) throw(r_Error)
+{
+ std::vector<r_Point>::const_iterator iter, iterEnd;
+
+ if(newPoints.empty())
+ {
+ TALK( "r_Polygon::fromPoinst(....) newPoints is empty" );
+ RMInit::logOut << "r_Polygon::fromPoinst(....) newPoints is empty" << std::endl;
+ throw r_Error(r_Error::r_Error_General);
+ }
+
+ iter = newPoints.begin();
+ iterEnd = newPoints.end();
+ edges.clear();
+
+ firstPoint = *iter;
+ currPoint = *iter;
+ while( ++iter != iterEnd )
+ {
+ edges.push_back(r_Edge(currPoint, *iter));
+ currPoint = *iter;
+ }
+ edges.push_back(r_Edge(currPoint, firstPoint));
+ closed = true;
+}
+
+void
+r_Polygon::eraseLine( r_Range x1, r_Range x2, r_Range y, r_GMarray& myArray, const std::string& bgr ) const throw(r_Error)
+{
+ // Do nothing in that case (may happen due to rounding problems)
+ if(x2 < x1)
+ return;
+
+ r_Minterval eraseDom(2);
+ eraseDom << r_Sinterval(x1, x2) << r_Sinterval(y, y);
+ r_Minterval arrayDom = myArray.spatial_domain();
+ r_Bytes typeSize = myArray.get_type_length();
+ r_Bytes bgrSize = bgr.size();
+ const char *bgrContent=bgr.c_str();
+ char *currCell=NULL;
+
+
+ // Grrr. In RasDaMan the y are stored close together. So the whole fillPolygon
+ // should have been organised by x instead of y. Well, for now I just use an
+ // r_Miter here.
+ r_Miter eraseIter( &eraseDom, &arrayDom, typeSize, myArray.get_array() );
+ while( !eraseIter.isDone() )
+ {
+ currCell = eraseIter.nextCell();
+ // FIXME This potentially wont work for all types. I just set every byte to 0.
+ if(bgr.empty())
+ memset(currCell, 0, typeSize);
+ else
+ {
+ if( typeSize != bgrSize)
+ throw r_Error( r_Error::r_Error_TypeInvalid );
+ memmove(currCell, bgrContent, bgrSize);
+ }
+ }
+}
+
+std::vector<r_Point>
+r_Polygon::clip1Side(const r_Minterval& b, r_Polygon::Side s)
+{
+ // This routine clips a polygon against one (endless) edge of a bounding box.
+ // It is an implementation of the Sutherland-Hodgman algorithm geared more
+ // towards readability than efficiency. The algorithm classifies edges into
+ // four cases:
+ // Case 1: both ends are inside. Then add the end point to the list of points.
+ // Case 2: start inside, end outside. And only the intersection of the
+ // bounding box edge and the polygon edge.
+ // Case 3: completely outside. Add no points.
+ // Case 4: start outside, end inside. Add end and the intersection of the
+ // bounding box edge and the polygon edge.
+
+ std::vector<r_Point> out;
+ std::vector<r_Edge>::const_iterator iter, iterEnd;
+
+ // iterate through all edges
+ for(iter = edges.begin(),iterEnd=edges.end(); iter != iterEnd; ++iter)
+ {
+ if(inside(b, (*iter).getEnd(), s))
+ {
+ if(inside(b, (*iter).getStart(), s))
+ {
+ // case 1
+ out.push_back((*iter).getEnd());
+ }
+ else
+ {
+ // case 4
+ out.push_back(intersect(b, *iter, s));
+ out.push_back((*iter).getEnd());
+ }
+ }
+ else
+ {
+ if(inside(b, (*iter).getStart(), s))
+ {
+ // case 2
+ out.push_back(intersect(b, *iter, s));
+ }
+ }
+ // do nothing for case 3
+ }
+ return out;
+}
+
+bool
+r_Polygon::inside(const r_Minterval& b, const r_Point& p, r_Polygon::Side s)
+{
+ switch(s)
+ {
+ case top:
+ return p[1] <= b[1].high();
+ case bottom:
+ return p[1] >= b[1].low();
+ case right:
+ return p[0] <= b[0].high();
+ case left:
+ return p[0] >= b[0].low();
+ default:
+ return false;
+ }
+}
+
+r_Point
+r_Polygon::intersect(const r_Minterval& b, const r_Edge& e, r_Polygon::Side s)
+{
+ switch(s)
+ {
+ case top:
+ return r_Point( e.getCurrX(b[1].high()), b[1].high() );
+ case bottom:
+ return r_Point( e.getCurrX(b[1].low()), b[1].low() );
+ case right:
+ return r_Point( b[0].high(), e.getCurrY(b[0].high()) );
+ default: //case left:
+ return r_Point( b[0].low(), e.getCurrY(b[0].low()) );
+ }
+}
+
+r_Point
+r_Polygon::getMiddle() const throw(r_Error)
+{
+ // Note that the summing up done here is a bit risky since overflows
+ // give incorrect results.
+
+ r_Point retVal(2);
+ double xSum = 0;
+ double ySum = 0;
+ int pointCount = 0;
+ std::vector<r_Point> myPoints = getPoints();
+ std::vector<r_Point>::const_iterator iter = myPoints.begin();
+ std::vector<r_Point>::const_iterator iterEnd = myPoints.end();
+
+ while( iter != iterEnd )
+ {
+ ySum += (*iter)[1];
+ xSum += (*iter)[0];
+ ++pointCount;
+ ++iter;
+ }
+ retVal[0] = rint((xSum / pointCount));
+ retVal[1] = rint((ySum / pointCount));
+
+ return retVal;
+}
+
+void
+r_Polygon::shrinkPoly(int pixelCount) throw(r_Error)
+{
+ // Ok now, we move all points towards the middle. Since we store edges we
+ // have to use this somewhat clumsy form with using points in between.
+ // Note that there is quite a bit of potential for error (e.g. points
+ // coinciding after moving them), Anyway, this was programmed as a quick
+ // hack for a problem at BLVA.
+ r_Point middle = getMiddle();
+ r_Dimension dim = middle.dimension();
+ std::vector<r_Point> oldPoints = getPoints();
+ std::vector<r_Point>::const_iterator iter = oldPoints.begin();
+ std::vector<r_Point>::const_iterator iterEnd = oldPoints.end();
+ std::vector<r_Point> newPoints;
+ r_Point tmpPoint(dim);
+ r_Range coord=0;
+
+ // iterate through all points
+ while( iter != iterEnd )
+ {
+ // currently only 2-D, but who knows
+ for (int i=0; i<dim; i++)
+ {
+ coord = (*iter)[i];
+ if(coord > middle[i])
+ {
+ coord = coord - pixelCount;
+ }
+ else
+ {
+ if(coord < middle[i])
+ {
+ coord = coord + pixelCount;
+ }
+ }
+ tmpPoint[i] = coord;
+ }
+ newPoints.push_back(tmpPoint);
+ ++iter;
+ }
+ fromPoints(newPoints);
+}
+
+
+int
+r_Polygon::countEdges() const
+{
+ return edges.size();
+}
+
+int
+r_Polygon::countHorizontalEdges() const
+{
+ int counter = 0;
+
+ std::vector<r_Edge>::const_iterator iter = edges.begin();
+
+ for(int i=0;i<edges.size();i++,iter++)
+ {
+ counter += iter->isHorizontal() ? 1:0;
+ }
+ return counter;
+}
+
diff --git a/rasodmg/polygon.hh b/rasodmg/polygon.hh
new file mode 100644
index 0000000..ebed9ea
--- /dev/null
+++ b/rasodmg/polygon.hh
@@ -0,0 +1,287 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: polygon.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Polygon
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_POLYGON_
+#define _R_POLYGON_
+
+#include <iostream>
+#include <vector>
+#include <string>
+
+#include "raslib/point.hh"
+#include "raslib/minterval.hh"
+
+class r_GMarray;
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ The class r_Edge is used to represent edges of 2-D polygons
+ represented in class r_Polygon. Edges cannot be modified. This does
+ not make sense, as a polygon always has to consist out of connecting
+ edges. Modifications should always be done on the polygon.
+
+*/
+
+class r_Edge
+{
+public:
+ /// constructor getting a 2-D start and end point.
+ r_Edge(const r_Point& newStart, const r_Point& newEnd);
+
+ /// retrieve 2-D start point of edge.
+ const r_Point& getStart() const;
+
+ /// retrieve 2-D end point of edge.
+ const r_Point& getEnd() const;
+
+ /// calculate inverse slope of the edge. Note: may throw exception due to division by 0.
+ double getInvSlope() const;
+
+ /// calculate slope of the edge. Note: may throw exception due to division by 0.
+ double getSlope() const;
+
+ /// retrieve x for a given y on a line with the slope of the edge. Calls getInvSlope().
+ double getCurrX(r_Range y) const;
+
+ /// retrieve y for a given x on a line with the slope of the edge. Calls getSlope().
+ double getCurrY(r_Range x) const;
+
+ /// print start and end point of the edge.
+ void print_status( std::ostream& s = std::cout ) const;
+
+ /// returns true if the edge is parallel to the first axis
+ bool isHorizontal() const;
+
+private:
+ /// start point of the edge.
+ r_Point start;
+
+ /// end point of the edge.
+ r_Point end;
+};
+
+/*@Doc:
+
+ The class r_Polygon is used to represent 2-D polygons in
+ RasDaMan. Polygons are always constructed by specifying a set of
+ points. This class is mainly used for doing polygonal cutouts on
+ r_Marray objects, it offers the relevant methods for that purpose.
+
+ The construction of a r_Polygon with addPoint has to finish with a
+ call to close(). A open polygon is not a legal polygon! Currently no
+ exceptions are thrown if a polygon is open and methods besides
+ addPointXY or close are called. The results are undefined, if the
+ polygon is not closed.
+
+*/
+
+class r_Polygon
+{
+public:
+
+ /// FIXME current we support only 2 dimensional polygon
+ static const r_Dimension polyPointDim;
+
+ /// enum used to clasify one polygon
+ enum r_Polygon_Type{
+ UNKNOWN,
+ CONCAVE,
+ CONVEX
+ };
+
+ /// constructor to initialize polygon from a string
+ r_Polygon(const char* init) throw (r_Error);
+
+ /// constructor getting x and y of the first point in the polygon.
+ r_Polygon(r_Range x, r_Range y);
+
+ /// copy constructor
+ r_Polygon(const r_Polygon&);
+
+ /// default constructor.
+ r_Polygon();
+
+ /// asignment opertor
+ r_Polygon& operator=(const r_Polygon&);
+
+ /// add a point to the polygon.
+ void addPoint(const r_Point& newPoint) throw(r_Error);
+
+ /// add a point to the polygon specifying x and y.
+ void addPointXY(r_Range x, r_Range y) throw(r_Error);
+
+ /// close a polygon after creation with addPointXY.
+ void close();
+
+ /// retrieve the set of all edges of the polygon.
+ const std::vector<r_Edge>& getEdges() const throw(r_Error);
+
+ /// determine the polygon type for an polygon in 2D
+ r_Polygon::r_Polygon_Type detectPolygonType() const throw(r_Error);
+ /**
+ It is assumed that the polygon is simple (does not intersect itself or have holes)
+ Returns UNKNOWN for incomputables eg: polygon with colinear points, polygon with less then 3 points
+ */
+
+ /// retrieve a vector of all points in the polygon.
+ std::vector<r_Point> getPoints() const throw(r_Error);
+ /**
+ Each point is connected with its successor. The last point is connected to the first one.
+ */
+
+ /// print all edges of the polygon.
+ void print_status( std::ostream& s = std::cout ) const;
+
+ /// Fill the 2-D array myArray according to the polygon.
+ void fillMArray( r_GMarray& myArray, bool fillInside = false, const std::string& bgr = "") const throw(r_Error);
+ /** The polygon has to be completely in the domain of the array. Should this not be the case,
+ then the polygon must be clipped according to the domain of the array. Filling is done
+ so that the data in the array is overwritten byte by byte with 0 which is not inside
+ the polygon.
+ */
+
+ /// retrieve the bounding box of the polygon.
+ r_Minterval getBoundingBox() const throw(r_Error);
+
+ /// clip the polygon according to the bounding box specified in clipDom.
+ void clip(const r_Minterval& clipDom) throw(r_Error);
+ /** Note that the r_Polygon object is modified! So after calling clip you will generally
+ have a different polygon represented by your object. */
+
+ /// scale the points of the polygon according to scaleFactor.
+ void scale(const r_Point& origin, const r_Minterval& mddDom,
+ const r_Minterval& clipDom, const double& scaleFactor) throw(r_Error);
+ /** This function is used when using a polygon to extract part of an image retrieved
+ with r_Fast_Scale. The scaling is done like in r_Fast_Base_Scale::get_scaled_domain().
+ origin is the point of origin for the scaling. mddDom is the domain of the MDD which
+ will later be filled with the polygon. Problem is, that the domain of this MDD is
+ currently not created by simply scaling the domain of the original MDD. Instead it
+ is made sure that the origin of the scaled domain stays the same. clipDom is used
+ to do the same when scaling the polygon, it contains the scaled domain of the MDD
+ without shifting it to origin of the domain of the MDD before scaling. It is a
+ bit complicated, I know. scaleFactor is trivially the scaleFactor used. */
+
+ /// scale the points of the polygon according to scaleFactor.
+ void scale(const r_Point& origin, const double& scaleFactor) throw(r_Error);
+ /** This function is used used when we scale a polygon to extract part of an image retrieved
+ with r_Fast_Scale. The scaling is done like in r_Fast_Base_Scale::get_scaled_domain().
+ origin is the point of origin for the scaling. scaleFactor is the scale factor used. */
+
+ /// mirrors a polygon along the y-axes point by point.
+ void mirror(const r_Minterval& mddDom) throw(r_Error);
+ /** The mirroring is done along the middle of mddDom. It is done like that to be coherent
+ with the mirroring commonly done when inserting TIFF image, e.g. in insertlva.cc. */
+
+ /// get "middle" point by averaging all x and y values.
+ r_Point getMiddle() const throw(r_Error);
+
+ /// "shrink" polygon by moving all points towards the middle by pixelCount pixels.
+ void shrinkPoly(int pixelCount) throw(r_Error);
+
+ /// returns the number of edges
+ int countEdges() const;
+
+ /// returns the number of horizontal edges (used by polygon cut out)
+ int countHorizontalEdges() const;
+
+private:
+
+ /// check if the current point is the first point to close the polygon
+ void checkFistPoint();
+
+ /// clipping is done side by side. This enum is used to tell functions which side to clip.
+ enum Side {
+ top, bottom, left, right
+ };
+
+ /// overwrite this with a polygon create from a vector of points.
+ void fromPoints(const std::vector<r_Point>& newPoints) throw(r_Error);
+
+ /// erase the area in myArray outside of the polygon for one scanline.
+ void eraseLine( r_Range x1, r_Range x2, r_Range y, r_GMarray& myArray, const std::string& bgr ) const throw(r_Error);
+
+ /// return the polygon clipped on the specified side as a list of points.
+ std::vector<r_Point> clip1Side(const r_Minterval& b, r_Polygon::Side s);
+
+ /// determine if a point is inside a bounding line on a certain side.
+ bool inside(const r_Minterval& b, const r_Point& p, r_Polygon::Side s);
+
+ /// intersect an edge with a bounding line on a certain side.
+ r_Point intersect(const r_Minterval& b, const r_Edge& e, r_Polygon::Side s);
+
+ /// flag if the polygon is closed.
+ bool closed;
+
+ /// flag if firstPoint has been set.
+ bool firstPointSet;
+
+ /// vector of all edges of the polygon.
+ std::vector<r_Edge> edges;
+ /// remember first point. Used when constructing the polygon.
+
+ r_Point firstPoint;
+
+ /// remember last added point. Used when constructing the polygon.
+ r_Point currPoint;
+};
+
+extern std::ostream& operator<<( std::ostream& s, const r_Polygon& d );
+
+// The following classes are STL function objects which can be used to make
+// sorted collection of r_Edge. In the current implementation only the first
+// one is needed.
+
+class EdgeSortCriterion
+{
+public:
+ // This is needed for keeping a sorted set of edges (sorted by start coordinate y,
+ // then start coordinate x).
+ bool operator() (const r_Edge& e1, const r_Edge& e2) const {
+ return e1.getStart()[1] < e2.getStart()[1] ||
+ (!(e2.getStart()[1] < e1.getStart()[1]) && e1.getStart()[0] < e2.getStart()[0]);
+ }
+};
+
+class ActiveEdgeSortCriterion
+{
+public:
+ // This is needed for keeping a sorted set of active edges (sorted by start coordinate x,
+ // then start coordinate y).
+ bool operator() (const r_Edge& e1, const r_Edge& e2) const {
+ return e1.getStart()[0] < e2.getStart()[0] ||
+ (!(e2.getStart()[0] < e1.getStart()[0]) && e1.getStart()[1] < e2.getStart()[1]);
+ }
+};
+
+#endif
diff --git a/rasodmg/ref.cc b/rasodmg/ref.cc
new file mode 100644
index 0000000..b63be0e
--- /dev/null
+++ b/rasodmg/ref.cc
@@ -0,0 +1,656 @@
+/*
+* 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: ref.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Ref
+ *
+ * COMMENTS:
+ * None
+*/
+
+static const char rcsidref[] = "@(#)rasodmg, r_Ref: $Id: ref.cc,v 1.28 2002/08/28 12:10:18 coman Exp $";
+
+#include "rasodmg/database.hh"
+#include "rasodmg/ref.hh"
+
+#include "raslib/rmdebug.hh"
+
+#ifdef __VISUALC__
+#include <sstrea.h>
+#else
+#include <sstream>
+#endif
+
+#include "rasodmg/transaction.hh"
+#include "clientcomm/clientcomm.hh"
+
+// forward declaration needed because of EARLY_TEMPLATE
+class r_Transaction;
+
+// In case of early templates take care non-template code is only
+// compiled once.
+#ifndef __EXECUTABLE__
+
+r_Ref_Any::r_Ref_Any()
+ : memptr(0), oid()
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "r_Ref_Any()")
+}
+
+
+
+r_Ref_Any::r_Ref_Any( const r_Ref_Any& obj )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "r_Ref_Any( const r_Ref_Any& )")
+ memptr = obj.memptr;
+ oid = obj.oid;
+}
+
+
+
+r_Ref_Any::r_Ref_Any( const r_OId& initOId )
+ : memptr(0)
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "r_Ref_Any( const r_OId& )")
+ oid = initOId;
+}
+
+
+
+r_Ref_Any::r_Ref_Any( r_Object* ptr )
+ : oid(), memptr( ptr )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "r_Ref_Any( r_Object* )")
+}
+
+
+
+r_Ref_Any::r_Ref_Any( void* ptr )
+ : oid(), memptr( ptr )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "r_Ref_Any( void* )")
+}
+
+
+r_Ref_Any::r_Ref_Any( const r_OId &initOId, r_Object* ptr )
+ : oid( initOId ), memptr( ptr )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "r_Ref_Any( const r_OId &oid, const r_Object* )")
+}
+
+
+
+r_Ref_Any::~r_Ref_Any()
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "~r_Ref_Any()")
+
+ // object should not be delete from databse when reference destructor is called
+ // if( memptr ){
+ // delete memptr;
+ // memptr = 0;
+ // }
+}
+
+
+
+r_Ref_Any&
+r_Ref_Any::operator=( const r_Ref_Any& objptr )
+{
+ memptr = objptr.memptr;
+ oid = objptr.oid;
+
+ return *this;
+}
+
+
+
+r_Ref_Any&
+r_Ref_Any::operator=( r_Object* ptr )
+{
+ memptr = ptr;
+ oid = r_OId();
+
+ return *this;
+}
+
+
+
+void
+r_Ref_Any::destroy()
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "destroy()")
+
+ if( memptr && !oid.is_valid() ){
+ delete memptr;
+ memptr = 0;
+ }
+}
+
+
+void
+r_Ref_Any::delete_object()
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "delete_object()")
+
+ if( memptr ){
+ delete memptr;
+ memptr = 0;
+ }
+}
+
+
+
+r_Ref_Any::operator const void*() const
+{
+ return memptr;
+}
+
+
+
+r_Ref_Any::operator void*()
+{
+ return memptr;
+}
+
+
+
+r_Ref_Any::operator r_Point*()
+{
+ return (r_Point*)memptr;
+}
+
+
+
+r_Ref_Any::operator r_Sinterval*()
+{
+ return (r_Sinterval*)memptr;
+}
+
+
+
+r_Ref_Any::operator r_Minterval*()
+{
+ return (r_Minterval*)memptr;
+}
+
+
+
+r_Ref_Any::operator r_OId*()
+{
+ return (r_OId*)memptr;
+}
+
+
+
+r_Ref_Any::operator r_Scalar*()
+{
+ return (r_Scalar*)memptr;
+}
+
+
+
+r_Ref_Any::operator r_Primitive*()
+{
+ return (r_Primitive*)memptr;
+}
+
+
+
+r_Ref_Any::operator r_Structure*()
+{
+ return (r_Structure*)memptr;
+}
+
+
+
+int
+r_Ref_Any::operator!() const
+{
+ return !is_null();
+}
+
+
+
+int
+r_Ref_Any::is_null() const
+{
+ return (memptr==0) && !oid.is_valid();
+}
+
+
+
+int
+r_Ref_Any::operator==( const r_Ref_Any& ref ) const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "operator==( const r_Ref_Any& )")
+ return // both refs are not valid or ...
+ ( is_null() && ref.is_null() ) ||
+ // both oids are valid and the same or ...
+ ( oid.is_valid() && oid == ref.oid ) ||
+ // both oids are not valid and memory pointers are the same
+ ( !oid.is_valid() && !ref.oid.is_valid() && memptr == ref.memptr );
+}
+
+
+
+int
+r_Ref_Any::operator!=( const r_Ref_Any& ref ) const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "operator!=( const r_Ref_Any& )")
+ return !operator==( ref );
+}
+
+
+
+int
+r_Ref_Any::operator==( const r_Object* ptr ) const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "operator==( const r_Object* )")
+ return memptr == (void*)ptr;
+}
+
+
+
+int
+r_Ref_Any::operator!=( const r_Object* ptr ) const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref_Any", "operator!=( const r_Object* )")
+ return !operator==( ptr );
+}
+
+
+
+
+void*
+r_Ref_Any::get_memory_ptr() const
+{
+ return memptr;
+}
+
+#endif // __EXECUTABLE__
+
+
+
+template<class T>
+r_Ref<T>::r_Ref()
+ : memptr(0), oid()
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "r_Ref()")
+}
+
+
+
+template<class T>
+r_Ref<T>::r_Ref( const r_Ref<T>& obj )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "r_Ref( const r_Ref<T>& )")
+ memptr = obj.memptr;
+ oid = obj.oid;
+}
+
+
+
+template<class T>
+r_Ref<T>::r_Ref( const r_OId& initOId )
+ : memptr(0)
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "r_Ref( const r_OId& )")
+ oid = initOId;
+}
+
+
+
+template<class T>
+r_Ref<T>::r_Ref( const r_Ref_Any& obj )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "r_Ref( const r_Ref_Any& )")
+
+ memptr = (T*)obj.get_memory_ptr();
+ oid = obj.get_oid();
+}
+
+
+
+template<class T>
+r_Ref<T>::r_Ref( T* ptr )
+ : oid(), memptr( ptr )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "r_Ref( const T* )")
+}
+
+
+
+template<class T>
+r_Ref<T>::r_Ref( const r_OId &initOId, T* ptr )
+ : oid( initOId ), memptr( ptr )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "r_Ref( const r_OId &oid, const T* )")
+}
+
+
+
+template<class T>
+r_Ref<T>::~r_Ref()
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "~r_Ref()")
+
+ // object should not be delete from databse when reference destructor is called
+ // if( memptr ){
+ // delete memptr;
+ // memptr = 0;
+ // }
+}
+
+
+
+template<class T>
+r_Ref<T>::operator r_Ref_Any() const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator r_Ref_Any()")
+ return r_Ref_Any( oid, (r_Object *)memptr );
+}
+
+
+/*
+template<class T>
+r_Ref<T>::operator const r_Ref_Any() const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator const r_Ref_Any()")
+ return r_Ref_Any( oid, memptr );
+}
+*/
+
+template<class T>
+r_Ref<T>&
+r_Ref<T>::operator=( const r_Ref_Any& ptr )
+{
+ memptr = (T*)ptr.get_memory_ptr();
+ oid = ptr.get_oid();
+
+ return *this;
+}
+
+
+
+template<class T>
+r_Ref<T>&
+r_Ref<T>::operator=( T* ptr )
+{
+ memptr = ptr;
+ oid = r_OId();
+
+ return *this;
+}
+
+
+
+/*
+template<class T>
+r_Ref<T>&
+r_Ref<T>::operator=( r_Ref<T>& objptr )
+{
+ memptr = objptr.memptr;
+ oid = objptr.oid;
+
+ return *this;
+}
+*/
+
+
+template<class T>
+r_Ref<T>&
+r_Ref<T>::operator=( const r_Ref<T>& objptr )
+{
+ memptr = objptr.memptr;
+ oid = objptr.oid;
+
+ return *this;
+}
+
+
+
+template<class T>
+const T&
+r_Ref<T>::operator*() const throw( r_Error )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator*()")
+ if( !memptr )
+ load_object();
+
+ if( !memptr )
+ {
+ r_Error err = r_Error( r_Error::r_Error_RefNull );
+ throw err;
+ }
+
+ return *memptr;
+}
+
+
+template<class T>
+T&
+r_Ref<T>::operator*() throw( r_Error )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator*()")
+ if( !memptr )
+ load_object();
+
+ if( !memptr )
+ {
+ r_Error err = r_Error( r_Error::r_Error_RefNull );
+ throw err;
+ }
+
+ return *memptr;
+}
+
+
+
+template<class T>
+const T*
+r_Ref<T>::operator->() const throw( r_Error )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator->()")
+ if( !memptr )
+ load_object();
+
+ if( !memptr )
+ {
+ r_Error err = r_Error( r_Error::r_Error_RefNull );
+ throw err;
+ }
+
+ return memptr;
+}
+
+template<class T>
+T*
+r_Ref<T>::operator->() throw( r_Error )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator->()")
+ if( !memptr )
+ load_object();
+
+ if( !memptr )
+ {
+ r_Error err = r_Error( r_Error::r_Error_RefNull );
+ throw err;
+ }
+
+ return memptr;
+}
+
+
+
+template<class T>
+const T*
+r_Ref<T>::ptr() const throw( r_Error )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "ptr()")
+ if( !memptr )
+ load_object();
+
+ return memptr;
+}
+
+
+template<class T>
+T*
+r_Ref<T>::ptr() throw( r_Error )
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "ptr()")
+ if( !memptr )
+ load_object();
+
+ return memptr;
+}
+
+
+
+template<class T>
+int
+r_Ref<T>::operator!() const
+{
+ return !is_null();
+}
+
+
+
+template<class T>
+int
+r_Ref<T>::is_null() const
+{
+ return (memptr==0) && !oid.is_valid();
+}
+
+
+
+template<class T>
+int
+r_Ref<T>::operator==( const r_Ref<T>& refR ) const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator==( const r_Ref<T>& )")
+ return // both refs are not valid or ...
+ ( is_null() && refR.is_null() ) ||
+ // both oids are valid and the same or ...
+ ( oid.is_valid() && oid == refR.oid ) ||
+ // both oids are not valid and memory pointers are the same
+ ( !oid.is_valid() && !refR.oid.is_valid() && memptr == refR.memptr );
+}
+
+
+
+template<class T>
+int
+r_Ref<T>::operator!=( const r_Ref<T>& refR ) const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator!=( const r_Ref<T>& )")
+ return !operator==( refR );
+}
+
+
+
+template<class T>
+int
+r_Ref<T>::operator==( const T* ptr ) const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator==( const T* )")
+ return memptr == ptr;
+}
+
+
+
+template<class T>
+int
+r_Ref<T>::operator!=( const T* ptr ) const
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "operator!=( const T* )")
+ return !operator==( ptr );
+}
+
+
+template<class T>
+void
+r_Ref<T>::destroy()
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "destroy()")
+
+ if( memptr && !oid.is_valid() ){
+ delete memptr;
+ memptr = 0;
+ }
+}
+
+
+
+template<class T>
+void
+r_Ref<T>::delete_object()
+{
+ RMDBGONCE(4, RMDebug::module_rasodmg, "r_Ref", "delete_object()")
+
+ if( memptr ){
+ delete memptr;
+ memptr = 0;
+ }
+}
+
+
+
+template<class T>
+T*
+r_Ref<T>::get_memory_ptr() const
+{
+ return memptr;
+}
+
+#ifdef DEF_TRANSACTION
+
+template<class T>
+void
+r_Ref<T>::load_object() const
+{
+ if( oid.is_valid() )
+ {
+ if( r_Database::actual_database == 0 || r_Database::actual_database->get_status() == r_Database::not_open )
+ {
+ r_Error err = r_Error( r_Error::r_Error_DatabaseClosed );
+ throw err;
+ }
+
+ if( r_Transaction::actual_transaction == 0 ||
+ r_Transaction::actual_transaction->get_status() != r_Transaction::active )
+ {
+ r_Error err = r_Error( r_Error::r_Error_TransactionNotOpen );
+ throw err;
+ }
+
+ // load object and take its memory pointer
+ r_Ref<T> ref = r_Transaction::actual_transaction->load_object( oid );
+ memptr = ref.get_memory_ptr();
+ }
+}
+
+#endif
diff --git a/rasodmg/ref.hh b/rasodmg/ref.hh
new file mode 100644
index 0000000..2b5678e
--- /dev/null
+++ b/rasodmg/ref.hh
@@ -0,0 +1,323 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: ref.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Ref, r_Ref_Any
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_REF_
+#define _D_REF_
+
+#include "raslib/error.hh"
+#include "raslib/oid.hh"
+
+class r_Object;
+class r_Point;
+class r_Sinterval;
+class r_Minterval;
+class r_Oid;
+class r_Scalar;
+class r_Primitive;
+class r_Structure;
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/**
+ The class \Ref{r_Ref_Any} is defined to support a reference to any
+ type. Its primary purpose is to handle generic refernces and allow
+ conversions of \Ref{r_Ref}s in the type hierarchy. A \Ref{r_Ref_Any}
+ object can be used as an intermediary between any two types \Ref{r_Ref}<X>
+ and \Ref{r_Ref}<Y> where X and Y are different types. A \Ref{r_Ref}<T> can
+ always be converted to a \Ref{r_Ref_Any}; there is a function to perform
+ the conversion in the \Ref{r_Ref}<T> template. Each \Ref{r_Ref}<T> class
+ has a constructor and assignment operator that takes a reference to a
+ \Ref{r_Ref_Any}.
+*/
+
+class r_Ref_Any
+{
+ public:
+ /// default constructor
+ r_Ref_Any();
+
+ /// copy constructor
+ r_Ref_Any( const r_Ref_Any& );
+
+ /// constructor for creating a reference with an oid
+ r_Ref_Any( const r_OId& initOId );
+ /**
+ Dereferencing the self object results in loading the object with {\tt initOId}.
+ */
+
+ /// constructor getting a pointer to a persistent capable object
+ r_Ref_Any( r_Object* );
+
+ /// constructor getting a general pointer
+ r_Ref_Any( void* );
+
+ /// destructor deletes referenced object from main memory and database
+ ~r_Ref_Any();
+
+ /// assignment operator for assigning a \Ref{r_Ref_Any} pointer
+ r_Ref_Any& operator=( const r_Ref_Any& );
+
+ /// assignment operator for assigning a pointer to a persistent capable object
+ r_Ref_Any& operator=( r_Object* );
+
+ /// delete from main memory
+ void destroy();
+
+ /// deletes referenced object from main memory and database
+ void delete_object();
+
+ //@Man: Cast operators:
+ //@{
+ ///
+
+ ///
+ operator const void*() const;
+ ///
+ operator void*();
+ ///
+ operator r_Point*();
+ ///
+ operator r_Sinterval*();
+ ///
+ operator r_Minterval*();
+ ///
+ operator r_OId*();
+ ///
+ operator r_Scalar*();
+ ///
+ operator r_Structure*();
+ ///
+ operator r_Primitive*();
+
+ ///
+ //@}
+
+
+ /// operator for validity test
+ int operator!() const;
+
+ /// method for reference validity test
+ int is_null() const;
+ /**
+ The method delivers true iff the oid and/or the memory pointer are valid.
+ */
+
+ //@Man: Comparison operators:
+ //@{
+ ///
+
+ ///
+ int operator==( const r_Ref_Any& ) const;
+ ///
+ int operator!=( const r_Ref_Any& ) const;
+ /// compares the memory pointer (does not load the object)
+ int operator==( const r_Object* ) const;
+ /// compares the memory pointer (does not load the object)
+ int operator!=( const r_Object* ) const;
+
+ ///
+ //@}
+
+ /// get oid
+ inline const r_OId& get_oid() const;
+
+ //@Man: Methods for internal use only
+ //@{
+ ///
+ /// constructor getting oid and memory pointer
+ r_Ref_Any( const r_OId&, r_Object* );
+ ///
+ inline unsigned int is_oid_valid() const;
+ /// get memory pointer (without loading the object)
+ void* get_memory_ptr() const;
+ ///
+ //@}
+
+ private:
+ /// main memory pointer
+ void* memptr;
+
+ /// object identifier
+ r_OId oid;
+};
+
+
+
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/**
+ References of type \Ref{r_Ref} in many respects behave like
+ C++ pointers but provide an additional mechanism that guarantees
+ integrity in references to persistent objects. \Ref{r_Ref}
+ implements a so called {\bf smart pointer} which behaves like
+ a C++ pointer but can do additional things in time of dereferencing
+ the pointer. In case that no valid memory pointer is available,
+ which means that the object is not present, and an oid is existing,
+ the object belonging to the oid is read from the db and the new
+ memory pointer is given back.
+*/
+
+template<class T>
+class r_Ref
+{
+ public:
+ /// default constructor
+ r_Ref();
+
+ /// constructor for r_Ref_Any objects
+ r_Ref( const r_Ref_Any& );
+
+ /// constructor for creating a reference with an oid
+ r_Ref( const r_OId& initOId );
+ /**
+ Dereferencing the self object results in loading the object with {\tt initOId}.
+ */
+
+ /// copy constructor
+ r_Ref( const r_Ref<T>& );
+
+ /// destructor deletes referenced object from main memory and database
+ ~r_Ref();
+
+ /// cast to \Ref{r_Ref_Any}
+ operator r_Ref_Any() const;
+
+ // cast to const \Ref{r_Ref_Any}
+ // operator const r_Ref_Any() const;
+
+ /// assignment operator for assigning a \Ref{r_Ref_Any}
+ r_Ref<T>& operator=( const r_Ref_Any& );
+
+ /// assignment operator for assigning a C pointer
+ r_Ref<T>& operator=( T* );
+
+ // assignment operator for assigning a r_Ref pointer
+ // r_Ref<T>& operator=( r_Ref<T>& );
+
+ /// assignment operator for assigning a r_Ref pointer
+ r_Ref<T>& operator=( const r_Ref<T>& );
+
+ /// dereference operator (error kinds: r_Error_RefNull, r_Error_RefInvalid)
+ const T& operator*() const throw (r_Error);
+
+ /// dereference operator (error kinds: r_Error_RefNull, r_Error_RefInvalid)
+ T& operator*() throw( r_Error );
+ /**
+ If the memory pointer is zero and the oid is valid, the object is loaded from the server
+ and a reference to the object in memory is returned.
+ */
+
+ const T* operator->() const throw (r_Error);
+
+ /// operator for dereferencing the reference (error kinds: r_Error_RefNull, r_Error_RefInvalid)
+ T* operator->() throw( r_Error );
+ /**
+ If the memory pointer is zero and the oid is valid, the object is loaded from the server
+ and the new memory location is returned.
+ */
+
+ const T* ptr() const throw (r_Error);
+
+ /// method for dereferencing the reference (error kinds: r_Error_RefNull, r_Error_RefInvalid)
+ T* ptr() throw( r_Error );
+ /**
+ If the memory pointer is zero and the oid is valid, the object is loaded from the server
+ and the new memory location is returned.
+ */
+
+ /// operator for validity test
+ int operator!() const;
+
+ /// method for reference validity test
+ int is_null() const;
+ /**
+ The method delivers true iff the oid and/or the memory pointer are valid.
+ */
+
+ //@Man: Comparison operators:
+ //@{
+ ///
+
+ ///
+ int operator==( const r_Ref<T>& refR ) const;
+ ///
+ int operator!=( const r_Ref<T>& refR ) const;
+ /// compares the memory pointer (does not load the object)
+ int operator==( const T* ) const;
+ /// compares the memory pointer (does not load the object)
+ int operator!=( const T* ) const;
+
+ ///
+ //@}
+
+ /// delete from main memory
+ void destroy();
+
+ /// deletes referenced object from main memory and database
+ void delete_object();
+
+ /// get oid
+ inline const r_OId& get_oid() const;
+
+ //@Man: Methods for internal use only
+ //@{
+ ///
+ /// constructor getting memory pointer
+ r_Ref( T* );
+
+ /// constructor getting oid and memory pointer
+ r_Ref( const r_OId&, T* );
+
+ /// get memory pointer (without loading the object)
+ T* get_memory_ptr() const;
+
+ ///
+ inline unsigned int is_oid_valid() const;
+
+ ///
+ //@}
+
+ private:
+ /// loads an object from database
+ void load_object() const;
+
+ /// main memory pointer
+ mutable T* memptr;
+
+ /// object identifier
+ r_OId oid;
+};
+
+#include "rasodmg/ref.icc"
+
+#endif
diff --git a/rasodmg/ref.icc b/rasodmg/ref.icc
new file mode 100644
index 0000000..8289b8f
--- /dev/null
+++ b/rasodmg/ref.icc
@@ -0,0 +1,64 @@
+/*
+* 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>.
+/
+/**
+ * INLINE SOURCE: ref.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Ref
+ *
+ * COMMENTS:
+ * None
+*/
+
+
+inline const r_OId&
+r_Ref_Any::get_oid() const
+{
+ return oid;
+}
+
+
+
+inline unsigned int
+r_Ref_Any::is_oid_valid() const
+{
+ return oid.is_valid();
+}
+
+
+
+template<class T>
+inline const r_OId&
+r_Ref<T>::get_oid() const
+{
+ return oid;
+}
+
+
+
+template<class T>
+inline unsigned int
+r_Ref<T>::is_oid_valid() const
+{
+ return oid.is_valid();
+}
diff --git a/rasodmg/set.cc b/rasodmg/set.cc
new file mode 100644
index 0000000..b79fc4e
--- /dev/null
+++ b/rasodmg/set.cc
@@ -0,0 +1,92 @@
+/*
+* 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: set.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Set
+ *
+ * COMMENTS:
+ * None
+*/
+
+
+static const char rcsidset[] = "@(#)rasodmg, r_Set: $Id: set.cc,v 1.17 2002/08/23 11:18:44 schatz Exp $";
+
+#include "rasodmg/set.hh"
+
+class r_GMarray;
+
+#ifdef __VISUALC__
+ template class r_Set< r_GMarray *>;
+#endif
+
+#ifndef __GNUG__
+#define NULL 0
+#endif
+
+template<class T>
+r_Set<T>::r_Set() throw(r_Error)
+ : r_Collection<T>()
+{
+ this->allowsDuplicates = 0;
+ this->isOrdered = 0;
+ this->card = 0;
+}
+
+/* OBSOLETE
+template<class T>
+r_Set<T>::r_Set( const char* name )
+ : r_Collection<T>( name )
+{
+ allowsDuplicates = 0;
+ isOrdered = 0;
+ card = 0;
+}
+*/
+
+template<class T>
+r_Set<T>::r_Set( const r_Set<T>& set ) throw(r_Error)
+ : r_Collection<T>( set )
+{
+ this->allowsDuplicates = 0;
+ this->isOrdered = 0;
+}
+
+template<class T>
+r_Set<T>::~r_Set()
+{
+}
+
+template<class T>
+void
+r_Set<T>::insert_element( const T& element, int no_modification )
+{
+ typename r_Collection<T>::CNode* ptr = (typename r_Collection<T>::CNode*)this->coll;
+
+ while ( ptr->next != NULL && *((T*)(ptr->elem)) != element )
+ ptr = ptr->next;
+
+ if ( ptr->elem == NULL || *((T*)(ptr->elem)) != element )
+ r_Collection<T>::insert_element( element, no_modification );
+}
diff --git a/rasodmg/set.hh b/rasodmg/set.hh
new file mode 100644
index 0000000..b9f4915
--- /dev/null
+++ b/rasodmg/set.hh
@@ -0,0 +1,79 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: set.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Set
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _D_SET_
+#define _D_SET_
+
+#include "rasodmg/collection.hh"
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ The class implements a set container. It inherits most of the
+ functionality from {\tt r_Collection}. The set can not have
+ any duplicates and it is not ordered.
+
+*/
+
+template <class T>
+class r_Set : public r_Collection<T>
+{
+ public:
+ /// default constructor
+ r_Set() throw(r_Error);
+ /// copy constructor
+ r_Set( const r_Set<T>& set ) throw(r_Error);
+ /// virtual destructor
+ virtual ~r_Set();
+
+ /// inserts an element at the beginning (no duplicates)
+ virtual void insert_element( const T& element, int no_modification = 0 );
+ /**
+ The method inserts an element into the collection. If {\tt no_modification}
+ is set, the {\tt mark_modified()} method of r_Object is not invoked and, therefore,
+ a modification will not be recognized at the commit point.
+ */
+
+};
+
+#ifdef EARLY_TEMPLATE
+#ifdef __EXECUTABLE__
+#ifdef __VISUALC__
+#include "rasodmg/set.cpp"
+#else
+#include "rasodmg/set.cc"
+#endif
+#endif
+#endif
+
+#endif
diff --git a/rasodmg/stattiling.cc b/rasodmg/stattiling.cc
new file mode 100644
index 0000000..d99df04
--- /dev/null
+++ b/rasodmg/stattiling.cc
@@ -0,0 +1,678 @@
+/*
+* 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: stattiling.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Stat_Tiling r_Access
+ *
+ * COMMENTS:
+ * None
+ */
+
+#ifdef __VISUALC__
+// Diable warning for signed/unsigned mismatch.
+#pragma warning( disable : 4018 )
+#endif
+
+#include "rasodmg/interesttiling.hh"
+#include "rasodmg/alignedtiling.hh"
+#include "rasodmg/stattiling.hh"
+#include "raslib/rminit.hh"
+#include "raslib/rmdebug.hh"
+
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+#include <cstdlib>
+
+// Uncoment the _VISUALIZE_2D_DECOMP_ line to generate ppm files the
+// visualization of the domain decomposition done by the algoritm
+// #define _VISUALIZE_2D_DECOMP_
+
+// Uncomment the following line to have debug information (printfs)
+// #define _DEBUG_STATTILING_
+
+#ifdef _VISUALIZE_2D_DECOMP_
+#include "tools/visualtiling2d.hh"
+#endif
+
+const char*
+r_Stat_Tiling::description = "dimensions, access patterns, border threshold, interesting threshold, tile size (in bytes) (ex: \"2;[0:9,0:9],3;[100:109,0:9],2;2;0.3;100\")";
+
+const r_ULong
+r_Stat_Tiling::DEF_BORDER_THR = 50;
+const r_Double
+r_Stat_Tiling::DEF_INTERESTING_THR = 0.20;
+
+r_Stat_Tiling::r_Stat_Tiling(const char* encoded) throw (r_Error)
+ : r_Dimension_Tiling(0, 0)
+{
+ if(!encoded)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << (encoded?encoded: "NULL") << ")" << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ r_Dimension tileD=0;
+ std::vector<r_Access> vectAccessInfo;
+ r_Access* accessInfo=NULL;
+ r_Minterval* accessInterv=NULL;
+ r_ULong accessTimes=0;
+ r_Bytes tileS=0, lenToConvert=0, lenInToConvert=0;
+ r_Area borderTH=0;
+ r_Double interestTH=0.;
+ const char *pStart=NULL, *pEnd=NULL, *pRes=NULL, *pTemp=NULL;
+ char *pToConvert=NULL;
+ const char *pInRes=NULL, *pInEnd=NULL;
+ char *pInToConvert=NULL;
+
+ pStart=encoded;
+ pEnd=pStart+strlen(pStart);
+ pTemp=pStart;
+
+ pRes=strstr(pTemp,COLON);
+ if(!pRes)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding tile dimension from \"" << pTemp << "\"." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with dimension
+ 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_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding tile dimension from \"" << pToConvert << "\", is not a number." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if (tileD < 0)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding tile dimension from \"" << pToConvert << "\", is negative." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //skip COLON && free buffer
+ delete[] pToConvert;
+ if(pRes != (pEnd-1))
+ pRes++;
+ else
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access information from \"" << pStart << "\", end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with access informations
+ pTemp=pRes;
+ pRes=strstr(pTemp, COLON);
+ if(!pRes)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access information from \"" << pTemp << "\"." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ while(pRes)
+ {
+ //is access info?
+ if(*pTemp!=*LSQRBRA)
+ break;
+
+ //copy substring in buffer
+ lenToConvert=pRes-pTemp;
+ pToConvert=new char[lenToConvert+1];
+ memcpy(pToConvert, pTemp, lenToConvert);
+ pToConvert[lenToConvert]='\0';
+
+ //deal with access Interval
+ pInEnd=pToConvert+strlen(pToConvert);
+ pInRes=strstr(pToConvert, RSQRBRA);
+ if(!pInRes)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access information from \"" << pToConvert << "\"." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ lenInToConvert=pInRes-pToConvert+1; //1 for ]
+ pInToConvert=new char[lenInToConvert+1];
+ memcpy(pInToConvert, pToConvert, lenInToConvert);
+ pInToConvert[lenInToConvert]='\0';
+
+ try
+ {
+ accessInterv=new r_Minterval(pInToConvert);
+ delete [] pInToConvert;
+ }
+ catch(r_Error &err)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access interval \"" << pInToConvert << "\" from \"" << pToConvert << "\"." << endl;
+ RMInit::logOut << "Error " << err.get_errorno() << " : " << err.what() << endl;
+ delete[] pInToConvert;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with access Times
+ pInRes=strstr(pInRes, COMMA);
+ if(!pInRes)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access times \"" << pInRes << "\" from acess information \"" << pToConvert << "\", not specified." << endl;
+ delete[] pInToConvert;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if(pInRes!=(pEnd-1))
+ pInRes++;
+ else
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access times \"" << pInRes << "\" from acess information \"" << pToConvert << "\", not specified." << endl;
+ delete[] pInToConvert;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ accessTimes=strtol(pInRes, (char**)NULL, DefaultBase);
+ if(!accessTimes)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access times \"" << pInRes << "\" from acess information \"" << pToConvert << "\", not a number." << endl;
+ delete[] pInToConvert;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if(accessTimes<0)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access times \"" << pInRes << "\" from acess information \"" << pToConvert << "\", negative number." << endl;
+ delete[] pInToConvert;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ accessInfo=new r_Access(*accessInterv, accessTimes);
+ vectAccessInfo.push_back(*accessInfo);
+ delete accessInfo;
+ delete accessInterv;
+
+ //skip COLON && free buffer
+ delete[] pToConvert;
+
+ if(pRes != (pEnd-1))
+ pRes++;
+ else
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access informations, end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with next item
+ pTemp=pRes;
+ pRes=strstr(pTemp, COLON);
+ }
+
+ if(vectAccessInfo.empty())
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding access informations, no access informations specified." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with borderTH
+ lenToConvert=pRes-pTemp;
+ pToConvert=new char[lenToConvert+1];
+ memcpy(pToConvert, pTemp, lenToConvert);
+ pToConvert[lenToConvert]='\0';
+
+ borderTH=strtol(pToConvert, (char**)NULL, DefaultBase);
+ if (!borderTH)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding border threshold \"" << pToConvert << "\"." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if (borderTH < 0)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding border threshold \"" << pToConvert << "\"." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //skip COLON && free buffer
+ delete[] pToConvert;
+ if(pRes != (pEnd-1))
+ pRes++;
+ else
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding interesting threshold, end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with interestTH
+ pTemp=pRes;
+ pRes=strstr(pTemp,COLON);
+ if(!pRes)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding interesting threshold." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //copy substring into buffer
+ lenToConvert=pRes-pTemp;
+ pToConvert=new char[lenToConvert+1];
+ memcpy(pToConvert, pTemp, lenToConvert);
+ pToConvert[lenToConvert]='\0';
+
+ interestTH=strtod(pToConvert, (char**)NULL);
+ if (!interestTH)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding interesting threshold \"" << pToConvert << "\"." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if (interestTH < 0.)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding interesting threshold \"" << pToConvert << "\", negative number." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ if (interestTH > 1.)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding interesting threshold \"" << pToConvert << "\", not in [0,1] interval." << endl;
+ delete[] pToConvert;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //skip COLON && free buffer
+ delete[] pToConvert;
+ if(pRes != (pEnd-1))
+ pRes++;
+ else
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding tile size, end of stream." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ //deal with tilesize
+ pTemp=pRes;
+ tileS=strtol(pTemp, (char**)NULL, DefaultBase);
+ if (!tileS)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding tile size \"" << pToConvert << "\", not a number." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+ if (tileS < 0.)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << encoded << "): Error decoding tile size \"" << pToConvert << "\", negative number." << endl;
+ throw r_Error(TILINGPARAMETERNOTCORRECT);
+ }
+
+ border_thr = borderTH;
+ stat_info = vectAccessInfo;
+ interesting_thr = interestTH;
+ dimension = tileD;
+ tile_size = tileS;
+}
+
+
+r_Stat_Tiling::r_Stat_Tiling(r_Dimension dim, const std::vector<r_Access>& stat_info2, r_Bytes ts, r_ULong border_threshold, r_Double interesting_threshold) throw (r_Error)
+ : r_Dimension_Tiling(dim, ts),
+ border_thr(border_threshold),
+ stat_info(stat_info2),
+ interesting_thr(interesting_threshold)
+{
+ RMDBGENTER(1, RMDebug::module_rasodmg, "r_Stat_Tiling", "Filtering accesses... ");
+ // Filter accesses all areas have the same dimension if successfull else exception
+ filter(stat_info);
+ RMDBGMIDDLE(1, RMDebug::module_rasodmg, "r_Stat_Tiling", "done\n");
+ std::vector<r_Access>::iterator areas_it = stat_info.begin();
+ // Count total accesses
+ r_ULong total_accesses = 0;
+
+
+
+ for (;areas_it != stat_info.end(); areas_it++)
+ {
+ if ((*areas_it).get_pattern().dimension() != dim)
+ {
+ RMInit::logOut << "r_Stat_Tiling::r_Stat_Tiling(" << dim << ", " << &stat_info
+ << ", " << ts << ", " << border_threshold << ", " << interesting_threshold
+ << ") dimension (" << dim << ") does not match dimension of access patterns ("
+ << (*areas_it).get_pattern().dimension() << ")" << endl;
+ throw r_Edim_mismatch(dim, (*areas_it).get_pattern().dimension());
+ }
+ total_accesses += (*areas_it).get_times();
+ }
+
+ RMDBGMIDDLE(1, RMDebug::module_rasodmg, "r_Stat_Tiling", "Defining interest areas... ");
+
+ // Mininum number of accesses for being interesting
+ r_ULong critical_accesses = (r_ULong)(interesting_thr*total_accesses);
+
+ iareas.clear();
+ for (areas_it = stat_info.begin(); areas_it != stat_info.end(); areas_it++)
+ {
+ if ((*areas_it).get_times() >= critical_accesses) // Threshold exceeded or equal
+ {
+ iareas.push_back(areas_it->get_pattern()); // count this area in
+ }
+ }
+
+ RMDBGEXIT(1, RMDebug::module_rasodmg, "r_Stat_Tiling", "Defining interest areas... done\n");
+}
+
+r_Stat_Tiling::~r_Stat_Tiling()
+{
+}
+
+r_Tiling* r_Stat_Tiling::clone() const
+{
+ r_Tiling* copy = new r_Stat_Tiling(dimension, stat_info, tile_size, border_thr, interesting_thr);
+ return copy;
+}
+
+void r_Stat_Tiling::print_status(std::ostream& os) const
+{
+ os << "r_Stat_Tiling[ ";
+ r_Dimension_Tiling::print_status(os);
+ os << " border threshold = " << border_thr << ", interesting threshold = " << interesting_thr << " ]";
+}
+
+const std::vector<r_Minterval>&
+r_Stat_Tiling::get_interesting_areas() const
+ {
+ return iareas;
+ }
+
+r_Tiling_Scheme
+r_Stat_Tiling::get_tiling_scheme() const
+ {
+ return r_StatisticalTiling;
+ }
+
+r_Area
+r_Stat_Tiling::get_border_threshold() const
+{
+ return border_thr;
+}
+
+r_Double
+r_Stat_Tiling::get_interesting_threshold() const
+{
+ return interesting_thr;
+}
+
+r_Access
+r_Stat_Tiling::merge(const std::vector<r_Access>& patterns) const
+{
+ // Create an interator for list of patterns
+ std::vector<r_Access>::const_iterator it = patterns.begin();
+
+ // The result (initialy updated to the first element of patterns)
+ r_Access result = (*it);
+ it++;
+
+ // For all patterns
+ for (;it != patterns.end(); it++)
+ {
+ result.merge_with(*it); // Merge them
+ }
+ return result; // Return the result
+}
+
+void r_Stat_Tiling::filter(std::vector<r_Access>& patterns) const throw (r_Error)
+{
+ // List to hold the result
+ std::vector<r_Access> result;
+
+ // List to hold the clusters
+ std::vector<r_Access> cluster;
+
+ // Iterators for pattern and cluster list
+ std::vector<r_Access>::iterator pattern_it = patterns.begin();
+ std::vector<r_Access>::iterator cluster_it;
+
+ // For all elements in pattern table
+ while (!patterns.empty())
+ {
+ // Clean cluster
+ cluster.clear();
+ // Cluster with first element of pattern list
+ cluster.push_back(patterns.back());
+ patterns.pop_back();
+
+ // For all elements in the cluster
+ for (cluster_it = cluster.begin(); cluster_it != cluster.end(); cluster_it++)
+ {
+ // For all remaining patterns
+ for (pattern_it = patterns.begin(); pattern_it != patterns.end(); pattern_it++)
+ {
+ // Pattern near an element from the cluster
+ if ((*cluster_it).is_near(*pattern_it, border_thr))
+ {
+ // Add pattern to the cluster
+ cluster.push_back(*pattern_it);
+ // Remove pattern from list
+ patterns.erase(pattern_it);
+ }
+ }
+ }
+ // Merge cluster and add to result
+ result.push_back(merge(cluster));
+ }
+ // Filtered table
+ patterns = result;
+}
+
+std::vector<r_Minterval>*
+r_Stat_Tiling::compute_tiles(const r_Minterval& domain, r_Bytes typelen) const throw (r_Error)
+{
+ r_Dimension num_dims = domain.dimension(); // Dimensionality of dom
+if (domain.dimension() != dimension)
+ {
+ RMInit::logOut << "r_Stat_Tiling::compute_tiles(" << domain << ", " << typelen << ") dimension (" << dimension << ") does not match dimension of object to tile (" << num_dims << ")" << endl;
+ throw r_Edim_mismatch(dimension, num_dims);
+ }
+if (typelen > tile_size)
+ {
+ RMInit::logOut << "r_Stat_Tiling::compute_tiles(" << domain << ", " << typelen << ") tile size (" << tile_size << ") is smaller than type length (" << typelen << ")" << endl;
+ throw r_Error(TILESIZETOOSMALL);
+ }
+#ifdef _VISUALIZE_2D_DECOMP_ // User wants a visual
+ static int count; // Number of decomps
+ ++count; // Update num decomps
+ // of the 2D decomp.
+ Visual_Tiling_2D* vis;
+ if (domain.dimension() == 2)
+ {
+ // Create an object for visualization
+ char fname[80];
+ sprintf(fname, "2D_decomp_stat_%d.ppm", count);
+ vis = new Visual_Tiling_2D(domain, fname);
+ }
+#endif
+
+ // *** Main algoritm ***
+
+ std::vector<r_Minterval>* result; // Holds the result
+
+ if (iareas.empty()) // No interest areas
+ {
+ // Perform regular tiling
+
+ RMDBGENTER(1, RMDebug::module_rasodmg, "r_Stat_Tiling", "Regular tiling...");
+
+ result = r_Size_Tiling::compute_tiles(domain, typelen);
+
+ RMDBGEXIT(1, RMDebug::module_rasodmg, "r_Stat_Tiling", "done\n");
+ }
+ else // We have interest areas
+ {
+ // Use interest areas for tiling the domain
+
+ RMDBGENTER(1, RMDebug::module_rasodmg, "r_Stat_Tiling", "Statistic tiling...\n");
+ r_Interest_Tiling* tiling=NULL;
+
+ try
+ {
+ tiling=new r_Interest_Tiling(dimension, iareas, get_tile_size(), r_Interest_Tiling::SUB_TILING);
+ result = tiling->compute_tiles(domain, typelen);
+ delete tiling;
+ }
+ catch(r_Error& err)
+ {
+ if(tiling)
+ delete tiling;
+ throw;
+ }
+
+ RMDBGEXIT(1, RMDebug::module_rasodmg, "r_Stat_Tiling", "done\n");
+ }
+
+ // *** End of the main algorithm
+
+#ifdef _VISUALIZE_2D_DECOMP_
+ if (domain.dimension() == 2)
+ {
+ vis->set_pen(0, 255, 255);
+
+ std::vector<r_Minterval>::iterator it(*result);
+ it.seek_begin();
+ for (; it.not_done(); it++)
+ (*vis) << (*it);
+
+ vis->set_pen(255, 255, 0);
+
+ std::vector<r_Minterval>& ia = (std::vector<r_Minterval>) iareas; // Cast away constness
+
+ std::vector<r_Minterval>::iterator it2(ia);
+ it2.seek_begin();
+ for (; it2.not_done(); it2++)
+ (*vis) << (*it2);
+
+ delete vis;
+ }
+#endif
+
+ // Return result
+
+ return result;
+}
+
+
+
+//***************************************************************************
+
+r_Access::r_Access() :
+ times(0)
+{
+}
+
+r_Access::r_Access(const r_Minterval& pattern, r_ULong accesses) :
+ interval(pattern), times(accesses)
+{
+}
+
+const r_Minterval& r_Access::get_pattern() const
+{
+ return interval;
+}
+
+void r_Access::set_pattern(const r_Minterval& pattern)
+{
+ interval = pattern;
+}
+
+r_ULong r_Access::get_times() const
+{
+ return times;
+}
+
+void r_Access::set_times(r_ULong accesses)
+{
+ times = accesses;
+}
+
+bool r_Access::is_near(const r_Access& other, r_ULong border_threshold) const throw (r_Error)
+{
+ const r_Minterval& a = this->interval;
+ const r_Minterval& b = other.interval;
+
+ r_Dimension num_dims = interval.dimension();
+ if (num_dims != b.dimension())
+ {
+ RMInit::logOut << "r_Access::is_near(" << other << ", " << border_threshold << ") parameter 1 does not match my dimension (" << num_dims << ")" << endl;
+ throw r_Edim_mismatch(num_dims, b.dimension());
+ }
+ bool the_same = true;
+
+ // For all dimensions
+ for (r_Dimension i = 0; i < num_dims; i++)
+ {
+ // Higher limit does not exceed border threshold
+ if (labs(a[i].high() - b[i].high()) > border_threshold)
+ {
+ the_same = false;
+ break;
+ }
+
+ // Lower limit does not exceed border threshold
+ if (labs(a[i].low() - b[i].low()) > border_threshold)
+ {
+ the_same = false;
+ break;
+ }
+ }
+
+ return the_same;
+}
+
+void r_Access::merge_with(const r_Access& other)
+{
+ interval.closure_with(other.interval);
+ times+= other.times;
+}
+
+void r_Access::print_status(std::ostream& os) const
+{
+ os << "{" << times <<"x: " << interval << "}";
+}
+
+std::ostream& operator<<(std::ostream& os, const r_Access& access)
+{
+ access.print_status(os);
+
+ return os;
+}
+
+bool r_Access::operator==(const r_Access& other) const
+{
+ return ((this->interval == other.interval) && (this->times == other.times));
+}
+
+bool r_Access::operator!=(const r_Access& other) const
+{
+ return !(*this == other);
+}
diff --git a/rasodmg/stattiling.hh b/rasodmg/stattiling.hh
new file mode 100644
index 0000000..415b919
--- /dev/null
+++ b/rasodmg/stattiling.hh
@@ -0,0 +1,210 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: stattiling.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Stat_Tiling r_Access
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_STATTILING_HH_
+#define _R_STATTILING_HH_
+
+// Include statements
+
+class r_Access;
+class r_Stat_Tiling;
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ This class represents an access pattern to a certain object.
+ {\tt r_Stat_Tiling} receives a list of this objects so that
+ an appropriate tiling can be defined.
+*/
+
+class r_Access
+{
+ public:
+
+ /// Class constructor
+ r_Access(const r_Minterval& pattern, r_ULong accesses = 1);
+ /**
+ It takes as parameter the interval and the number of times
+ that interval was accessed.
+ */
+
+ /// Gets the current interval (access pattern)
+ const r_Minterval& get_pattern() const;
+
+ /// Sets the current interval (access pattern)
+ void set_pattern(const r_Minterval& pattern);
+
+ /// Gets the number of times the pattern was accessed
+ r_ULong get_times() const;
+
+ /// Sets the number of times the pattern was accessed
+ void set_times(r_ULong accesses);
+
+ /// Checks if a certain access pattern is "close enough" of other
+ /// throws exception if the domains do not match
+ bool is_near(const r_Access& other, r_ULong border_threshold) const throw (r_Error);
+
+ /// Merge this access pattern with another
+ void merge_with(const r_Access& other);
+
+ /// Print object status
+ void print_status(std::ostream& os) const;
+
+ /// Operator equal
+ bool operator==(const r_Access& other) const;
+
+ /// Operator different
+ bool operator!=(const r_Access& other) const;
+
+ private:
+
+ /// The user can't use the default constructor
+ r_Access();
+
+ /// The actual stored pattern
+ r_Minterval interval;
+
+ /// The number of times it was accessed
+ r_ULong times;
+};
+
+//@ManMemo: Module: {\bf rasodmg}
+/**
+ Prints the status of a Access object to a stream
+*/
+extern std::ostream& operator<<(std::ostream& os, const r_Access& access);
+
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+ This class implements the "statistic tiling" algorithm.
+
+ Three parameters are passed in the constructor of the class,
+ the border threshold for considering two access patterns to be the
+ same, the interesting threshold which specifies the percentage of
+ accesses that must take place so that an areas is considered of interest
+ when performing tiling and also the tilesize.
+
+ A call to {\tt update_stat_information} should be made prior to performing
+ tiling so that the static information about the accesses to the object
+ can be updated and the tiling operation prepared.
+*/
+
+class r_Stat_Tiling : public r_Dimension_Tiling
+{
+ // ******************* PUBLIC SECTION *******************
+
+ public: // constants
+
+ /// Default threshold for two borders being considered the same
+ const static r_Area DEF_BORDER_THR;
+
+ /// Default threshold for considering an area interesting when tiling
+ const static r_Double DEF_INTERESTING_THR;
+
+ /// read everything from an encoded string
+ /// e.g. "2;[0:9,0:9],3;[100:109,0:9],2;2;0.3;100"
+ r_Stat_Tiling(const char* encoded) throw (r_Error);
+
+ /// Class constructor
+ r_Stat_Tiling(r_Dimension dim,
+ const std::vector<r_Access>& stat_info,
+ r_Bytes ts = RMInit::clientTileSize,
+ r_Area border_threshold = DEF_BORDER_THR,
+ r_Double interesting_threshold = DEF_INTERESTING_THR) throw (r_Error);
+ /**
+ This is the "Statistic Tiling" class constructor.
+ It takes as parameters the threshold for, when performing filtering,
+ considering two borders the same, and also, the threshold at which
+ an area is considered interesting and should be taken in account when
+ performing tiling. Finally, the tilesize is considered as a parameter.
+ stat_info inputs the statistic information into the class and
+ calculates the new interest areas that will be used to perform tiling
+ on the object.
+ An exception is thrown when the statistical data does not fit the dimension.
+ */
+
+ virtual ~r_Stat_Tiling();
+
+ /// Gets the statistical information
+ virtual const std::vector<r_Minterval>& get_interesting_areas() const;
+
+ /// Gets the threshold at which to intervals are considered the same
+ r_Area get_border_threshold() const;
+ /**
+ This method gets the number of points (pixels/cells) at which two
+ intervals are considered to be the same, in the access patterns.
+ */
+
+ /// Gets the threshold at which an area is considered to be interesting
+ r_Double get_interesting_threshold() const;
+ /**
+ This method gets the threshold at which an area is considered to be
+ interesting. All the areas that are accessed above the specified
+ threshold, will be considered interest areas when performing tiling.
+ */
+
+ virtual void print_status(std::ostream& os) const;
+
+ virtual std::vector<r_Minterval>* compute_tiles(const r_Minterval& obj_domain, r_Bytes cell_size) const throw (r_Error);
+
+ virtual r_Tiling* clone() const;
+
+ virtual r_Tiling_Scheme get_tiling_scheme() const;
+
+ static const char* description;
+
+ protected: // methods
+
+ /// Filters and access pattern table (list)
+ /// throws exception if dimensions of access patterns are not the same
+ void filter(std::vector<r_Access>& patterns) const throw (r_Error);
+
+ /// Merges a list of access patterns
+ r_Access merge(const std::vector<r_Access>& patterns) const;
+
+ /// The "interesting area" threshold
+ r_Double interesting_thr;
+
+ /// The "same border" threshold
+ r_Area border_thr;
+
+ /// Current interest areas
+ std::vector<r_Minterval> iareas;
+
+ /// Statistical data
+ std::vector<r_Access> stat_info;
+};
+
+#endif
diff --git a/rasodmg/storagelayout.cc b/rasodmg/storagelayout.cc
new file mode 100644
index 0000000..847759d
--- /dev/null
+++ b/rasodmg/storagelayout.cc
@@ -0,0 +1,182 @@
+/*
+* 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: storagelayout.cc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_StorageLayout, r_Domain_Storage_Layout
+ *
+ * COMMENTS:
+ * None
+ *
+*/
+
+// Because of NT port
+#include <string.h>
+#ifdef __VISUALC__
+#include <strstrea.h>
+#else
+#include <strstream>
+#endif
+#include <math.h>
+#include <vector>
+
+#include "rasodmg/storagelayout.hh"
+#include "rasodmg/iterator.hh"
+#include "rasodmg/tiling.hh"
+#include "rasodmg/alignedtiling.hh"
+#include "raslib/rmdebug.hh"
+#include "raslib/rminit.hh"
+#include "raslib/minterval.hh"
+#include "rasodmg/gmarray.hh"
+
+r_Storage_Layout::r_Storage_Layout(r_Data_Format init_format, const char* formatParams)
+ : til(0),
+ storage_format(init_format),
+ storage_params(0)
+{
+ til = new r_Size_Tiling();
+ if (formatParams != NULL)
+ storage_params = strdup(formatParams);
+}
+
+r_Storage_Layout::r_Storage_Layout(r_Tiling* ts, r_Data_Format init_format, const char* formatParams)
+ : til(ts),
+ storage_format(init_format),
+ storage_params(0)
+{
+ if (til == NULL)
+ til = new r_Size_Tiling();
+ if (formatParams != NULL)
+ storage_params = strdup(formatParams);
+}
+
+r_Storage_Layout::r_Storage_Layout(const r_Storage_Layout& sl)
+ : til(sl.get_tiling()->clone()),
+ storage_format(sl.get_storage_format()),
+ storage_params(0)
+{
+ if (sl.storage_params != NULL)
+ storage_params = strdup(sl.storage_params);
+}
+
+r_Storage_Layout*
+r_Storage_Layout::clone() const
+{
+ r_Storage_Layout* newSL = new r_Storage_Layout(til->clone(), storage_format, storage_params);
+ return newSL;
+}
+
+r_Storage_Layout::~r_Storage_Layout()
+{
+ if(til)
+ {
+ delete til;
+ til = NULL;
+ }
+ if (storage_params)
+ {
+ free(storage_params);
+ storage_params = NULL;
+ }
+}
+
+const r_Tiling*
+r_Storage_Layout::get_tiling() const
+{
+ return til;
+}
+
+r_Data_Format
+r_Storage_Layout::get_storage_format() const
+{
+ return storage_format;
+}
+
+const char*
+r_Storage_Layout::get_storage_format_params() const
+{
+ return storage_params;
+}
+
+r_Set< r_GMarray* >*
+r_Storage_Layout::decomposeMDD(const r_GMarray* mar) const throw (r_Error)
+{
+ r_Bytes cell_size = mar->get_type_length();
+ std::vector<r_Minterval>* tiles=NULL;
+ r_Set<r_GMarray*>* result=NULL;
+
+ if (!til->is_compatible(mar->spatial_domain(), cell_size))
+ {
+ RMInit::logOut << "r_Storage_Layout::decomposeMDD() gmarray is not compatible with tiling" << endl;
+ RMInit::logOut << "\tgmarray domain : " << mar->spatial_domain() << endl;
+ RMInit::logOut << "\tgmarray type size: " << mar->get_type_length() << endl;
+ RMInit::logOut << "\tstorage layout : " << *this << endl;
+ throw r_Error(STORAGERLAYOUTINCOMPATIBLEWITHGMARRAY);
+ }
+
+
+
+ try
+ {
+ tiles = til->compute_tiles(mar->spatial_domain(), cell_size);
+ }
+ catch(r_Error& err)
+ {
+ throw;
+ }
+
+ result = new r_Set<r_GMarray*>;
+
+ for (std::vector<r_Minterval>::iterator it = tiles->begin(); it != tiles->end(); it++)
+ result->insert_element(mar->intersect(*it));
+
+ delete tiles;
+ return result;
+}
+
+void
+r_Storage_Layout::print_status(std::ostream& os) const
+{
+ os << "r_Storage_Layout[ tiling = "<< *til << " storage format = " << storage_format << " storage parameters = ";
+ if (storage_params != NULL)
+ os << "upps, not here";
+ //os << storage_params;
+ else
+ os << "none defined";
+ os << " ]";
+}
+
+bool
+r_Storage_Layout::is_compatible(const r_Minterval& obj_domain, r_Bytes cellTypeSize) const
+{
+ return til->is_compatible(obj_domain, cellTypeSize);
+}
+
+std::ostream&
+operator<<(std::ostream& s, const r_Storage_Layout& sl)
+{
+ sl.print_status(s);
+ return s;
+}
+
diff --git a/rasodmg/storagelayout.hh b/rasodmg/storagelayout.hh
new file mode 100644
index 0000000..decb1a0
--- /dev/null
+++ b/rasodmg/storagelayout.hh
@@ -0,0 +1,132 @@
+/*
+* 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>.
+/
+/**
+ * INCLUDE: storagelayout.hh
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Storage_Layout, r_Domain_Storage_Layout
+ *
+ * COMMENTS:
+ * None
+*/
+
+#ifndef _R_STORAGELAYOUT_HH_
+#define _R_STORAGELAYOUT_HH_
+
+
+#include <iostream>
+using std::cout;
+
+#include "raslib/mddtypes.hh"
+#include "rasodmg/set.hh"
+
+// forward declarations
+class r_Storage_Layout;
+class r_GMarray;
+class ClientComm;
+class r_Tiling;
+class r_Minterval;
+
+//@ManMemo: Module: {\bf rasodmg}
+
+/*@Doc:
+
+ The {\tt r_Storage_Layout} class is used to express the storage options
+ for {\tt r_Marray} objects. This is the superclass of different storage
+ layout classes which may be used for different types of storage layout
+ schemes. It is also used directly by the rasdaman client for
+ default storage layout, i.e., for the storage layout for objects for
+ which absolutely none has been defined.
+
+ Notice: the tiling options are invalid if the rasdaman client is running
+ with the option notiling. In that case, no tiling is done,
+ independently of the storage layout chosen.
+ For the time being, compression does not work.
+*/
+
+class r_Storage_Layout
+{
+ public:
+
+ /// the dataformat is not used. please use the database methods for this purpose.
+ r_Storage_Layout(r_Data_Format init_format = r_Array, const char* formatParams = NULL);
+
+ /// the dataformat is not used. please use the database methods for this purpose.
+ r_Storage_Layout(r_Tiling* ts, r_Data_Format init_format = r_Array, const char* formatParams = NULL);
+
+ /// Copy constructor.
+ r_Storage_Layout(const r_Storage_Layout& sl);
+
+ ///
+ virtual r_Storage_Layout* clone() const;
+
+ /// virtual destructor
+ virtual ~r_Storage_Layout();
+
+ ///
+ const r_Tiling* get_tiling() const;
+
+ /// this does not do anything important. please use the database methods for this purpose.
+ r_Data_Format get_storage_format() const;
+
+ /// this does not do anything important. please use the database methods for this purpose.
+ const char* get_storage_format_params() const;
+
+ /// Function for decomposing large MDDs into a set of smaller tiles
+ virtual r_Set< r_GMarray* >* decomposeMDD(const r_GMarray* mar) const throw (r_Error);
+
+ /// writes the state of the object to the specified stream
+ void print_status(std::ostream& s = cout) const;
+
+ ///
+ virtual bool is_compatible(const r_Minterval& obj_domain, r_Bytes celltypesize) const;
+
+ protected:
+
+ friend class ClientComm;
+ friend class r_GMArray;
+
+ char* storage_params;
+
+ /// the dataformat is not used. please use the database methods for this purpose.
+ r_Data_Format storage_format;
+
+ /// Tiling scheme
+ r_Tiling* til;
+
+};
+
+//@ManMemo: Module: {\bf rasodmg }
+/**
+ Output stream operator for objects of type {\tt const} \Ref{r_Storage_Layout}.
+*/
+extern std::ostream& operator<<(std::ostream& s, const r_Storage_Layout& sl);
+
+#if (defined(__VISUALC__) && !defined(__EXECUTABLE__))
+ #define __EXECUTABLE__
+ #include "raslib/dlist.hh"
+ #undef __EXECUTABLE__
+#else
+ #include "raslib/dlist.hh"
+#endif
+#endif
diff --git a/rasodmg/storagelayout.icc b/rasodmg/storagelayout.icc
new file mode 100644
index 0000000..f31834d
--- /dev/null
+++ b/rasodmg/storagelayout.icc
@@ -0,0 +1,31 @@
+/*
+* 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>.
+/
+/**
+ * INLINE SOURCE: storagelayout.icc
+ *
+ * MODULE: rasodmg
+ * CLASS: r_Storage_Layout
+ *
+ * COMMENTS:
+ * None
+*/
diff --git a/rasodmg/test/Makefile b/rasodmg/test/Makefile
new file mode 100644
index 0000000..07385a2
--- /dev/null
+++ b/rasodmg/test/Makefile
@@ -0,0 +1,372 @@
+# -*-Makefile-*-
+#
+# 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>. # Top Level makefile. This points to the various modules that have to be build
+# and/or deployed
+#
+# MAKEFILE FOR:
+# test programs of module rasodmg
+#
+# COMMENTS:
+# - the rasql situated here is obsolete, see applications/rasql
+#
+##################################################################
+#
+# This is just an example Makefile for a test program.
+# The dependency of the test program on the lib of the
+# corresponding module is in the Makefile of the module.
+#
+
+######################### Definitions ############################
+
+# standard include with general options
+include $(RMANBASE)/Makefile.inc
+
+DEFCLIENTLIBS = $(RASODMG) $(CLIENTCOMM) $(COMPRESSION) $(RASLIB) $(CONVERSION)
+
+# use client specific flags
+CXXFLAGS := $(CLIENTCXXFLAGS)
+LDFLAGS := $(CLIENTLDFLAGS)
+
+# add communication flags
+CXXFLAGS += $(COMMCXXFLAGS)
+LDFLAGS += $(COMMLDFLAGS)
+
+# COMPDATE must be made more general at the final destination
+COMPDATE = `date +\"%d.%m.%Y %H:%M:%S\"`
+CXXFLAGS += -DCOMPDATE="\"$(COMPDATE)\""
+
+## a symbol for not writing too much when linking
+QL = $(SUPPORT_BASE)/lib/lib
+SUPPORTLIBS= $(QL)tiff.a $(QL)jpeg.a $(QL)png.a $(QL)crypto.a $(QL)z.a \
+ $(QL)mfhdf.a $(QL)df.a $(QL)ppm.a $(QL)pgm.a $(QL)pbm.a $(LIBAKINSIDE) \
+ $(LIBAKNET)
+
+# all test programs
+ALLTESTS = test_oqlquery test_collection test_set test_iterator \
+ test_marray deletecollection \
+ test_ref test_insert test_lookup test_query test_insert3 \
+ test_breakdown test_benchmark test_storage test_alignedtiling \
+ test_dirtiling test_interesttiling test_stattiling test_bmark_dir \
+ gen_pattern test_bmark_int test_bmark_stat test_bmark_dir1 \
+ test_bmark_int1 test_gmarray test_transaction test_fastscale \
+ test_polygon exporttif defdiff defconv system_update system_compare \
+ system_insert system_query
+
+SRCCXX= defconv.cc system_compare.cc test_bmark_dir1.cc test_dirtiling.cc test_lookup.cc \
+ test_stattiling.cc defdiff.cc system_insert.cc test_bmark_int.cc test_fastscale.cc \
+ test_marray.cc test_storage.cc deletecollection.cc system_query.cc test_bmark_int1.cc \
+ test_gmarray.cc test_oqlquery.cc test_transaction.cc gen_pattern.cc system_update.cc \
+ test_bmark_pet.cc test_insert.cc test_polygon.cc rasql.cc test_alignedtiling.cc \
+ test_bmark_stat.cc test_insert3.cc test_query.cc readln.cc test_benchmark.cc \
+ test_breakdown.cc test_interesttiling.cc test_ref.cc system_basic.cc test_bmark_dir.cc \
+ test_collection.cc test_iterator.cc test_set.cc
+
+OBJS = ${SRCCXX:%.cc=%.o}
+
+ifeq ($(OSTYPE),$(OSTYPE_SOLARIS))
+LDFLAGS+= -lsocket
+endif
+
+MISCCLEAN = $(OBJS) $(ALLTESTS)
+
+########################### Targets ##############################
+# all tests
+tests: $(ALLTESTS)
+
+# test target for class r_Collection
+# test target for class r_OQL_Query
+.PHONY : oqlquery
+oqlquery: test_module test_oqlquery
+
+# test target for class r_Collection
+.PHONY : collection
+collection: test_module test_collection
+
+# test target for class r_Set
+.PHONY : set
+set: test_module test_set
+
+# test target for class r_Iterator
+.PHONY : iterator
+iterator: test_module test_iterator
+
+# test target for class r_Marray
+.PHONY : marray
+marray: test_module test_marray
+
+# test target for class r_GMarray
+.PHONY : gmarray
+gmarray: test_module test_gmarray
+
+# test target for class r_Ref, r_Transaction
+.PHONY : ref
+ref: test_module test_ref
+
+# test target for ODMG conformant insertion of r_Marrays
+.PHONY : insert
+insert: test_module test_insert
+
+# test target for ODMG conformant lookup of r_Marrays
+.PHONY : lookup
+lookup: test_module test_lookup
+
+# test target for RasQL queries
+.PHONY : query
+query: test_module test_query
+
+# test target for test_insert3
+.PHONY : insert3
+insert3: test_module test_insert3
+
+# test target for deletecollection
+.PHONY : deletecoll
+insert3: test_module deletecollection
+
+# test target for simulation of communication breakdown
+.PHONY : breakdown
+breakdown: test_module test_breakdown
+
+# test target for RasQL benchmark
+.PHONY : benchmark
+benchmark: test_module test_benchmark
+
+# test target for storage layout
+storage: test_module test_storage test_alignedtiling test_dirtiling
+
+# test target for transactions
+transaction: test_module test_transaction
+
+.PHONY : test_module
+test_module:
+ cd $(RMANBASE)/rasodmg; $(MAKE)
+ cd $(RMANBASE)/raslib; $(MAKE)
+
+test_oqlquery: test_oqlquery.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_collection: test_collection.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_set: test_set.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_iterator: test_iterator.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_marray: test_marray.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_gmarray: test_gmarray.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_ref: test_ref.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_insert: test_insert.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_lookup: test_lookup.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_fastscale: test_fastscale.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+ifeq ($(OSTYPE),$(OSTYPE_LINUX))
+exporttif_static: exporttif.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o test_polygon -Xlinker -Bstatic $^ $(SUPPORTLIBS) -lstdc++
+endif
+
+ifeq ($(OSTYPE),$(OSTYPE_LINUX))
+exporttif: exporttif.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) -nodefaultlibs $(LDFLAGS) -o $@ -Xlinker -Bstatic $^ \
+ $(SUPPORTLIBS) -lstdc++ -Xlinker -Bdynamic -lm -lgcc -lc -lgcc
+endif
+
+
+ifeq ($(OSTYPE),$(OSTYPE_LINUX))
+test_polygon_static: test_polygon.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o test_polygon -Xlinker -Bstatic $^ \
+ $(SUPPORTLIBS) -lstdc++
+endif
+
+ifeq ($(OSTYPE),$(OSTYPE_LINUX))
+test_polygon: test_polygon.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) -nodefaultlibs $(LDFLAGS) -o $@ -Xlinker -Bstatic $^ \
+ $(SUPPORTLIBS) -lstdc++ -Xlinker -Bdynamic -lm -lgcc -lc -lgcc
+endif
+
+ifeq ($(OSTYPE),$(OSTYPE_SOLARIS))
+test_polygon: test_polygon.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ $(SUPPORTLIBS)
+endif
+
+test_query: test_query.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+ifeq ($(OSTYPE),$(OSTYPE_LINUX))
+test_query_static: test_query.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) -nodefaultlibs $(LDFLAGS) -o test_query $^ -Xlinker -Bstatic \
+ $(SUPPORTLIBS) -lstdc++ -Xlinker -Bdynamic -lgcc -lc -lgcc
+endif
+
+system_compare: system_basic.o system_compare.o $(DEFCLIENTLIBS)
+ifeq ($(OSTYPE),$(OSTYPE_SOLARIS))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lstdc++ -lm $(SUPPORTLIBS)
+else
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -Xlinker -Bstatic $(SUPPORTLIBS)
+endif
+
+system_update: system_update.o system_basic.o $(DEFCLIENTLIBS)
+ifeq ($(OSTYPE),$(OSTYPE_SOLARIS))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) -lNCSCNet -lNCSEcw -lNCSUtil -mt
+endif
+ifeq ($(OSTYPE),$(OSTYPE_LINUX))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -Xlinker -Bstatic $(SUPPORTLIBS)
+endif
+ifeq ($(OSTYPE),$(OSTYPE_OSF1))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ $(SUPPORTLIBS)
+endif
+
+system_insert: system_insert.o system_basic.o $(DEFCLIENTLIBS)
+ifeq ($(OSTYPE),$(OSTYPE_SOLARIS))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lstdc++ -lm $(SUPPORTLIBS)
+else
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ $(SUPPORTLIBS)
+endif
+
+system_query: system_query.o system_basic.o $(DEFCLIENTLIBS)
+ifeq ($(OSTYPE),$(OSTYPE_SOLARIS))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ $(SUPPORTLIBS) -lstdc++ -lm
+else
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -Xlinker -Bstatic $(SUPPORTLIBS)
+endif
+
+defdiff: defdiff.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -Xlinker -Bstatic -lstdc++ -lm $(SUPPORTLIBS)
+
+defconv: defconv.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -Xlinker -Bstatic -lstdc++ -lm $(SUPPORTLIBS)
+
+test_insert3: test_insert3.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+ifeq ($(OSTYPE),$(OSTYPE_LINUX))
+test_insert3_static: test_insert3.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) -nodefaultlibs $(LDFLAGS) -o test_insert3 $^ -Xlinker -Bstatic \
+ $(SUPPORTLIBS) -lstdc++ -Xlinker -Bdynamic -lgcc -lc -lgcc
+endif
+
+deletecollection: deletecollection.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_breakdown: test_breakdown.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_benchmark: test_benchmark.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_storage: test_storage.o $(DEFCLIENTLIBS) $(TOOLS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_alignedtiling: test_alignedtiling.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_dirtiling: test_dirtiling.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_interesttiling: test_interesttiling.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_stattiling: test_stattiling.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_bmark_dir: test_bmark_dir.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_bmark_dir1: test_bmark_dir1.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_bmark_int: test_bmark_int.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_bmark_int1: test_bmark_int1.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_bmark_pet: test_bmark_pet.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_bmark_stat: test_bmark_stat.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+gen_pattern: gen_pattern.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) $(TOOLS)
+
+test_transaction: test_transaction.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS)
+
+test_db2blob: test_db2blob.o $(DEFCLIENTLIBS)
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ -mt $^ -lm $(DB2LDFLAGS) $(SUPPORTLIBS)
+
+test_db2blob.cc: test_db2blob.sqC
+ db2 connect to sample
+ db2 prep $< bindfile OUTPUT $@
+ db2 bind test_db2blob.bnd
+ db2 connect reset
+
+.PHONY : raslib
+raslib:
+ cd $(RMANBASE)/raslib; $(MAKE)
+
+.PHONY : rasodmg
+rasodmg:
+ cd $(RMANBASE)/rasodmg; $(MAKE)
+
+.PHONY : clientcomm
+clientcomm:
+ cd $(RMANBASE)/clientcomm; $(MAKE)
+
+
+rasql: readln.o rasql.o
+ $(CXX) -o rasql $^ -L$(SUPPORT_BASE)/lib -lreadline -lcurses
+ ln -s -f $(RMANHOME)/rasodmg/test/rasql $(RMANHOME)/bin/rasql
+
+
+updatemap: updatemap.o updatemap_util.o updatemap_error.o $(DEFCLIENTLIBS)
+ifeq ($(OSTYPE),$(OSTYPE_SOLARIS))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -lm $(SUPPORTLIBS) -lNCSCNet -lNCSEcw -lNCSUtil -mt
+endif
+ifeq ($(OSTYPE),$(OSTYPE_LINUX))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -Xlinker -Bstatic $(SUPPORTLIBS)
+endif
+ifeq ($(OSTYPE),$(OSTYPE_OSF1))
+ $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ $(SUPPORTLIBS)
+endif
+
+PHONY: clean
+clean:
+ -rm $(MISCCLEAN)
+
+######################## Dependencies ############################
+
+# automatically created dependencies
+include Makefile.dep
+
diff --git a/rasodmg/test/Makefile.dep b/rasodmg/test/Makefile.dep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/rasodmg/test/Makefile.dep
diff --git a/rasodmg/test/cmov_16.ql b/rasodmg/test/cmov_16.ql
new file mode 100644
index 0000000..47e4178
--- /dev/null
+++ b/rasodmg/test/cmov_16.ql
@@ -0,0 +1,425 @@
+// This query tests different selectivities with moving query boxes
+// on comp_cubed with 16kB tiles ([0:24,0:24,0:24]). Each selectivity
+// is repeated 20 times with query boxes of the same shape and size
+// starting at different origins.
+
+// [0.5]: [39:83, 43:87, 117:143]
+SELECT img[39:83, 43:87, 117:143]
+FROM comp_cubed_16 AS img
+// [0.5]: [146:190, 116:160, 35:61]
+SELECT img[146:190, 116:160, 35:61]
+FROM comp_cubed_16 AS img
+// [0.5]: [17:61, 42:86, 15:41]
+SELECT img[17:61, 42:86, 15:41]
+FROM comp_cubed_16 AS img
+// [0.5]: [112:156, 154:198, 108:134]
+SELECT img[112:156, 154:198, 108:134]
+FROM comp_cubed_16 AS img
+// [0.5]: [138:182, 26:70, 48:74]
+SELECT img[138:182, 26:70, 48:74]
+FROM comp_cubed_16 AS img
+// [0.5]: [53:97, 94:138, 22:48]
+SELECT img[53:97, 94:138, 22:48]
+FROM comp_cubed_16 AS img
+// [0.5]: [190:234, 59:103, 17:43]
+SELECT img[190:234, 59:103, 17:43]
+FROM comp_cubed_16 AS img
+// [0.5]: [118:162, 147:191, 30:56]
+SELECT img[118:162, 147:191, 30:56]
+FROM comp_cubed_16 AS img
+// [0.5]: [210:254, 179:223, 18:44]
+SELECT img[210:254, 179:223, 18:44]
+FROM comp_cubed_16 AS img
+// [0.5]: [129:173, 76:120, 102:128]
+SELECT img[129:173, 76:120, 102:128]
+FROM comp_cubed_16 AS img
+// [0.5]: [199:243, 119:163, 59:85]
+SELECT img[199:243, 119:163, 59:85]
+FROM comp_cubed_16 AS img
+// [0.5]: [47:91, 52:96, 108:134]
+SELECT img[47:91, 52:96, 108:134]
+FROM comp_cubed_16 AS img
+// [0.5]: [87:131, 103:147, 11:37]
+SELECT img[87:131, 103:147, 11:37]
+FROM comp_cubed_16 AS img
+// [0.5]: [32:76, 81:125, 87:113]
+SELECT img[32:76, 81:125, 87:113]
+FROM comp_cubed_16 AS img
+// [0.5]: [14:58, 77:121, 0:26]
+SELECT img[14:58, 77:121, 0:26]
+FROM comp_cubed_16 AS img
+// [0.5]: [128:172, 145:189, 21:47]
+SELECT img[128:172, 145:189, 21:47]
+FROM comp_cubed_16 AS img
+// [0.5]: [185:229, 102:146, 60:86]
+SELECT img[185:229, 102:146, 60:86]
+FROM comp_cubed_16 AS img
+// [0.5]: [40:84, 39:83, 106:132]
+SELECT img[40:84, 39:83, 106:132]
+FROM comp_cubed_16 AS img
+// [0.5]: [37:81, 10:54, 51:77]
+SELECT img[37:81, 10:54, 51:77]
+FROM comp_cubed_16 AS img
+// [0.5]: [46:90, 21:65, 102:128]
+SELECT img[46:90, 21:65, 102:128]
+FROM comp_cubed_16 AS img
+// [1]: [199:254, 50:105, 11:44]
+SELECT img[199:254, 50:105, 11:44]
+FROM comp_cubed_16 AS img
+// [1]: [180:235, 51:106, 91:124]
+SELECT img[180:235, 51:106, 91:124]
+FROM comp_cubed_16 AS img
+// [1]: [199:254, 43:98, 113:146]
+SELECT img[199:254, 43:98, 113:146]
+FROM comp_cubed_16 AS img
+// [1]: [78:133, 40:95, 37:70]
+SELECT img[78:133, 40:95, 37:70]
+FROM comp_cubed_16 AS img
+// [1]: [11:66, 98:153, 19:52]
+SELECT img[11:66, 98:153, 19:52]
+FROM comp_cubed_16 AS img
+// [1]: [90:145, 74:129, 83:116]
+SELECT img[90:145, 74:129, 83:116]
+FROM comp_cubed_16 AS img
+// [1]: [82:137, 103:158, 1:34]
+SELECT img[82:137, 103:158, 1:34]
+FROM comp_cubed_16 AS img
+// [1]: [186:241, 191:246, 47:80]
+SELECT img[186:241, 191:246, 47:80]
+FROM comp_cubed_16 AS img
+// [1]: [143:198, 68:123, 77:110]
+SELECT img[143:198, 68:123, 77:110]
+FROM comp_cubed_16 AS img
+// [1]: [188:243, 23:78, 94:127]
+SELECT img[188:243, 23:78, 94:127]
+FROM comp_cubed_16 AS img
+// [1]: [71:126, 11:66, 75:108]
+SELECT img[71:126, 11:66, 75:108]
+FROM comp_cubed_16 AS img
+// [1]: [89:144, 109:164, 12:45]
+SELECT img[89:144, 109:164, 12:45]
+FROM comp_cubed_16 AS img
+// [1]: [47:102, 56:111, 14:47]
+SELECT img[47:102, 56:111, 14:47]
+FROM comp_cubed_16 AS img
+// [1]: [24:79, 190:245, 77:110]
+SELECT img[24:79, 190:245, 77:110]
+FROM comp_cubed_16 AS img
+// [1]: [14:69, 189:244, 0:33]
+SELECT img[14:69, 189:244, 0:33]
+FROM comp_cubed_16 AS img
+// [1]: [198:253, 167:222, 117:150]
+SELECT img[198:253, 167:222, 117:150]
+FROM comp_cubed_16 AS img
+// [1]: [125:180, 1:56, 113:146]
+SELECT img[125:180, 1:56, 113:146]
+FROM comp_cubed_16 AS img
+// [1]: [90:145, 126:181, 109:142]
+SELECT img[90:145, 126:181, 109:142]
+FROM comp_cubed_16 AS img
+// [1]: [154:209, 9:64, 47:80]
+SELECT img[154:209, 9:64, 47:80]
+FROM comp_cubed_16 AS img
+// [1]: [81:136, 1:56, 87:120]
+SELECT img[81:136, 1:56, 87:120]
+FROM comp_cubed_16 AS img
+// [2]: [116:185, 1:70, 77:119]
+SELECT img[116:185, 1:70, 77:119]
+FROM comp_cubed_16 AS img
+// [2]: [99:168, 87:156, 20:62]
+SELECT img[99:168, 87:156, 20:62]
+FROM comp_cubed_16 AS img
+// [2]: [81:150, 74:143, 35:77]
+SELECT img[81:150, 74:143, 35:77]
+FROM comp_cubed_16 AS img
+// [2]: [16:85, 100:169, 56:98]
+SELECT img[16:85, 100:169, 56:98]
+FROM comp_cubed_16 AS img
+// [2]: [180:249, 47:116, 92:134]
+SELECT img[180:249, 47:116, 92:134]
+FROM comp_cubed_16 AS img
+// [2]: [78:147, 57:126, 9:51]
+SELECT img[78:147, 57:126, 9:51]
+FROM comp_cubed_16 AS img
+// [2]: [160:229, 76:145, 39:81]
+SELECT img[160:229, 76:145, 39:81]
+FROM comp_cubed_16 AS img
+// [2]: [95:164, 29:98, 26:68]
+SELECT img[95:164, 29:98, 26:68]
+FROM comp_cubed_16 AS img
+// [2]: [143:212, 120:189, 35:77]
+SELECT img[143:212, 120:189, 35:77]
+FROM comp_cubed_16 AS img
+// [2]: [163:232, 116:185, 78:120]
+SELECT img[163:232, 116:185, 78:120]
+FROM comp_cubed_16 AS img
+// [2]: [116:185, 58:127, 69:111]
+SELECT img[116:185, 58:127, 69:111]
+FROM comp_cubed_16 AS img
+// [2]: [38:107, 169:238, 0:42]
+SELECT img[38:107, 169:238, 0:42]
+FROM comp_cubed_16 AS img
+// [2]: [87:156, 112:181, 41:83]
+SELECT img[87:156, 112:181, 41:83]
+FROM comp_cubed_16 AS img
+// [2]: [14:83, 118:187, 37:79]
+SELECT img[14:83, 118:187, 37:79]
+FROM comp_cubed_16 AS img
+// [2]: [24:93, 172:241, 27:69]
+SELECT img[24:93, 172:241, 27:69]
+FROM comp_cubed_16 AS img
+// [2]: [105:174, 14:83, 21:63]
+SELECT img[105:174, 14:83, 21:63]
+FROM comp_cubed_16 AS img
+// [2]: [54:123, 92:161, 0:42]
+SELECT img[54:123, 92:161, 0:42]
+FROM comp_cubed_16 AS img
+// [2]: [151:220, 160:229, 58:100]
+SELECT img[151:220, 160:229, 58:100]
+FROM comp_cubed_16 AS img
+// [2]: [73:142, 42:111, 73:115]
+SELECT img[73:142, 42:111, 73:115]
+FROM comp_cubed_16 AS img
+// [2]: [38:107, 181:250, 25:67]
+SELECT img[38:107, 181:250, 25:67]
+FROM comp_cubed_16 AS img
+// [5]: [82:176, 43:137, 32:88]
+SELECT img[82:176, 43:137, 32:88]
+FROM comp_cubed_16 AS img
+// [5]: [114:208, 6:100, 52:108]
+SELECT img[114:208, 6:100, 52:108]
+FROM comp_cubed_16 AS img
+// [5]: [116:210, 132:226, 29:85]
+SELECT img[116:210, 132:226, 29:85]
+FROM comp_cubed_16 AS img
+// [5]: [29:123, 69:163, 53:109]
+SELECT img[29:123, 69:163, 53:109]
+FROM comp_cubed_16 AS img
+// [5]: [85:179, 1:95, 72:128]
+SELECT img[85:179, 1:95, 72:128]
+FROM comp_cubed_16 AS img
+// [5]: [80:174, 121:215, 27:83]
+SELECT img[80:174, 121:215, 27:83]
+FROM comp_cubed_16 AS img
+// [5]: [142:236, 129:223, 46:102]
+SELECT img[142:236, 129:223, 46:102]
+FROM comp_cubed_16 AS img
+// [5]: [130:224, 156:250, 82:138]
+SELECT img[130:224, 156:250, 82:138]
+FROM comp_cubed_16 AS img
+// [5]: [27:121, 111:205, 45:101]
+SELECT img[27:121, 111:205, 45:101]
+FROM comp_cubed_16 AS img
+// [5]: [139:233, 122:216, 49:105]
+SELECT img[139:233, 122:216, 49:105]
+FROM comp_cubed_16 AS img
+// [5]: [12:106, 3:97, 84:140]
+SELECT img[12:106, 3:97, 84:140]
+FROM comp_cubed_16 AS img
+// [5]: [73:167, 70:164, 1:57]
+SELECT img[73:167, 70:164, 1:57]
+FROM comp_cubed_16 AS img
+// [5]: [160:254, 1:95, 80:136]
+SELECT img[160:254, 1:95, 80:136]
+FROM comp_cubed_16 AS img
+// [5]: [152:246, 54:148, 72:128]
+SELECT img[152:246, 54:148, 72:128]
+FROM comp_cubed_16 AS img
+// [5]: [25:119, 50:144, 55:111]
+SELECT img[25:119, 50:144, 55:111]
+FROM comp_cubed_16 AS img
+// [5]: [151:245, 34:128, 92:148]
+SELECT img[151:245, 34:128, 92:148]
+FROM comp_cubed_16 AS img
+// [5]: [28:122, 68:162, 76:132]
+SELECT img[28:122, 68:162, 76:132]
+FROM comp_cubed_16 AS img
+// [5]: [145:239, 98:192, 44:100]
+SELECT img[145:239, 98:192, 44:100]
+FROM comp_cubed_16 AS img
+// [5]: [73:167, 122:216, 2:58]
+SELECT img[73:167, 122:216, 2:58]
+FROM comp_cubed_16 AS img
+// [5]: [1:95, 107:201, 68:124]
+SELECT img[1:95, 107:201, 68:124]
+FROM comp_cubed_16 AS img
+// [10]: [102:220, 43:161, 75:146]
+SELECT img[102:220, 43:161, 75:146]
+FROM comp_cubed_16 AS img
+// [10]: [106:224, 36:154, 79:150]
+SELECT img[106:224, 36:154, 79:150]
+FROM comp_cubed_16 AS img
+// [10]: [95:213, 56:174, 69:140]
+SELECT img[95:213, 56:174, 69:140]
+FROM comp_cubed_16 AS img
+// [10]: [62:180, 126:244, 74:145]
+SELECT img[62:180, 126:244, 74:145]
+FROM comp_cubed_16 AS img
+// [10]: [93:211, 63:181, 46:117]
+SELECT img[93:211, 63:181, 46:117]
+FROM comp_cubed_16 AS img
+// [10]: [129:247, 74:192, 67:138]
+SELECT img[129:247, 74:192, 67:138]
+FROM comp_cubed_16 AS img
+// [10]: [44:162, 84:202, 75:146]
+SELECT img[44:162, 84:202, 75:146]
+FROM comp_cubed_16 AS img
+// [10]: [52:170, 107:225, 19:90]
+SELECT img[52:170, 107:225, 19:90]
+FROM comp_cubed_16 AS img
+// [10]: [89:207, 94:212, 9:80]
+SELECT img[89:207, 94:212, 9:80]
+FROM comp_cubed_16 AS img
+// [10]: [52:170, 120:238, 67:138]
+SELECT img[52:170, 120:238, 67:138]
+FROM comp_cubed_16 AS img
+// [10]: [98:216, 51:169, 42:113]
+SELECT img[98:216, 51:169, 42:113]
+FROM comp_cubed_16 AS img
+// [10]: [30:148, 109:227, 51:122]
+SELECT img[30:148, 109:227, 51:122]
+FROM comp_cubed_16 AS img
+// [10]: [130:248, 118:236, 30:101]
+SELECT img[130:248, 118:236, 30:101]
+FROM comp_cubed_16 AS img
+// [10]: [25:143, 25:143, 46:117]
+SELECT img[25:143, 25:143, 46:117]
+FROM comp_cubed_16 AS img
+// [10]: [86:204, 119:237, 12:83]
+SELECT img[86:204, 119:237, 12:83]
+FROM comp_cubed_16 AS img
+// [10]: [116:234, 18:136, 11:82]
+SELECT img[116:234, 18:136, 11:82]
+FROM comp_cubed_16 AS img
+// [10]: [61:179, 24:142, 68:139]
+SELECT img[61:179, 24:142, 68:139]
+FROM comp_cubed_16 AS img
+// [10]: [53:171, 14:132, 72:143]
+SELECT img[53:171, 14:132, 72:143]
+FROM comp_cubed_16 AS img
+// [10]: [49:167, 84:202, 64:135]
+SELECT img[49:167, 84:202, 64:135]
+FROM comp_cubed_16 AS img
+// [10]: [85:203, 80:198, 13:84]
+SELECT img[85:203, 80:198, 13:84]
+FROM comp_cubed_16 AS img
+// [20]: [97:246, 85:234, 54:143]
+SELECT img[97:246, 85:234, 54:143]
+FROM comp_cubed_16 AS img
+// [20]: [63:212, 18:167, 43:132]
+SELECT img[63:212, 18:167, 43:132]
+FROM comp_cubed_16 AS img
+// [20]: [99:248, 28:177, 58:147]
+SELECT img[99:248, 28:177, 58:147]
+FROM comp_cubed_16 AS img
+// [20]: [57:206, 16:165, 46:135]
+SELECT img[57:206, 16:165, 46:135]
+FROM comp_cubed_16 AS img
+// [20]: [83:232, 93:242, 36:125]
+SELECT img[83:232, 93:242, 36:125]
+FROM comp_cubed_16 AS img
+// [20]: [57:206, 31:180, 48:137]
+SELECT img[57:206, 31:180, 48:137]
+FROM comp_cubed_16 AS img
+// [20]: [86:235, 70:219, 32:121]
+SELECT img[86:235, 70:219, 32:121]
+FROM comp_cubed_16 AS img
+// [20]: [39:188, 49:198, 50:139]
+SELECT img[39:188, 49:198, 50:139]
+FROM comp_cubed_16 AS img
+// [20]: [62:211, 104:253, 29:118]
+SELECT img[62:211, 104:253, 29:118]
+FROM comp_cubed_16 AS img
+// [20]: [103:252, 44:193, 13:102]
+SELECT img[103:252, 44:193, 13:102]
+FROM comp_cubed_16 AS img
+// [20]: [48:197, 14:163, 2:91]
+SELECT img[48:197, 14:163, 2:91]
+FROM comp_cubed_16 AS img
+// [20]: [0:149, 79:228, 13:102]
+SELECT img[0:149, 79:228, 13:102]
+FROM comp_cubed_16 AS img
+// [20]: [6:155, 103:252, 35:124]
+SELECT img[6:155, 103:252, 35:124]
+FROM comp_cubed_16 AS img
+// [20]: [0:149, 91:240, 46:135]
+SELECT img[0:149, 91:240, 46:135]
+FROM comp_cubed_16 AS img
+// [20]: [23:172, 50:199, 42:131]
+SELECT img[23:172, 50:199, 42:131]
+FROM comp_cubed_16 AS img
+// [20]: [80:229, 33:182, 17:106]
+SELECT img[80:229, 33:182, 17:106]
+FROM comp_cubed_16 AS img
+// [20]: [38:187, 41:190, 1:90]
+SELECT img[38:187, 41:190, 1:90]
+FROM comp_cubed_16 AS img
+// [20]: [42:191, 17:166, 39:128]
+SELECT img[42:191, 17:166, 39:128]
+FROM comp_cubed_16 AS img
+// [20]: [98:247, 95:244, 58:147]
+SELECT img[98:247, 95:244, 58:147]
+FROM comp_cubed_16 AS img
+// [20]: [10:159, 51:200, 21:110]
+SELECT img[10:159, 51:200, 21:110]
+FROM comp_cubed_16 AS img
+// [50]: [8:210, 13:215, 9:130]
+SELECT img[8:210, 13:215, 9:130]
+FROM comp_cubed_16 AS img
+// [50]: [48:250, 45:247, 24:145]
+SELECT img[48:250, 45:247, 24:145]
+FROM comp_cubed_16 AS img
+// [50]: [29:231, 6:208, 23:144]
+SELECT img[29:231, 6:208, 23:144]
+FROM comp_cubed_16 AS img
+// [50]: [12:214, 44:246, 23:144]
+SELECT img[12:214, 44:246, 23:144]
+FROM comp_cubed_16 AS img
+// [50]: [11:213, 27:229, 7:128]
+SELECT img[11:213, 27:229, 7:128]
+FROM comp_cubed_16 AS img
+// [50]: [1:203, 2:204, 14:135]
+SELECT img[1:203, 2:204, 14:135]
+FROM comp_cubed_16 AS img
+// [50]: [22:224, 50:252, 10:131]
+SELECT img[22:224, 50:252, 10:131]
+FROM comp_cubed_16 AS img
+// [50]: [15:217, 35:237, 9:130]
+SELECT img[15:217, 35:237, 9:130]
+FROM comp_cubed_16 AS img
+// [50]: [4:206, 51:253, 28:149]
+SELECT img[4:206, 51:253, 28:149]
+FROM comp_cubed_16 AS img
+// [50]: [22:224, 20:222, 31:152]
+SELECT img[22:224, 20:222, 31:152]
+FROM comp_cubed_16 AS img
+// [50]: [16:218, 42:244, 27:148]
+SELECT img[16:218, 42:244, 27:148]
+FROM comp_cubed_16 AS img
+// [50]: [21:223, 32:234, 22:143]
+SELECT img[21:223, 32:234, 22:143]
+FROM comp_cubed_16 AS img
+// [50]: [37:239, 44:246, 29:150]
+SELECT img[37:239, 44:246, 29:150]
+FROM comp_cubed_16 AS img
+// [50]: [17:219, 49:251, 14:135]
+SELECT img[17:219, 49:251, 14:135]
+FROM comp_cubed_16 AS img
+// [50]: [49:251, 50:252, 3:124]
+SELECT img[49:251, 50:252, 3:124]
+FROM comp_cubed_16 AS img
+// [50]: [17:219, 15:217, 1:122]
+SELECT img[17:219, 15:217, 1:122]
+FROM comp_cubed_16 AS img
+// [50]: [21:223, 51:253, 13:134]
+SELECT img[21:223, 51:253, 13:134]
+FROM comp_cubed_16 AS img
+// [50]: [7:209, 47:249, 11:132]
+SELECT img[7:209, 47:249, 11:132]
+FROM comp_cubed_16 AS img
+// [50]: [4:206, 22:224, 4:125]
+SELECT img[4:206, 22:224, 4:125]
+FROM comp_cubed_16 AS img
+// [50]: [16:218, 51:253, 21:142]
+SELECT img[16:218, 51:253, 21:142]
+FROM comp_cubed_16 AS img
diff --git a/rasodmg/test/cmov_32.ql b/rasodmg/test/cmov_32.ql
new file mode 100644
index 0000000..c6b31fe
--- /dev/null
+++ b/rasodmg/test/cmov_32.ql
@@ -0,0 +1,425 @@
+// This query tests different selectivities with moving query boxes
+// on comp_cubed with 32kB tiles ([0:31,0:31,0:31]). Each selectivity
+// is repeated 20 times with query boxes of the same shape and size
+// starting at different origins.
+
+// [0.5]: [46:90, 176:220, 60:86]
+SELECT img[46:90, 176:220, 60:86]
+FROM comp_cubed AS img
+// [0.5]: [143:187, 175:219, 106:132]
+SELECT img[143:187, 175:219, 106:132]
+FROM comp_cubed AS img
+// [0.5]: [169:213, 75:119, 66:92]
+SELECT img[169:213, 75:119, 66:92]
+FROM comp_cubed AS img
+// [0.5]: [90:134, 178:222, 48:74]
+SELECT img[90:134, 178:222, 48:74]
+FROM comp_cubed AS img
+// [0.5]: [76:120, 136:180, 31:57]
+SELECT img[76:120, 136:180, 31:57]
+FROM comp_cubed AS img
+// [0.5]: [7:51, 150:194, 89:115]
+SELECT img[7:51, 150:194, 89:115]
+FROM comp_cubed AS img
+// [0.5]: [133:177, 113:157, 0:26]
+SELECT img[133:177, 113:157, 0:26]
+FROM comp_cubed AS img
+// [0.5]: [114:158, 125:169, 108:134]
+SELECT img[114:158, 125:169, 108:134]
+FROM comp_cubed AS img
+// [0.5]: [210:254, 12:56, 56:82]
+SELECT img[210:254, 12:56, 56:82]
+FROM comp_cubed AS img
+// [0.5]: [176:220, 171:215, 83:109]
+SELECT img[176:220, 171:215, 83:109]
+FROM comp_cubed AS img
+// [0.5]: [102:146, 50:94, 34:60]
+SELECT img[102:146, 50:94, 34:60]
+FROM comp_cubed AS img
+// [0.5]: [134:178, 96:140, 97:123]
+SELECT img[134:178, 96:140, 97:123]
+FROM comp_cubed AS img
+// [0.5]: [200:244, 43:87, 123:149]
+SELECT img[200:244, 43:87, 123:149]
+FROM comp_cubed AS img
+// [0.5]: [155:199, 127:171, 48:74]
+SELECT img[155:199, 127:171, 48:74]
+FROM comp_cubed AS img
+// [0.5]: [111:155, 80:124, 11:37]
+SELECT img[111:155, 80:124, 11:37]
+FROM comp_cubed AS img
+// [0.5]: [164:208, 2:46, 64:90]
+SELECT img[164:208, 2:46, 64:90]
+FROM comp_cubed AS img
+// [0.5]: [137:181, 102:146, 17:43]
+SELECT img[137:181, 102:146, 17:43]
+FROM comp_cubed AS img
+// [0.5]: [100:144, 149:193, 121:147]
+SELECT img[100:144, 149:193, 121:147]
+FROM comp_cubed AS img
+// [0.5]: [186:230, 38:82, 108:134]
+SELECT img[186:230, 38:82, 108:134]
+FROM comp_cubed AS img
+// [0.5]: [48:92, 53:97, 14:40]
+SELECT img[48:92, 53:97, 14:40]
+FROM comp_cubed AS img
+// [1]: [64:119, 65:120, 57:90]
+SELECT img[64:119, 65:120, 57:90]
+FROM comp_cubed AS img
+// [1]: [13:68, 121:176, 20:53]
+SELECT img[13:68, 121:176, 20:53]
+FROM comp_cubed AS img
+// [1]: [3:58, 115:170, 59:92]
+SELECT img[3:58, 115:170, 59:92]
+FROM comp_cubed AS img
+// [1]: [174:229, 82:137, 93:126]
+SELECT img[174:229, 82:137, 93:126]
+FROM comp_cubed AS img
+// [1]: [40:95, 143:198, 43:76]
+SELECT img[40:95, 143:198, 43:76]
+FROM comp_cubed AS img
+// [1]: [126:181, 160:215, 86:119]
+SELECT img[126:181, 160:215, 86:119]
+FROM comp_cubed AS img
+// [1]: [20:75, 44:99, 89:122]
+SELECT img[20:75, 44:99, 89:122]
+FROM comp_cubed AS img
+// [1]: [15:70, 92:147, 23:56]
+SELECT img[15:70, 92:147, 23:56]
+FROM comp_cubed AS img
+// [1]: [122:177, 62:117, 75:108]
+SELECT img[122:177, 62:117, 75:108]
+FROM comp_cubed AS img
+// [1]: [183:238, 174:229, 70:103]
+SELECT img[183:238, 174:229, 70:103]
+FROM comp_cubed AS img
+// [1]: [13:68, 82:137, 97:130]
+SELECT img[13:68, 82:137, 97:130]
+FROM comp_cubed AS img
+// [1]: [174:229, 107:162, 91:124]
+SELECT img[174:229, 107:162, 91:124]
+FROM comp_cubed AS img
+// [1]: [79:134, 83:138, 88:121]
+SELECT img[79:134, 83:138, 88:121]
+FROM comp_cubed AS img
+// [1]: [3:58, 62:117, 39:72]
+SELECT img[3:58, 62:117, 39:72]
+FROM comp_cubed AS img
+// [1]: [96:151, 25:80, 93:126]
+SELECT img[96:151, 25:80, 93:126]
+FROM comp_cubed AS img
+// [1]: [124:179, 183:238, 21:54]
+SELECT img[124:179, 183:238, 21:54]
+FROM comp_cubed AS img
+// [1]: [106:161, 111:166, 89:122]
+SELECT img[106:161, 111:166, 89:122]
+FROM comp_cubed AS img
+// [1]: [66:121, 103:158, 74:107]
+SELECT img[66:121, 103:158, 74:107]
+FROM comp_cubed AS img
+// [1]: [180:235, 131:186, 80:113]
+SELECT img[180:235, 131:186, 80:113]
+FROM comp_cubed AS img
+// [1]: [4:59, 132:187, 59:92]
+SELECT img[4:59, 132:187, 59:92]
+FROM comp_cubed AS img
+// [2]: [69:138, 184:253, 75:117]
+SELECT img[69:138, 184:253, 75:117]
+FROM comp_cubed AS img
+// [2]: [58:127, 168:237, 87:129]
+SELECT img[58:127, 168:237, 87:129]
+FROM comp_cubed AS img
+// [2]: [162:231, 145:214, 58:100]
+SELECT img[162:231, 145:214, 58:100]
+FROM comp_cubed AS img
+// [2]: [129:198, 122:191, 7:49]
+SELECT img[129:198, 122:191, 7:49]
+FROM comp_cubed AS img
+// [2]: [86:155, 170:239, 54:96]
+SELECT img[86:155, 170:239, 54:96]
+FROM comp_cubed AS img
+// [2]: [0:69, 98:167, 70:112]
+SELECT img[0:69, 98:167, 70:112]
+FROM comp_cubed AS img
+// [2]: [41:110, 33:102, 58:100]
+SELECT img[41:110, 33:102, 58:100]
+FROM comp_cubed AS img
+// [2]: [37:106, 24:93, 65:107]
+SELECT img[37:106, 24:93, 65:107]
+FROM comp_cubed AS img
+// [2]: [39:108, 114:183, 26:68]
+SELECT img[39:108, 114:183, 26:68]
+FROM comp_cubed AS img
+// [2]: [166:235, 9:78, 38:80]
+SELECT img[166:235, 9:78, 38:80]
+FROM comp_cubed AS img
+// [2]: [147:216, 174:243, 45:87]
+SELECT img[147:216, 174:243, 45:87]
+FROM comp_cubed AS img
+// [2]: [121:190, 69:138, 58:100]
+SELECT img[121:190, 69:138, 58:100]
+FROM comp_cubed AS img
+// [2]: [87:156, 78:147, 73:115]
+SELECT img[87:156, 78:147, 73:115]
+FROM comp_cubed AS img
+// [2]: [31:100, 109:178, 75:117]
+SELECT img[31:100, 109:178, 75:117]
+FROM comp_cubed AS img
+// [2]: [54:123, 155:224, 26:68]
+SELECT img[54:123, 155:224, 26:68]
+FROM comp_cubed AS img
+// [2]: [150:219, 139:208, 25:67]
+SELECT img[150:219, 139:208, 25:67]
+FROM comp_cubed AS img
+// [2]: [65:134, 119:188, 87:129]
+SELECT img[65:134, 119:188, 87:129]
+FROM comp_cubed AS img
+// [2]: [159:228, 45:114, 47:89]
+SELECT img[159:228, 45:114, 47:89]
+FROM comp_cubed AS img
+// [2]: [77:146, 60:129, 87:129]
+SELECT img[77:146, 60:129, 87:129]
+FROM comp_cubed AS img
+// [2]: [169:238, 135:204, 4:46]
+SELECT img[169:238, 135:204, 4:46]
+FROM comp_cubed AS img
+// [5]: [24:118, 61:155, 77:133]
+SELECT img[24:118, 61:155, 77:133]
+FROM comp_cubed AS img
+// [5]: [137:231, 119:213, 11:67]
+SELECT img[137:231, 119:213, 11:67]
+FROM comp_cubed AS img
+// [5]: [140:234, 131:225, 56:112]
+SELECT img[140:234, 131:225, 56:112]
+FROM comp_cubed AS img
+// [5]: [154:248, 6:100, 54:110]
+SELECT img[154:248, 6:100, 54:110]
+FROM comp_cubed AS img
+// [5]: [146:240, 62:156, 60:116]
+SELECT img[146:240, 62:156, 60:116]
+FROM comp_cubed AS img
+// [5]: [78:172, 21:115, 3:59]
+SELECT img[78:172, 21:115, 3:59]
+FROM comp_cubed AS img
+// [5]: [80:174, 33:127, 84:140]
+SELECT img[80:174, 33:127, 84:140]
+FROM comp_cubed AS img
+// [5]: [138:232, 95:189, 52:108]
+SELECT img[138:232, 95:189, 52:108]
+FROM comp_cubed AS img
+// [5]: [60:154, 136:230, 70:126]
+SELECT img[60:154, 136:230, 70:126]
+FROM comp_cubed AS img
+// [5]: [79:173, 149:243, 65:121]
+SELECT img[79:173, 149:243, 65:121]
+FROM comp_cubed AS img
+// [5]: [13:107, 53:147, 57:113]
+SELECT img[13:107, 53:147, 57:113]
+FROM comp_cubed AS img
+// [5]: [13:107, 66:160, 44:100]
+SELECT img[13:107, 66:160, 44:100]
+FROM comp_cubed AS img
+// [5]: [137:231, 47:141, 38:94]
+SELECT img[137:231, 47:141, 38:94]
+FROM comp_cubed AS img
+// [5]: [11:105, 84:178, 42:98]
+SELECT img[11:105, 84:178, 42:98]
+FROM comp_cubed AS img
+// [5]: [19:113, 31:125, 51:107]
+SELECT img[19:113, 31:125, 51:107]
+FROM comp_cubed AS img
+// [5]: [27:121, 17:111, 29:85]
+SELECT img[27:121, 17:111, 29:85]
+FROM comp_cubed AS img
+// [5]: [142:236, 76:170, 94:150]
+SELECT img[142:236, 76:170, 94:150]
+FROM comp_cubed AS img
+// [5]: [153:247, 71:165, 83:139]
+SELECT img[153:247, 71:165, 83:139]
+FROM comp_cubed AS img
+// [5]: [12:106, 108:202, 79:135]
+SELECT img[12:106, 108:202, 79:135]
+FROM comp_cubed AS img
+// [5]: [146:240, 26:120, 59:115]
+SELECT img[146:240, 26:120, 59:115]
+FROM comp_cubed AS img
+// 1[0]: [3:121, 62:180, 39:110]
+SELECT img[3:121, 62:180, 39:110]
+FROM comp_cubed AS img
+// 1[0]: [11:129, 26:144, 19:90]
+SELECT img[11:129, 26:144, 19:90]
+FROM comp_cubed AS img
+// 1[0]: [49:167, 76:194, 77:148]
+SELECT img[49:167, 76:194, 77:148]
+FROM comp_cubed AS img
+// [10]: [55:173, 86:204, 21:92]
+SELECT img[55:173, 86:204, 21:92]
+FROM comp_cubed AS img
+// [10]: [110:228, 98:216, 80:151]
+SELECT img[110:228, 98:216, 80:151]
+FROM comp_cubed AS img
+// [10]: [123:241, 28:146, 59:130]
+SELECT img[123:241, 28:146, 59:130]
+FROM comp_cubed AS img
+// [10]: [89:207, 90:208, 34:105]
+SELECT img[89:207, 90:208, 34:105]
+FROM comp_cubed AS img
+// [10]: [111:229, 51:169, 5:76]
+SELECT img[111:229, 51:169, 5:76]
+FROM comp_cubed AS img
+// [10]: [15:133, 74:192, 12:83]
+SELECT img[15:133, 74:192, 12:83]
+FROM comp_cubed AS img
+// [10]: [103:221, 94:212, 74:145]
+SELECT img[103:221, 94:212, 74:145]
+FROM comp_cubed AS img
+// [10]: [107:225, 111:229, 16:87]
+SELECT img[107:225, 111:229, 16:87]
+FROM comp_cubed AS img
+// [10]: [14:132, 80:198, 58:129]
+SELECT img[14:132, 80:198, 58:129]
+FROM comp_cubed AS img
+// [10]: [2:120, 64:182, 25:96]
+SELECT img[2:120, 64:182, 25:96]
+FROM comp_cubed AS img
+// [10]: [74:192, 130:248, 3:74]
+SELECT img[74:192, 130:248, 3:74]
+FROM comp_cubed AS img
+// [10]: [96:214, 61:179, 14:85]
+SELECT img[96:214, 61:179, 14:85]
+FROM comp_cubed AS img
+// [10]: [73:191, 93:211, 6:77]
+SELECT img[73:191, 93:211, 6:77]
+FROM comp_cubed AS img
+// [10]: [55:173, 12:130, 54:125]
+SELECT img[55:173, 12:130, 54:125]
+FROM comp_cubed AS img
+// [10]: [1:119, 123:241, 51:122]
+SELECT img[1:119, 123:241, 51:122]
+FROM comp_cubed AS img
+// [10]: [117:235, 101:219, 55:126]
+SELECT img[117:235, 101:219, 55:126]
+FROM comp_cubed AS img
+// [10]: [24:142, 26:144, 33:104]
+SELECT img[24:142, 26:144, 33:104]
+FROM comp_cubed AS img
+// [20]: [36:185, 0:149, 39:128]
+SELECT img[36:185, 0:149, 39:128]
+FROM comp_cubed AS img
+// [20]: [85:234, 31:180, 54:143]
+SELECT img[85:234, 31:180, 54:143]
+FROM comp_cubed AS img
+// [20]: [55:204, 78:227, 20:109]
+SELECT img[55:204, 78:227, 20:109]
+FROM comp_cubed AS img
+// [20]: [28:177, 98:247, 26:115]
+SELECT img[28:177, 98:247, 26:115]
+FROM comp_cubed AS img
+// [20]: [53:202, 14:163, 15:104]
+SELECT img[53:202, 14:163, 15:104]
+FROM comp_cubed AS img
+// [20]: [84:233, 59:208, 28:117]
+SELECT img[84:233, 59:208, 28:117]
+FROM comp_cubed AS img
+// [20]: [24:173, 81:230, 21:110]
+SELECT img[24:173, 81:230, 21:110]
+FROM comp_cubed AS img
+// [20]: [70:219, 103:252, 59:148]
+SELECT img[70:219, 103:252, 59:148]
+FROM comp_cubed AS img
+// [20]: [75:224, 32:181, 36:125]
+SELECT img[75:224, 32:181, 36:125]
+FROM comp_cubed AS img
+// [20]: [80:229, 65:214, 22:111]
+SELECT img[80:229, 65:214, 22:111]
+FROM comp_cubed AS img
+// [20]: [5:154, 34:183, 20:109]
+SELECT img[5:154, 34:183, 20:109]
+FROM comp_cubed AS img
+// [20]: [16:165, 72:221, 57:146]
+SELECT img[16:165, 72:221, 57:146]
+FROM comp_cubed AS img
+// [20]: [90:239, 27:176, 55:144]
+SELECT img[90:239, 27:176, 55:144]
+FROM comp_cubed AS img
+// [20]: [81:230, 63:212, 61:150]
+SELECT img[81:230, 63:212, 61:150]
+FROM comp_cubed AS img
+// [20]: [87:236, 79:228, 61:150]
+SELECT img[87:236, 79:228, 61:150]
+FROM comp_cubed AS img
+// [20]: [100:249, 33:182, 35:124]
+SELECT img[100:249, 33:182, 35:124]
+FROM comp_cubed AS img
+// [20]: [14:163, 91:240, 38:127]
+SELECT img[14:163, 91:240, 38:127]
+FROM comp_cubed AS img
+// [20]: [60:209, 95:244, 11:100]
+SELECT img[60:209, 95:244, 11:100]
+FROM comp_cubed AS img
+// [20]: [99:248, 4:153, 29:118]
+SELECT img[99:248, 4:153, 29:118]
+FROM comp_cubed AS img
+// [20]: [10:159, 64:213, 32:121]
+SELECT img[10:159, 64:213, 32:121]
+FROM comp_cubed AS img
+// [50]: [8:210, 0:202, 1:122]
+SELECT img[8:210, 0:202, 1:122]
+FROM comp_cubed AS img
+// [50]: [17:219, 21:223, 6:127]
+SELECT img[17:219, 21:223, 6:127]
+FROM comp_cubed AS img
+// [50]: [49:251, 0:202, 4:125]
+SELECT img[49:251, 0:202, 4:125]
+FROM comp_cubed AS img
+// [50]: [11:213, 37:239, 15:136]
+SELECT img[11:213, 37:239, 15:136]
+FROM comp_cubed AS img
+// [50]: [29:231, 36:238, 18:139]
+SELECT img[29:231, 36:238, 18:139]
+FROM comp_cubed AS img
+// [50]: [38:240, 21:223, 2:123]
+SELECT img[38:240, 21:223, 2:123]
+FROM comp_cubed AS img
+// [50]: [26:228, 4:206, 9:130]
+SELECT img[26:228, 4:206, 9:130]
+FROM comp_cubed AS img
+// [50]: [1:203, 41:243, 21:142]
+SELECT img[1:203, 41:243, 21:142]
+FROM comp_cubed AS img
+// [50]: [39:241, 37:239, 10:131]
+SELECT img[39:241, 37:239, 10:131]
+FROM comp_cubed AS img
+// [50]: [6:208, 49:251, 2:123]
+SELECT img[6:208, 49:251, 2:123]
+FROM comp_cubed AS img
+// [50]: [2:204, 51:253, 8:129]
+SELECT img[2:204, 51:253, 8:129]
+FROM comp_cubed AS img
+// [50]: [23:225, 51:253, 9:130]
+SELECT img[23:225, 51:253, 9:130]
+FROM comp_cubed AS img
+// [50]: [32:234, 43:245, 10:131]
+SELECT img[32:234, 43:245, 10:131]
+FROM comp_cubed AS img
+// [50]: [33:235, 9:211, 31:152]
+SELECT img[33:235, 9:211, 31:152]
+FROM comp_cubed AS img
+// [50]: [28:230, 36:238, 4:125]
+SELECT img[28:230, 36:238, 4:125]
+FROM comp_cubed AS img
+// [50]: [25:227, 40:242, 3:124]
+SELECT img[25:227, 40:242, 3:124]
+FROM comp_cubed AS img
+// [50]: [33:235, 28:230, 25:146]
+SELECT img[33:235, 28:230, 25:146]
+FROM comp_cubed AS img
+// [50]: [42:244, 34:236, 1:122]
+SELECT img[42:244, 34:236, 1:122]
+FROM comp_cubed AS img
+// [50]: [34:236, 47:249, 6:127]
+SELECT img[34:236, 47:249, 6:127]
+FROM comp_cubed AS img
+// [50]: [35:237, 22:224, 31:152]
+SELECT img[35:237, 22:224, 31:152]
+FROM comp_cubed AS img
diff --git a/rasodmg/test/cmov_64.ql b/rasodmg/test/cmov_64.ql
new file mode 100644
index 0000000..4cb19ff
--- /dev/null
+++ b/rasodmg/test/cmov_64.ql
@@ -0,0 +1,425 @@
+// This query tests different selectivities with moving query boxes
+// on comp_cubed with 64kB tiles ([0:39,0:39,0:39]). Each selectivity
+// is repeated 20 times with query boxes of the same shape and size
+// starting at different origins.
+
+// [0.5]: [205:249, 154:198, 39:65]
+SELECT img[205:249, 154:198, 39:65]
+FROM comp_cubed_64 AS img
+// [0.5]: [125:169, 124:168, 15:41]
+SELECT img[125:169, 124:168, 15:41]
+FROM comp_cubed_64 AS img
+// [0.5]: [197:241, 71:115, 82:108]
+SELECT img[197:241, 71:115, 82:108]
+FROM comp_cubed_64 AS img
+// [0.5]: [53:97, 192:236, 122:148]
+SELECT img[53:97, 192:236, 122:148]
+FROM comp_cubed_64 AS img
+// [0.5]: [140:184, 93:137, 121:147]
+SELECT img[140:184, 93:137, 121:147]
+FROM comp_cubed_64 AS img
+// [0.5]: [154:198, 82:126, 120:146]
+SELECT img[154:198, 82:126, 120:146]
+FROM comp_cubed_64 AS img
+// [0.5]: [209:253, 51:95, 47:73]
+SELECT img[209:253, 51:95, 47:73]
+FROM comp_cubed_64 AS img
+// [0.5]: [57:101, 159:203, 113:139]
+SELECT img[57:101, 159:203, 113:139]
+FROM comp_cubed_64 AS img
+// [0.5]: [98:142, 166:210, 12:38]
+SELECT img[98:142, 166:210, 12:38]
+FROM comp_cubed_64 AS img
+// [0.5]: [194:238, 88:132, 52:78]
+SELECT img[194:238, 88:132, 52:78]
+FROM comp_cubed_64 AS img
+// [0.5]: [162:206, 101:145, 53:79]
+SELECT img[162:206, 101:145, 53:79]
+FROM comp_cubed_64 AS img
+// [0.5]: [166:210, 60:104, 126:152]
+SELECT img[166:210, 60:104, 126:152]
+FROM comp_cubed_64 AS img
+// [0.5]: [127:171, 157:201, 92:118]
+SELECT img[127:171, 157:201, 92:118]
+FROM comp_cubed_64 AS img
+// [0.5]: [46:90, 94:138, 53:79]
+SELECT img[46:90, 94:138, 53:79]
+FROM comp_cubed_64 AS img
+// [0.5]: [19:63, 42:86, 17:43]
+SELECT img[19:63, 42:86, 17:43]
+FROM comp_cubed_64 AS img
+// [0.5]: [182:226, 0:44, 97:123]
+SELECT img[182:226, 0:44, 97:123]
+FROM comp_cubed_64 AS img
+// [0.5]: [139:183, 98:142, 47:73]
+SELECT img[139:183, 98:142, 47:73]
+FROM comp_cubed_64 AS img
+// [0.5]: [106:150, 182:226, 11:37]
+SELECT img[106:150, 182:226, 11:37]
+FROM comp_cubed_64 AS img
+// [0.5]: [193:237, 200:244, 23:49]
+SELECT img[193:237, 200:244, 23:49]
+FROM comp_cubed_64 AS img
+// [0.5]: [40:84, 2:46, 5:31]
+SELECT img[40:84, 2:46, 5:31]
+FROM comp_cubed_64 AS img
+// [1]: [51:106, 169:224, 105:138]
+SELECT img[51:106, 169:224, 105:138]
+FROM comp_cubed_64 AS img
+// [1]: [72:127, 30:85, 113:146]
+SELECT img[72:127, 30:85, 113:146]
+FROM comp_cubed_64 AS img
+// [1]: [104:159, 82:137, 48:81]
+SELECT img[104:159, 82:137, 48:81]
+FROM comp_cubed_64 AS img
+// [1]: [91:146, 86:141, 40:73]
+SELECT img[91:146, 86:141, 40:73]
+FROM comp_cubed_64 AS img
+// [1]: [121:176, 19:74, 59:92]
+SELECT img[121:176, 19:74, 59:92]
+FROM comp_cubed_64 AS img
+// [1]: [69:124, 156:211, 27:60]
+SELECT img[69:124, 156:211, 27:60]
+FROM comp_cubed_64 AS img
+// [1]: [24:79, 64:119, 25:58]
+SELECT img[24:79, 64:119, 25:58]
+FROM comp_cubed_64 AS img
+// [1]: [70:125, 193:248, 90:123]
+SELECT img[70:125, 193:248, 90:123]
+FROM comp_cubed_64 AS img
+// [1]: [193:248, 1:56, 38:71]
+SELECT img[193:248, 1:56, 38:71]
+FROM comp_cubed_64 AS img
+// [1]: [118:173, 178:233, 56:89]
+SELECT img[118:173, 178:233, 56:89]
+FROM comp_cubed_64 AS img
+// [1]: [118:173, 23:78, 21:54]
+SELECT img[118:173, 23:78, 21:54]
+FROM comp_cubed_64 AS img
+// [1]: [9:64, 166:221, 44:77]
+SELECT img[9:64, 166:221, 44:77]
+FROM comp_cubed_64 AS img
+// [1]: [66:121, 65:120, 93:126]
+SELECT img[66:121, 65:120, 93:126]
+FROM comp_cubed_64 AS img
+// [1]: [63:118, 141:196, 31:64]
+SELECT img[63:118, 141:196, 31:64]
+FROM comp_cubed_64 AS img
+// [1]: [89:144, 58:113, 39:72]
+SELECT img[89:144, 58:113, 39:72]
+FROM comp_cubed_64 AS img
+// [1]: [72:127, 124:179, 93:126]
+SELECT img[72:127, 124:179, 93:126]
+FROM comp_cubed_64 AS img
+// [1]: [46:101, 178:233, 41:74]
+SELECT img[46:101, 178:233, 41:74]
+FROM comp_cubed_64 AS img
+// [1]: [52:107, 10:65, 49:82]
+SELECT img[52:107, 10:65, 49:82]
+FROM comp_cubed_64 AS img
+// [1]: [151:206, 5:60, 1:34]
+SELECT img[151:206, 5:60, 1:34]
+FROM comp_cubed_64 AS img
+// [1]: [95:150, 71:126, 85:118]
+SELECT img[95:150, 71:126, 85:118]
+FROM comp_cubed_64 AS img
+// [2]: [31:100, 166:235, 7:49]
+SELECT img[31:100, 166:235, 7:49]
+FROM comp_cubed_64 AS img
+// [2]: [109:178, 174:243, 31:73]
+SELECT img[109:178, 174:243, 31:73]
+FROM comp_cubed_64 AS img
+// [2]: [24:93, 32:101, 91:133]
+SELECT img[24:93, 32:101, 91:133]
+FROM comp_cubed_64 AS img
+// [2]: [76:145, 52:121, 33:75]
+SELECT img[76:145, 52:121, 33:75]
+FROM comp_cubed_64 AS img
+// [2]: [82:151, 5:74, 17:59]
+SELECT img[82:151, 5:74, 17:59]
+FROM comp_cubed_64 AS img
+// [2]: [48:117, 100:169, 72:114]
+SELECT img[48:117, 100:169, 72:114]
+FROM comp_cubed_64 AS img
+// [2]: [81:150, 183:252, 39:81]
+SELECT img[81:150, 183:252, 39:81]
+FROM comp_cubed_64 AS img
+// [2]: [8:77, 122:191, 5:47]
+SELECT img[8:77, 122:191, 5:47]
+FROM comp_cubed_64 AS img
+// [2]: [170:239, 145:214, 23:65]
+SELECT img[170:239, 145:214, 23:65]
+FROM comp_cubed_64 AS img
+// [2]: [84:153, 101:170, 86:128]
+SELECT img[84:153, 101:170, 86:128]
+FROM comp_cubed_64 AS img
+// [2]: [72:141, 147:216, 32:74]
+SELECT img[72:141, 147:216, 32:74]
+FROM comp_cubed_64 AS img
+// [2]: [12:81, 25:94, 108:150]
+SELECT img[12:81, 25:94, 108:150]
+FROM comp_cubed_64 AS img
+// [2]: [94:163, 125:194, 29:71]
+SELECT img[94:163, 125:194, 29:71]
+FROM comp_cubed_64 AS img
+// [2]: [4:73, 44:113, 0:42]
+SELECT img[4:73, 44:113, 0:42]
+FROM comp_cubed_64 AS img
+// [2]: [134:203, 7:76, 85:127]
+SELECT img[134:203, 7:76, 85:127]
+FROM comp_cubed_64 AS img
+// [2]: [84:153, 168:237, 3:45]
+SELECT img[84:153, 168:237, 3:45]
+FROM comp_cubed_64 AS img
+// [2]: [166:235, 140:209, 41:83]
+SELECT img[166:235, 140:209, 41:83]
+FROM comp_cubed_64 AS img
+// [2]: [98:167, 43:112, 81:123]
+SELECT img[98:167, 43:112, 81:123]
+FROM comp_cubed_64 AS img
+// [2]: [5:74, 137:206, 29:71]
+SELECT img[5:74, 137:206, 29:71]
+FROM comp_cubed_64 AS img
+// [2]: [177:246, 45:114, 28:70]
+SELECT img[177:246, 45:114, 28:70]
+FROM comp_cubed_64 AS img
+// [5]: [52:146, 5:99, 72:128]
+SELECT img[52:146, 5:99, 72:128]
+FROM comp_cubed_64 AS img
+// [5]: [147:241, 45:139, 90:146]
+SELECT img[147:241, 45:139, 90:146]
+FROM comp_cubed_64 AS img
+// [5]: [156:250, 145:239, 7:63]
+SELECT img[156:250, 145:239, 7:63]
+FROM comp_cubed_64 AS img
+// [5]: [30:124, 108:202, 74:130]
+SELECT img[30:124, 108:202, 74:130]
+FROM comp_cubed_64 AS img
+// [5]: [140:234, 44:138, 25:81]
+SELECT img[140:234, 44:138, 25:81]
+FROM comp_cubed_64 AS img
+// [5]: [48:142, 9:103, 8:64]
+SELECT img[48:142, 9:103, 8:64]
+FROM comp_cubed_64 AS img
+// [5]: [0:94, 157:251, 73:129]
+SELECT img[0:94, 157:251, 73:129]
+FROM comp_cubed_64 AS img
+// [5]: [125:219, 53:147, 7:63]
+SELECT img[125:219, 53:147, 7:63]
+FROM comp_cubed_64 AS img
+// [5]: [26:120, 133:227, 38:94]
+SELECT img[26:120, 133:227, 38:94]
+FROM comp_cubed_64 AS img
+// [5]: [157:251, 41:135, 74:130]
+SELECT img[157:251, 41:135, 74:130]
+FROM comp_cubed_64 AS img
+// [5]: [41:135, 120:214, 31:87]
+SELECT img[41:135, 120:214, 31:87]
+FROM comp_cubed_64 AS img
+// [5]: [33:127, 116:210, 71:127]
+SELECT img[33:127, 116:210, 71:127]
+FROM comp_cubed_64 AS img
+// [5]: [138:232, 127:221, 20:76]
+SELECT img[138:232, 127:221, 20:76]
+FROM comp_cubed_64 AS img
+// [5]: [13:107, 9:103, 60:116]
+SELECT img[13:107, 9:103, 60:116]
+FROM comp_cubed_64 AS img
+// [5]: [124:218, 139:233, 74:130]
+SELECT img[124:218, 139:233, 74:130]
+FROM comp_cubed_64 AS img
+// [5]: [117:211, 86:180, 91:147]
+SELECT img[117:211, 86:180, 91:147]
+FROM comp_cubed_64 AS img
+// [5]: [143:237, 52:146, 71:127]
+SELECT img[143:237, 52:146, 71:127]
+FROM comp_cubed_64 AS img
+// [5]: [10:104, 35:129, 19:75]
+SELECT img[10:104, 35:129, 19:75]
+FROM comp_cubed_64 AS img
+// [5]: [110:204, 64:158, 64:120]
+SELECT img[110:204, 64:158, 64:120]
+FROM comp_cubed_64 AS img
+// [5]: [12:106, 103:197, 96:152]
+SELECT img[12:106, 103:197, 96:152]
+FROM comp_cubed_64 AS img
+// [10]: [108:226, 53:171, 9:80]
+SELECT img[108:226, 53:171, 9:80]
+FROM comp_cubed_64 AS img
+// [10]: [46:164, 103:221, 10:81]
+SELECT img[46:164, 103:221, 10:81]
+FROM comp_cubed_64 AS img
+// [10]: [80:198, 73:191, 38:109]
+SELECT img[80:198, 73:191, 38:109]
+FROM comp_cubed_64 AS img
+// [10]: [38:156, 132:250, 26:97]
+SELECT img[38:156, 132:250, 26:97]
+FROM comp_cubed_64 AS img
+// [10]: [11:129, 86:204, 77:148]
+SELECT img[11:129, 86:204, 77:148]
+FROM comp_cubed_64 AS img
+// [10]: [46:164, 90:208, 17:88]
+SELECT img[46:164, 90:208, 17:88]
+FROM comp_cubed_64 AS img
+// [10]: [86:204, 125:243, 6:77]
+SELECT img[86:204, 125:243, 6:77]
+FROM comp_cubed_64 AS img
+// [10]: [54:172, 49:167, 69:140]
+SELECT img[54:172, 49:167, 69:140]
+FROM comp_cubed_64 AS img
+// [10]: [11:129, 111:229, 23:94]
+SELECT img[11:129, 111:229, 23:94]
+FROM comp_cubed_64 AS img
+// [10]: [46:164, 66:184, 2:73]
+SELECT img[46:164, 66:184, 2:73]
+FROM comp_cubed_64 AS img
+// [10]: [88:206, 88:206, 39:110]
+SELECT img[88:206, 88:206, 39:110]
+FROM comp_cubed_64 AS img
+// [10]: [46:164, 22:140, 43:114]
+SELECT img[46:164, 22:140, 43:114]
+FROM comp_cubed_64 AS img
+// [10]: [4:122, 59:177, 47:118]
+SELECT img[4:122, 59:177, 47:118]
+FROM comp_cubed_64 AS img
+// [10]: [22:140, 37:155, 31:102]
+SELECT img[22:140, 37:155, 31:102]
+FROM comp_cubed_64 AS img
+// [10]: [109:227, 71:189, 81:152]
+SELECT img[109:227, 71:189, 81:152]
+FROM comp_cubed_64 AS img
+// [10]: [96:214, 76:194, 67:138]
+SELECT img[96:214, 76:194, 67:138]
+FROM comp_cubed_64 AS img
+// [10]: [4:122, 126:244, 10:81]
+SELECT img[4:122, 126:244, 10:81]
+FROM comp_cubed_64 AS img
+// [10]: [38:156, 90:208, 31:102]
+SELECT img[38:156, 90:208, 31:102]
+FROM comp_cubed_64 AS img
+// [10]: [12:130, 67:185, 70:141]
+SELECT img[12:130, 67:185, 70:141]
+FROM comp_cubed_64 AS img
+// [10]: [108:226, 59:177, 70:141]
+SELECT img[108:226, 59:177, 70:141]
+FROM comp_cubed_64 AS img
+// [20]: [60:209, 12:161, 15:104]
+SELECT img[60:209, 12:161, 15:104]
+FROM comp_cubed_64 AS img
+// [20]: [36:185, 68:217, 31:120]
+SELECT img[36:185, 68:217, 31:120]
+FROM comp_cubed_64 AS img
+// [20]: [19:168, 96:245, 50:139]
+SELECT img[19:168, 96:245, 50:139]
+FROM comp_cubed_64 AS img
+// [20]: [68:217, 96:245, 4:93]
+SELECT img[68:217, 96:245, 4:93]
+FROM comp_cubed_64 AS img
+// [20]: [16:165, 44:193, 49:138]
+SELECT img[16:165, 44:193, 49:138]
+FROM comp_cubed_64 AS img
+// [20]: [71:220, 91:240, 11:100]
+SELECT img[71:220, 91:240, 11:100]
+FROM comp_cubed_64 AS img
+// [20]: [96:245, 58:207, 4:93]
+SELECT img[96:245, 58:207, 4:93]
+FROM comp_cubed_64 AS img
+// [20]: [40:189, 6:155, 11:100]
+SELECT img[40:189, 6:155, 11:100]
+FROM comp_cubed_64 AS img
+// [20]: [91:240, 22:171, 7:96]
+SELECT img[91:240, 22:171, 7:96]
+FROM comp_cubed_64 AS img
+// [20]: [79:228, 85:234, 39:128]
+SELECT img[79:228, 85:234, 39:128]
+FROM comp_cubed_64 AS img
+// [20]: [97:246, 104:253, 6:95]
+SELECT img[97:246, 104:253, 6:95]
+FROM comp_cubed_64 AS img
+// [20]: [62:211, 26:175, 7:96]
+SELECT img[62:211, 26:175, 7:96]
+FROM comp_cubed_64 AS img
+// [20]: [35:184, 5:154, 29:118]
+SELECT img[35:184, 5:154, 29:118]
+FROM comp_cubed_64 AS img
+// [20]: [20:169, 92:241, 5:94]
+SELECT img[20:169, 92:241, 5:94]
+FROM comp_cubed_64 AS img
+// [20]: [77:226, 33:182, 45:134]
+SELECT img[77:226, 33:182, 45:134]
+FROM comp_cubed_64 AS img
+// [20]: [6:155, 40:189, 55:144]
+SELECT img[6:155, 40:189, 55:144]
+FROM comp_cubed_64 AS img
+// [20]: [102:251, 25:174, 20:109]
+SELECT img[102:251, 25:174, 20:109]
+FROM comp_cubed_64 AS img
+// [20]: [35:184, 70:219, 31:120]
+SELECT img[35:184, 70:219, 31:120]
+FROM comp_cubed_64 AS img
+// [20]: [99:248, 88:237, 10:99]
+SELECT img[99:248, 88:237, 10:99]
+FROM comp_cubed_64 AS img
+// [20]: [67:216, 63:212, 60:149]
+SELECT img[67:216, 63:212, 60:149]
+FROM comp_cubed_64 AS img
+// [50]: [46:248, 7:209, 31:152]
+SELECT img[46:248, 7:209, 31:152]
+FROM comp_cubed_64 AS img
+// [50]: [45:247, 24:226, 17:138]
+SELECT img[45:247, 24:226, 17:138]
+FROM comp_cubed_64 AS img
+// [50]: [22:224, 30:232, 9:130]
+SELECT img[22:224, 30:232, 9:130]
+FROM comp_cubed_64 AS img
+// [50]: [29:231, 39:241, 4:125]
+SELECT img[29:231, 39:241, 4:125]
+FROM comp_cubed_64 AS img
+// [50]: [19:221, 51:253, 6:127]
+SELECT img[19:221, 51:253, 6:127]
+FROM comp_cubed_64 AS img
+// [50]: [27:229, 14:216, 10:131]
+SELECT img[27:229, 14:216, 10:131]
+FROM comp_cubed_64 AS img
+// [50]: [33:235, 15:217, 26:147]
+SELECT img[33:235, 15:217, 26:147]
+FROM comp_cubed_64 AS img
+// [50]: [48:250, 1:203, 18:139]
+SELECT img[48:250, 1:203, 18:139]
+FROM comp_cubed_64 AS img
+// [50]: [24:226, 23:225, 23:144]
+SELECT img[24:226, 23:225, 23:144]
+FROM comp_cubed_64 AS img
+// [50]: [31:233, 12:214, 8:129]
+SELECT img[31:233, 12:214, 8:129]
+FROM comp_cubed_64 AS img
+// [50]: [34:236, 1:203, 24:145]
+SELECT img[34:236, 1:203, 24:145]
+FROM comp_cubed_64 AS img
+// [50]: [27:229, 17:219, 22:143]
+SELECT img[27:229, 17:219, 22:143]
+FROM comp_cubed_64 AS img
+// [50]: [15:217, 50:252, 16:137]
+SELECT img[15:217, 50:252, 16:137]
+FROM comp_cubed_64 AS img
+// [50]: [49:251, 3:205, 29:150]
+SELECT img[49:251, 3:205, 29:150]
+FROM comp_cubed_64 AS img
+// [50]: [11:213, 33:235, 17:138]
+SELECT img[11:213, 33:235, 17:138]
+FROM comp_cubed_64 AS img
+// [50]: [15:217, 23:225, 29:150]
+SELECT img[15:217, 23:225, 29:150]
+FROM comp_cubed_64 AS img
+// [50]: [46:248, 28:230, 30:151]
+SELECT img[46:248, 28:230, 30:151]
+FROM comp_cubed_64 AS img
+// [50]: [11:213, 6:208, 1:122]
+SELECT img[11:213, 6:208, 1:122]
+FROM comp_cubed_64 AS img
+// [50]: [13:215, 16:218, 24:145]
+SELECT img[13:215, 16:218, 24:145]
+FROM comp_cubed_64 AS img
+// [50]: [44:246, 46:248, 28:149]
+SELECT img[44:246, 46:248, 28:149]
+FROM comp_cubed_64 AS img
diff --git a/rasodmg/test/croll_16.ql b/rasodmg/test/croll_16.ql
new file mode 100644
index 0000000..8e37740
--- /dev/null
+++ b/rasodmg/test/croll_16.ql
@@ -0,0 +1,180 @@
+// ["x"] comp_cubed_16 [232:238,*:*,*:*]
+SELECT img[232,*:*,*:*]+img[233,*:*,*:*]+img[234,*:*,*:*]+img[235,*:*,*:*]+img[236,*:*,*:*]+img[237,*:*,*:*]+img[238,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [179:185,*:*,*:*]
+SELECT img[179,*:*,*:*]+img[180,*:*,*:*]+img[181,*:*,*:*]+img[182,*:*,*:*]+img[183,*:*,*:*]+img[184,*:*,*:*]+img[185,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [24:30,*:*,*:*]
+SELECT img[24,*:*,*:*]+img[25,*:*,*:*]+img[26,*:*,*:*]+img[27,*:*,*:*]+img[28,*:*,*:*]+img[29,*:*,*:*]+img[30,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [188:194,*:*,*:*]
+SELECT img[188,*:*,*:*]+img[189,*:*,*:*]+img[190,*:*,*:*]+img[191,*:*,*:*]+img[192,*:*,*:*]+img[193,*:*,*:*]+img[194,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [238:244,*:*,*:*]
+SELECT img[238,*:*,*:*]+img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]+img[243,*:*,*:*]+img[244,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [76:82,*:*,*:*]
+SELECT img[76,*:*,*:*]+img[77,*:*,*:*]+img[78,*:*,*:*]+img[79,*:*,*:*]+img[80,*:*,*:*]+img[81,*:*,*:*]+img[82,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [239:245,*:*,*:*]
+SELECT img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]+img[243,*:*,*:*]+img[244,*:*,*:*]+img[245,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [119:125,*:*,*:*]
+SELECT img[119,*:*,*:*]+img[120,*:*,*:*]+img[121,*:*,*:*]+img[122,*:*,*:*]+img[123,*:*,*:*]+img[124,*:*,*:*]+img[125,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [176:182,*:*,*:*]
+SELECT img[176,*:*,*:*]+img[177,*:*,*:*]+img[178,*:*,*:*]+img[179,*:*,*:*]+img[180,*:*,*:*]+img[181,*:*,*:*]+img[182,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [51:57,*:*,*:*]
+SELECT img[51,*:*,*:*]+img[52,*:*,*:*]+img[53,*:*,*:*]+img[54,*:*,*:*]+img[55,*:*,*:*]+img[56,*:*,*:*]+img[57,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [8:14,*:*,*:*]
+SELECT img[8,*:*,*:*]+img[9,*:*,*:*]+img[10,*:*,*:*]+img[11,*:*,*:*]+img[12,*:*,*:*]+img[13,*:*,*:*]+img[14,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [173:179,*:*,*:*]
+SELECT img[173,*:*,*:*]+img[174,*:*,*:*]+img[175,*:*,*:*]+img[176,*:*,*:*]+img[177,*:*,*:*]+img[178,*:*,*:*]+img[179,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [237:243,*:*,*:*]
+SELECT img[237,*:*,*:*]+img[238,*:*,*:*]+img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]+img[243,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [84:90,*:*,*:*]
+SELECT img[84,*:*,*:*]+img[85,*:*,*:*]+img[86,*:*,*:*]+img[87,*:*,*:*]+img[88,*:*,*:*]+img[89,*:*,*:*]+img[90,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [14:20,*:*,*:*]
+SELECT img[14,*:*,*:*]+img[15,*:*,*:*]+img[16,*:*,*:*]+img[17,*:*,*:*]+img[18,*:*,*:*]+img[19,*:*,*:*]+img[20,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [144:150,*:*,*:*]
+SELECT img[144,*:*,*:*]+img[145,*:*,*:*]+img[146,*:*,*:*]+img[147,*:*,*:*]+img[148,*:*,*:*]+img[149,*:*,*:*]+img[150,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [215:221,*:*,*:*]
+SELECT img[215,*:*,*:*]+img[216,*:*,*:*]+img[217,*:*,*:*]+img[218,*:*,*:*]+img[219,*:*,*:*]+img[220,*:*,*:*]+img[221,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [86:92,*:*,*:*]
+SELECT img[86,*:*,*:*]+img[87,*:*,*:*]+img[88,*:*,*:*]+img[89,*:*,*:*]+img[90,*:*,*:*]+img[91,*:*,*:*]+img[92,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [136:142,*:*,*:*]
+SELECT img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]+img[140,*:*,*:*]+img[141,*:*,*:*]+img[142,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["x"] comp_cubed_16 [135:141,*:*,*:*]
+SELECT img[135,*:*,*:*]+img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]+img[140,*:*,*:*]+img[141,*:*,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 146:152, *:*]
+SELECT img[*:*,146,*:*]+img[*:*,147,*:*]+img[*:*,148,*:*]+img[*:*,149,*:*]+img[*:*,150,*:*]+img[*:*,151,*:*]+img[*:*,152,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 15:21, *:*]
+SELECT img[*:*,15,*:*]+img[*:*,16,*:*]+img[*:*,17,*:*]+img[*:*,18,*:*]+img[*:*,19,*:*]+img[*:*,20,*:*]+img[*:*,21,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 148:154, *:*]
+SELECT img[*:*,148,*:*]+img[*:*,149,*:*]+img[*:*,150,*:*]+img[*:*,151,*:*]+img[*:*,152,*:*]+img[*:*,153,*:*]+img[*:*,154,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 82:88, *:*]
+SELECT img[*:*,82,*:*]+img[*:*,83,*:*]+img[*:*,84,*:*]+img[*:*,85,*:*]+img[*:*,86,*:*]+img[*:*,87,*:*]+img[*:*,88,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 149:155, *:*]
+SELECT img[*:*,149,*:*]+img[*:*,150,*:*]+img[*:*,151,*:*]+img[*:*,152,*:*]+img[*:*,153,*:*]+img[*:*,154,*:*]+img[*:*,155,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 154:160, *:*]
+SELECT img[*:*,154,*:*]+img[*:*,155,*:*]+img[*:*,156,*:*]+img[*:*,157,*:*]+img[*:*,158,*:*]+img[*:*,159,*:*]+img[*:*,160,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 46:52, *:*]
+SELECT img[*:*,46,*:*]+img[*:*,47,*:*]+img[*:*,48,*:*]+img[*:*,49,*:*]+img[*:*,50,*:*]+img[*:*,51,*:*]+img[*:*,52,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 3:9, *:*]
+SELECT img[*:*,3,*:*]+img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 20:26, *:*]
+SELECT img[*:*,20,*:*]+img[*:*,21,*:*]+img[*:*,22,*:*]+img[*:*,23,*:*]+img[*:*,24,*:*]+img[*:*,25,*:*]+img[*:*,26,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 17:23, *:*]
+SELECT img[*:*,17,*:*]+img[*:*,18,*:*]+img[*:*,19,*:*]+img[*:*,20,*:*]+img[*:*,21,*:*]+img[*:*,22,*:*]+img[*:*,23,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 236:242, *:*]
+SELECT img[*:*,236,*:*]+img[*:*,237,*:*]+img[*:*,238,*:*]+img[*:*,239,*:*]+img[*:*,240,*:*]+img[*:*,241,*:*]+img[*:*,242,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 98:104, *:*]
+SELECT img[*:*,98,*:*]+img[*:*,99,*:*]+img[*:*,100,*:*]+img[*:*,101,*:*]+img[*:*,102,*:*]+img[*:*,103,*:*]+img[*:*,104,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 4:10, *:*]
+SELECT img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]+img[*:*,10,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 199:205, *:*]
+SELECT img[*:*,199,*:*]+img[*:*,200,*:*]+img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]+img[*:*,204,*:*]+img[*:*,205,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 197:203, *:*]
+SELECT img[*:*,197,*:*]+img[*:*,198,*:*]+img[*:*,199,*:*]+img[*:*,200,*:*]+img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 19:25, *:*]
+SELECT img[*:*,19,*:*]+img[*:*,20,*:*]+img[*:*,21,*:*]+img[*:*,22,*:*]+img[*:*,23,*:*]+img[*:*,24,*:*]+img[*:*,25,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 64:70, *:*]
+SELECT img[*:*,64,*:*]+img[*:*,65,*:*]+img[*:*,66,*:*]+img[*:*,67,*:*]+img[*:*,68,*:*]+img[*:*,69,*:*]+img[*:*,70,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 169:175, *:*]
+SELECT img[*:*,169,*:*]+img[*:*,170,*:*]+img[*:*,171,*:*]+img[*:*,172,*:*]+img[*:*,173,*:*]+img[*:*,174,*:*]+img[*:*,175,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 109:115, *:*]
+SELECT img[*:*,109,*:*]+img[*:*,110,*:*]+img[*:*,111,*:*]+img[*:*,112,*:*]+img[*:*,113,*:*]+img[*:*,114,*:*]+img[*:*,115,*:*]
+FROM comp_cubed_16 as img
+// ["y"] comp_cubed_16 [*:*, 148:154, *:*]
+SELECT img[*:*,148,*:*]+img[*:*,149,*:*]+img[*:*,150,*:*]+img[*:*,151,*:*]+img[*:*,152,*:*]+img[*:*,153,*:*]+img[*:*,154,*:*]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 35:41]
+SELECT img[*:*,*:*,35]+img[*:*,*:*,36]+img[*:*,*:*,37]+img[*:*,*:*,38]+img[*:*,*:*,39]+img[*:*,*:*,40]+img[*:*,*:*,41]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 24:30]
+SELECT img[*:*,*:*,24]+img[*:*,*:*,25]+img[*:*,*:*,26]+img[*:*,*:*,27]+img[*:*,*:*,28]+img[*:*,*:*,29]+img[*:*,*:*,30]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 38:44]
+SELECT img[*:*,*:*,38]+img[*:*,*:*,39]+img[*:*,*:*,40]+img[*:*,*:*,41]+img[*:*,*:*,42]+img[*:*,*:*,43]+img[*:*,*:*,44]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 129:135]
+SELECT img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]+img[*:*,*:*,134]+img[*:*,*:*,135]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 88:94]
+SELECT img[*:*,*:*,88]+img[*:*,*:*,89]+img[*:*,*:*,90]+img[*:*,*:*,91]+img[*:*,*:*,92]+img[*:*,*:*,93]+img[*:*,*:*,94]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 49:55]
+SELECT img[*:*,*:*,49]+img[*:*,*:*,50]+img[*:*,*:*,51]+img[*:*,*:*,52]+img[*:*,*:*,53]+img[*:*,*:*,54]+img[*:*,*:*,55]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 70:76]
+SELECT img[*:*,*:*,70]+img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]+img[*:*,*:*,74]+img[*:*,*:*,75]+img[*:*,*:*,76]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 76:82]
+SELECT img[*:*,*:*,76]+img[*:*,*:*,77]+img[*:*,*:*,78]+img[*:*,*:*,79]+img[*:*,*:*,80]+img[*:*,*:*,81]+img[*:*,*:*,82]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 60:66]
+SELECT img[*:*,*:*,60]+img[*:*,*:*,61]+img[*:*,*:*,62]+img[*:*,*:*,63]+img[*:*,*:*,64]+img[*:*,*:*,65]+img[*:*,*:*,66]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 9:15]
+SELECT img[*:*,*:*,9]+img[*:*,*:*,10]+img[*:*,*:*,11]+img[*:*,*:*,12]+img[*:*,*:*,13]+img[*:*,*:*,14]+img[*:*,*:*,15]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 14:20]
+SELECT img[*:*,*:*,14]+img[*:*,*:*,15]+img[*:*,*:*,16]+img[*:*,*:*,17]+img[*:*,*:*,18]+img[*:*,*:*,19]+img[*:*,*:*,20]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 2:8]
+SELECT img[*:*,*:*,2]+img[*:*,*:*,3]+img[*:*,*:*,4]+img[*:*,*:*,5]+img[*:*,*:*,6]+img[*:*,*:*,7]+img[*:*,*:*,8]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 29:35]
+SELECT img[*:*,*:*,29]+img[*:*,*:*,30]+img[*:*,*:*,31]+img[*:*,*:*,32]+img[*:*,*:*,33]+img[*:*,*:*,34]+img[*:*,*:*,35]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 48:54]
+SELECT img[*:*,*:*,48]+img[*:*,*:*,49]+img[*:*,*:*,50]+img[*:*,*:*,51]+img[*:*,*:*,52]+img[*:*,*:*,53]+img[*:*,*:*,54]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 89:95]
+SELECT img[*:*,*:*,89]+img[*:*,*:*,90]+img[*:*,*:*,91]+img[*:*,*:*,92]+img[*:*,*:*,93]+img[*:*,*:*,94]+img[*:*,*:*,95]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 75:81]
+SELECT img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]+img[*:*,*:*,78]+img[*:*,*:*,79]+img[*:*,*:*,80]+img[*:*,*:*,81]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 83:89]
+SELECT img[*:*,*:*,83]+img[*:*,*:*,84]+img[*:*,*:*,85]+img[*:*,*:*,86]+img[*:*,*:*,87]+img[*:*,*:*,88]+img[*:*,*:*,89]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 125:131]
+SELECT img[*:*,*:*,125]+img[*:*,*:*,126]+img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 132:138]
+SELECT img[*:*,*:*,132]+img[*:*,*:*,133]+img[*:*,*:*,134]+img[*:*,*:*,135]+img[*:*,*:*,136]+img[*:*,*:*,137]+img[*:*,*:*,138]
+FROM comp_cubed_16 as img
+// ["z"] comp_cubed_16 [*:*, *:*, 32:38]
+SELECT img[*:*,*:*,32]+img[*:*,*:*,33]+img[*:*,*:*,34]+img[*:*,*:*,35]+img[*:*,*:*,36]+img[*:*,*:*,37]+img[*:*,*:*,38]
+FROM comp_cubed_16 as img
diff --git a/rasodmg/test/croll_32.ql b/rasodmg/test/croll_32.ql
new file mode 100644
index 0000000..b4b1790
--- /dev/null
+++ b/rasodmg/test/croll_32.ql
@@ -0,0 +1,180 @@
+// ["x"] comp_cubed [133:139,*:*,*:*]
+SELECT img[133,*:*,*:*]+img[134,*:*,*:*]+img[135,*:*,*:*]+img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [248:254,*:*,*:*]
+SELECT img[248,*:*,*:*]+img[249,*:*,*:*]+img[250,*:*,*:*]+img[251,*:*,*:*]+img[252,*:*,*:*]+img[253,*:*,*:*]+img[254,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [94:100,*:*,*:*]
+SELECT img[94,*:*,*:*]+img[95,*:*,*:*]+img[96,*:*,*:*]+img[97,*:*,*:*]+img[98,*:*,*:*]+img[99,*:*,*:*]+img[100,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [3:9,*:*,*:*]
+SELECT img[3,*:*,*:*]+img[4,*:*,*:*]+img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]+img[8,*:*,*:*]+img[9,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [93:99,*:*,*:*]
+SELECT img[93,*:*,*:*]+img[94,*:*,*:*]+img[95,*:*,*:*]+img[96,*:*,*:*]+img[97,*:*,*:*]+img[98,*:*,*:*]+img[99,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [62:68,*:*,*:*]
+SELECT img[62,*:*,*:*]+img[63,*:*,*:*]+img[64,*:*,*:*]+img[65,*:*,*:*]+img[66,*:*,*:*]+img[67,*:*,*:*]+img[68,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [174:180,*:*,*:*]
+SELECT img[174,*:*,*:*]+img[175,*:*,*:*]+img[176,*:*,*:*]+img[177,*:*,*:*]+img[178,*:*,*:*]+img[179,*:*,*:*]+img[180,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [97:103,*:*,*:*]
+SELECT img[97,*:*,*:*]+img[98,*:*,*:*]+img[99,*:*,*:*]+img[100,*:*,*:*]+img[101,*:*,*:*]+img[102,*:*,*:*]+img[103,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [43:49,*:*,*:*]
+SELECT img[43,*:*,*:*]+img[44,*:*,*:*]+img[45,*:*,*:*]+img[46,*:*,*:*]+img[47,*:*,*:*]+img[48,*:*,*:*]+img[49,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [41:47,*:*,*:*]
+SELECT img[41,*:*,*:*]+img[42,*:*,*:*]+img[43,*:*,*:*]+img[44,*:*,*:*]+img[45,*:*,*:*]+img[46,*:*,*:*]+img[47,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [38:44,*:*,*:*]
+SELECT img[38,*:*,*:*]+img[39,*:*,*:*]+img[40,*:*,*:*]+img[41,*:*,*:*]+img[42,*:*,*:*]+img[43,*:*,*:*]+img[44,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [75:81,*:*,*:*]
+SELECT img[75,*:*,*:*]+img[76,*:*,*:*]+img[77,*:*,*:*]+img[78,*:*,*:*]+img[79,*:*,*:*]+img[80,*:*,*:*]+img[81,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [189:195,*:*,*:*]
+SELECT img[189,*:*,*:*]+img[190,*:*,*:*]+img[191,*:*,*:*]+img[192,*:*,*:*]+img[193,*:*,*:*]+img[194,*:*,*:*]+img[195,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [3:9,*:*,*:*]
+SELECT img[3,*:*,*:*]+img[4,*:*,*:*]+img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]+img[8,*:*,*:*]+img[9,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [38:44,*:*,*:*]
+SELECT img[38,*:*,*:*]+img[39,*:*,*:*]+img[40,*:*,*:*]+img[41,*:*,*:*]+img[42,*:*,*:*]+img[43,*:*,*:*]+img[44,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [5:11,*:*,*:*]
+SELECT img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]+img[8,*:*,*:*]+img[9,*:*,*:*]+img[10,*:*,*:*]+img[11,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [83:89,*:*,*:*]
+SELECT img[83,*:*,*:*]+img[84,*:*,*:*]+img[85,*:*,*:*]+img[86,*:*,*:*]+img[87,*:*,*:*]+img[88,*:*,*:*]+img[89,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [23:29,*:*,*:*]
+SELECT img[23,*:*,*:*]+img[24,*:*,*:*]+img[25,*:*,*:*]+img[26,*:*,*:*]+img[27,*:*,*:*]+img[28,*:*,*:*]+img[29,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [185:191,*:*,*:*]
+SELECT img[185,*:*,*:*]+img[186,*:*,*:*]+img[187,*:*,*:*]+img[188,*:*,*:*]+img[189,*:*,*:*]+img[190,*:*,*:*]+img[191,*:*,*:*]
+FROM comp_cubed as img
+// ["x"] comp_cubed [148:154,*:*,*:*]
+SELECT img[148,*:*,*:*]+img[149,*:*,*:*]+img[150,*:*,*:*]+img[151,*:*,*:*]+img[152,*:*,*:*]+img[153,*:*,*:*]+img[154,*:*,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 100:106, *:*]
+SELECT img[*:*,100,*:*]+img[*:*,101,*:*]+img[*:*,102,*:*]+img[*:*,103,*:*]+img[*:*,104,*:*]+img[*:*,105,*:*]+img[*:*,106,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 2:8, *:*]
+SELECT img[*:*,2,*:*]+img[*:*,3,*:*]+img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 166:172, *:*]
+SELECT img[*:*,166,*:*]+img[*:*,167,*:*]+img[*:*,168,*:*]+img[*:*,169,*:*]+img[*:*,170,*:*]+img[*:*,171,*:*]+img[*:*,172,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 246:252, *:*]
+SELECT img[*:*,246,*:*]+img[*:*,247,*:*]+img[*:*,248,*:*]+img[*:*,249,*:*]+img[*:*,250,*:*]+img[*:*,251,*:*]+img[*:*,252,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 78:84, *:*]
+SELECT img[*:*,78,*:*]+img[*:*,79,*:*]+img[*:*,80,*:*]+img[*:*,81,*:*]+img[*:*,82,*:*]+img[*:*,83,*:*]+img[*:*,84,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 174:180, *:*]
+SELECT img[*:*,174,*:*]+img[*:*,175,*:*]+img[*:*,176,*:*]+img[*:*,177,*:*]+img[*:*,178,*:*]+img[*:*,179,*:*]+img[*:*,180,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 233:239, *:*]
+SELECT img[*:*,233,*:*]+img[*:*,234,*:*]+img[*:*,235,*:*]+img[*:*,236,*:*]+img[*:*,237,*:*]+img[*:*,238,*:*]+img[*:*,239,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 131:137, *:*]
+SELECT img[*:*,131,*:*]+img[*:*,132,*:*]+img[*:*,133,*:*]+img[*:*,134,*:*]+img[*:*,135,*:*]+img[*:*,136,*:*]+img[*:*,137,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 25:31, *:*]
+SELECT img[*:*,25,*:*]+img[*:*,26,*:*]+img[*:*,27,*:*]+img[*:*,28,*:*]+img[*:*,29,*:*]+img[*:*,30,*:*]+img[*:*,31,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 170:176, *:*]
+SELECT img[*:*,170,*:*]+img[*:*,171,*:*]+img[*:*,172,*:*]+img[*:*,173,*:*]+img[*:*,174,*:*]+img[*:*,175,*:*]+img[*:*,176,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 85:91, *:*]
+SELECT img[*:*,85,*:*]+img[*:*,86,*:*]+img[*:*,87,*:*]+img[*:*,88,*:*]+img[*:*,89,*:*]+img[*:*,90,*:*]+img[*:*,91,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 178:184, *:*]
+SELECT img[*:*,178,*:*]+img[*:*,179,*:*]+img[*:*,180,*:*]+img[*:*,181,*:*]+img[*:*,182,*:*]+img[*:*,183,*:*]+img[*:*,184,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 198:204, *:*]
+SELECT img[*:*,198,*:*]+img[*:*,199,*:*]+img[*:*,200,*:*]+img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]+img[*:*,204,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 54:60, *:*]
+SELECT img[*:*,54,*:*]+img[*:*,55,*:*]+img[*:*,56,*:*]+img[*:*,57,*:*]+img[*:*,58,*:*]+img[*:*,59,*:*]+img[*:*,60,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 227:233, *:*]
+SELECT img[*:*,227,*:*]+img[*:*,228,*:*]+img[*:*,229,*:*]+img[*:*,230,*:*]+img[*:*,231,*:*]+img[*:*,232,*:*]+img[*:*,233,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 4:10, *:*]
+SELECT img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]+img[*:*,10,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 7:13, *:*]
+SELECT img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]+img[*:*,10,*:*]+img[*:*,11,*:*]+img[*:*,12,*:*]+img[*:*,13,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 217:223, *:*]
+SELECT img[*:*,217,*:*]+img[*:*,218,*:*]+img[*:*,219,*:*]+img[*:*,220,*:*]+img[*:*,221,*:*]+img[*:*,222,*:*]+img[*:*,223,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 200:206, *:*]
+SELECT img[*:*,200,*:*]+img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]+img[*:*,204,*:*]+img[*:*,205,*:*]+img[*:*,206,*:*]
+FROM comp_cubed as img
+// ["y"] comp_cubed [*:*, 181:187, *:*]
+SELECT img[*:*,181,*:*]+img[*:*,182,*:*]+img[*:*,183,*:*]+img[*:*,184,*:*]+img[*:*,185,*:*]+img[*:*,186,*:*]+img[*:*,187,*:*]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 4:10]
+SELECT img[*:*,*:*,4]+img[*:*,*:*,5]+img[*:*,*:*,6]+img[*:*,*:*,7]+img[*:*,*:*,8]+img[*:*,*:*,9]+img[*:*,*:*,10]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 29:35]
+SELECT img[*:*,*:*,29]+img[*:*,*:*,30]+img[*:*,*:*,31]+img[*:*,*:*,32]+img[*:*,*:*,33]+img[*:*,*:*,34]+img[*:*,*:*,35]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 74:80]
+SELECT img[*:*,*:*,74]+img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]+img[*:*,*:*,78]+img[*:*,*:*,79]+img[*:*,*:*,80]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 71:77]
+SELECT img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]+img[*:*,*:*,74]+img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 125:131]
+SELECT img[*:*,*:*,125]+img[*:*,*:*,126]+img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 146:152]
+SELECT img[*:*,*:*,146]+img[*:*,*:*,147]+img[*:*,*:*,148]+img[*:*,*:*,149]+img[*:*,*:*,150]+img[*:*,*:*,151]+img[*:*,*:*,152]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 138:144]
+SELECT img[*:*,*:*,138]+img[*:*,*:*,139]+img[*:*,*:*,140]+img[*:*,*:*,141]+img[*:*,*:*,142]+img[*:*,*:*,143]+img[*:*,*:*,144]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 81:87]
+SELECT img[*:*,*:*,81]+img[*:*,*:*,82]+img[*:*,*:*,83]+img[*:*,*:*,84]+img[*:*,*:*,85]+img[*:*,*:*,86]+img[*:*,*:*,87]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 133:139]
+SELECT img[*:*,*:*,133]+img[*:*,*:*,134]+img[*:*,*:*,135]+img[*:*,*:*,136]+img[*:*,*:*,137]+img[*:*,*:*,138]+img[*:*,*:*,139]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 131:137]
+SELECT img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]+img[*:*,*:*,134]+img[*:*,*:*,135]+img[*:*,*:*,136]+img[*:*,*:*,137]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 52:58]
+SELECT img[*:*,*:*,52]+img[*:*,*:*,53]+img[*:*,*:*,54]+img[*:*,*:*,55]+img[*:*,*:*,56]+img[*:*,*:*,57]+img[*:*,*:*,58]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 67:73]
+SELECT img[*:*,*:*,67]+img[*:*,*:*,68]+img[*:*,*:*,69]+img[*:*,*:*,70]+img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 104:110]
+SELECT img[*:*,*:*,104]+img[*:*,*:*,105]+img[*:*,*:*,106]+img[*:*,*:*,107]+img[*:*,*:*,108]+img[*:*,*:*,109]+img[*:*,*:*,110]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 95:101]
+SELECT img[*:*,*:*,95]+img[*:*,*:*,96]+img[*:*,*:*,97]+img[*:*,*:*,98]+img[*:*,*:*,99]+img[*:*,*:*,100]+img[*:*,*:*,101]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 71:77]
+SELECT img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]+img[*:*,*:*,74]+img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 5:11]
+SELECT img[*:*,*:*,5]+img[*:*,*:*,6]+img[*:*,*:*,7]+img[*:*,*:*,8]+img[*:*,*:*,9]+img[*:*,*:*,10]+img[*:*,*:*,11]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 127:133]
+SELECT img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 4:10]
+SELECT img[*:*,*:*,4]+img[*:*,*:*,5]+img[*:*,*:*,6]+img[*:*,*:*,7]+img[*:*,*:*,8]+img[*:*,*:*,9]+img[*:*,*:*,10]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 141:147]
+SELECT img[*:*,*:*,141]+img[*:*,*:*,142]+img[*:*,*:*,143]+img[*:*,*:*,144]+img[*:*,*:*,145]+img[*:*,*:*,146]+img[*:*,*:*,147]
+FROM comp_cubed as img
+// ["z"] comp_cubed [*:*, *:*, 82:88]
+SELECT img[*:*,*:*,82]+img[*:*,*:*,83]+img[*:*,*:*,84]+img[*:*,*:*,85]+img[*:*,*:*,86]+img[*:*,*:*,87]+img[*:*,*:*,88]
+FROM comp_cubed as img
diff --git a/rasodmg/test/croll_64.ql b/rasodmg/test/croll_64.ql
new file mode 100644
index 0000000..5729a42
--- /dev/null
+++ b/rasodmg/test/croll_64.ql
@@ -0,0 +1,180 @@
+// ["x"] comp_cubed_64 [32:38,*:*,*:*]
+SELECT img[32,*:*,*:*]+img[33,*:*,*:*]+img[34,*:*,*:*]+img[35,*:*,*:*]+img[36,*:*,*:*]+img[37,*:*,*:*]+img[38,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [134:140,*:*,*:*]
+SELECT img[134,*:*,*:*]+img[135,*:*,*:*]+img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]+img[140,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [116:122,*:*,*:*]
+SELECT img[116,*:*,*:*]+img[117,*:*,*:*]+img[118,*:*,*:*]+img[119,*:*,*:*]+img[120,*:*,*:*]+img[121,*:*,*:*]+img[122,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [244:250,*:*,*:*]
+SELECT img[244,*:*,*:*]+img[245,*:*,*:*]+img[246,*:*,*:*]+img[247,*:*,*:*]+img[248,*:*,*:*]+img[249,*:*,*:*]+img[250,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [182:188,*:*,*:*]
+SELECT img[182,*:*,*:*]+img[183,*:*,*:*]+img[184,*:*,*:*]+img[185,*:*,*:*]+img[186,*:*,*:*]+img[187,*:*,*:*]+img[188,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [233:239,*:*,*:*]
+SELECT img[233,*:*,*:*]+img[234,*:*,*:*]+img[235,*:*,*:*]+img[236,*:*,*:*]+img[237,*:*,*:*]+img[238,*:*,*:*]+img[239,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [134:140,*:*,*:*]
+SELECT img[134,*:*,*:*]+img[135,*:*,*:*]+img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]+img[140,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [216:222,*:*,*:*]
+SELECT img[216,*:*,*:*]+img[217,*:*,*:*]+img[218,*:*,*:*]+img[219,*:*,*:*]+img[220,*:*,*:*]+img[221,*:*,*:*]+img[222,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [176:182,*:*,*:*]
+SELECT img[176,*:*,*:*]+img[177,*:*,*:*]+img[178,*:*,*:*]+img[179,*:*,*:*]+img[180,*:*,*:*]+img[181,*:*,*:*]+img[182,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [200:206,*:*,*:*]
+SELECT img[200,*:*,*:*]+img[201,*:*,*:*]+img[202,*:*,*:*]+img[203,*:*,*:*]+img[204,*:*,*:*]+img[205,*:*,*:*]+img[206,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [140:146,*:*,*:*]
+SELECT img[140,*:*,*:*]+img[141,*:*,*:*]+img[142,*:*,*:*]+img[143,*:*,*:*]+img[144,*:*,*:*]+img[145,*:*,*:*]+img[146,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [54:60,*:*,*:*]
+SELECT img[54,*:*,*:*]+img[55,*:*,*:*]+img[56,*:*,*:*]+img[57,*:*,*:*]+img[58,*:*,*:*]+img[59,*:*,*:*]+img[60,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [94:100,*:*,*:*]
+SELECT img[94,*:*,*:*]+img[95,*:*,*:*]+img[96,*:*,*:*]+img[97,*:*,*:*]+img[98,*:*,*:*]+img[99,*:*,*:*]+img[100,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [14:20,*:*,*:*]
+SELECT img[14,*:*,*:*]+img[15,*:*,*:*]+img[16,*:*,*:*]+img[17,*:*,*:*]+img[18,*:*,*:*]+img[19,*:*,*:*]+img[20,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [211:217,*:*,*:*]
+SELECT img[211,*:*,*:*]+img[212,*:*,*:*]+img[213,*:*,*:*]+img[214,*:*,*:*]+img[215,*:*,*:*]+img[216,*:*,*:*]+img[217,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [156:162,*:*,*:*]
+SELECT img[156,*:*,*:*]+img[157,*:*,*:*]+img[158,*:*,*:*]+img[159,*:*,*:*]+img[160,*:*,*:*]+img[161,*:*,*:*]+img[162,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [196:202,*:*,*:*]
+SELECT img[196,*:*,*:*]+img[197,*:*,*:*]+img[198,*:*,*:*]+img[199,*:*,*:*]+img[200,*:*,*:*]+img[201,*:*,*:*]+img[202,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [181:187,*:*,*:*]
+SELECT img[181,*:*,*:*]+img[182,*:*,*:*]+img[183,*:*,*:*]+img[184,*:*,*:*]+img[185,*:*,*:*]+img[186,*:*,*:*]+img[187,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [80:86,*:*,*:*]
+SELECT img[80,*:*,*:*]+img[81,*:*,*:*]+img[82,*:*,*:*]+img[83,*:*,*:*]+img[84,*:*,*:*]+img[85,*:*,*:*]+img[86,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["x"] comp_cubed_64 [1:7,*:*,*:*]
+SELECT img[1,*:*,*:*]+img[2,*:*,*:*]+img[3,*:*,*:*]+img[4,*:*,*:*]+img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 72:78, *:*]
+SELECT img[*:*,72,*:*]+img[*:*,73,*:*]+img[*:*,74,*:*]+img[*:*,75,*:*]+img[*:*,76,*:*]+img[*:*,77,*:*]+img[*:*,78,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 211:217, *:*]
+SELECT img[*:*,211,*:*]+img[*:*,212,*:*]+img[*:*,213,*:*]+img[*:*,214,*:*]+img[*:*,215,*:*]+img[*:*,216,*:*]+img[*:*,217,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 199:205, *:*]
+SELECT img[*:*,199,*:*]+img[*:*,200,*:*]+img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]+img[*:*,204,*:*]+img[*:*,205,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 92:98, *:*]
+SELECT img[*:*,92,*:*]+img[*:*,93,*:*]+img[*:*,94,*:*]+img[*:*,95,*:*]+img[*:*,96,*:*]+img[*:*,97,*:*]+img[*:*,98,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 233:239, *:*]
+SELECT img[*:*,233,*:*]+img[*:*,234,*:*]+img[*:*,235,*:*]+img[*:*,236,*:*]+img[*:*,237,*:*]+img[*:*,238,*:*]+img[*:*,239,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 201:207, *:*]
+SELECT img[*:*,201,*:*]+img[*:*,202,*:*]+img[*:*,203,*:*]+img[*:*,204,*:*]+img[*:*,205,*:*]+img[*:*,206,*:*]+img[*:*,207,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 59:65, *:*]
+SELECT img[*:*,59,*:*]+img[*:*,60,*:*]+img[*:*,61,*:*]+img[*:*,62,*:*]+img[*:*,63,*:*]+img[*:*,64,*:*]+img[*:*,65,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 208:214, *:*]
+SELECT img[*:*,208,*:*]+img[*:*,209,*:*]+img[*:*,210,*:*]+img[*:*,211,*:*]+img[*:*,212,*:*]+img[*:*,213,*:*]+img[*:*,214,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 1:7, *:*]
+SELECT img[*:*,1,*:*]+img[*:*,2,*:*]+img[*:*,3,*:*]+img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 4:10, *:*]
+SELECT img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]+img[*:*,10,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 5:11, *:*]
+SELECT img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]+img[*:*,10,*:*]+img[*:*,11,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 98:104, *:*]
+SELECT img[*:*,98,*:*]+img[*:*,99,*:*]+img[*:*,100,*:*]+img[*:*,101,*:*]+img[*:*,102,*:*]+img[*:*,103,*:*]+img[*:*,104,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 74:80, *:*]
+SELECT img[*:*,74,*:*]+img[*:*,75,*:*]+img[*:*,76,*:*]+img[*:*,77,*:*]+img[*:*,78,*:*]+img[*:*,79,*:*]+img[*:*,80,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 49:55, *:*]
+SELECT img[*:*,49,*:*]+img[*:*,50,*:*]+img[*:*,51,*:*]+img[*:*,52,*:*]+img[*:*,53,*:*]+img[*:*,54,*:*]+img[*:*,55,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 177:183, *:*]
+SELECT img[*:*,177,*:*]+img[*:*,178,*:*]+img[*:*,179,*:*]+img[*:*,180,*:*]+img[*:*,181,*:*]+img[*:*,182,*:*]+img[*:*,183,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 146:152, *:*]
+SELECT img[*:*,146,*:*]+img[*:*,147,*:*]+img[*:*,148,*:*]+img[*:*,149,*:*]+img[*:*,150,*:*]+img[*:*,151,*:*]+img[*:*,152,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 105:111, *:*]
+SELECT img[*:*,105,*:*]+img[*:*,106,*:*]+img[*:*,107,*:*]+img[*:*,108,*:*]+img[*:*,109,*:*]+img[*:*,110,*:*]+img[*:*,111,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 46:52, *:*]
+SELECT img[*:*,46,*:*]+img[*:*,47,*:*]+img[*:*,48,*:*]+img[*:*,49,*:*]+img[*:*,50,*:*]+img[*:*,51,*:*]+img[*:*,52,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 56:62, *:*]
+SELECT img[*:*,56,*:*]+img[*:*,57,*:*]+img[*:*,58,*:*]+img[*:*,59,*:*]+img[*:*,60,*:*]+img[*:*,61,*:*]+img[*:*,62,*:*]
+FROM comp_cubed_64 as img
+// ["y"] comp_cubed_64 [*:*, 154:160, *:*]
+SELECT img[*:*,154,*:*]+img[*:*,155,*:*]+img[*:*,156,*:*]+img[*:*,157,*:*]+img[*:*,158,*:*]+img[*:*,159,*:*]+img[*:*,160,*:*]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 127:133]
+SELECT img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 79:85]
+SELECT img[*:*,*:*,79]+img[*:*,*:*,80]+img[*:*,*:*,81]+img[*:*,*:*,82]+img[*:*,*:*,83]+img[*:*,*:*,84]+img[*:*,*:*,85]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 134:140]
+SELECT img[*:*,*:*,134]+img[*:*,*:*,135]+img[*:*,*:*,136]+img[*:*,*:*,137]+img[*:*,*:*,138]+img[*:*,*:*,139]+img[*:*,*:*,140]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 12:18]
+SELECT img[*:*,*:*,12]+img[*:*,*:*,13]+img[*:*,*:*,14]+img[*:*,*:*,15]+img[*:*,*:*,16]+img[*:*,*:*,17]+img[*:*,*:*,18]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 142:148]
+SELECT img[*:*,*:*,142]+img[*:*,*:*,143]+img[*:*,*:*,144]+img[*:*,*:*,145]+img[*:*,*:*,146]+img[*:*,*:*,147]+img[*:*,*:*,148]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 128:134]
+SELECT img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]+img[*:*,*:*,134]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 75:81]
+SELECT img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]+img[*:*,*:*,78]+img[*:*,*:*,79]+img[*:*,*:*,80]+img[*:*,*:*,81]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 118:124]
+SELECT img[*:*,*:*,118]+img[*:*,*:*,119]+img[*:*,*:*,120]+img[*:*,*:*,121]+img[*:*,*:*,122]+img[*:*,*:*,123]+img[*:*,*:*,124]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 87:93]
+SELECT img[*:*,*:*,87]+img[*:*,*:*,88]+img[*:*,*:*,89]+img[*:*,*:*,90]+img[*:*,*:*,91]+img[*:*,*:*,92]+img[*:*,*:*,93]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 23:29]
+SELECT img[*:*,*:*,23]+img[*:*,*:*,24]+img[*:*,*:*,25]+img[*:*,*:*,26]+img[*:*,*:*,27]+img[*:*,*:*,28]+img[*:*,*:*,29]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 69:75]
+SELECT img[*:*,*:*,69]+img[*:*,*:*,70]+img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]+img[*:*,*:*,74]+img[*:*,*:*,75]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 146:152]
+SELECT img[*:*,*:*,146]+img[*:*,*:*,147]+img[*:*,*:*,148]+img[*:*,*:*,149]+img[*:*,*:*,150]+img[*:*,*:*,151]+img[*:*,*:*,152]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 99:105]
+SELECT img[*:*,*:*,99]+img[*:*,*:*,100]+img[*:*,*:*,101]+img[*:*,*:*,102]+img[*:*,*:*,103]+img[*:*,*:*,104]+img[*:*,*:*,105]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 135:141]
+SELECT img[*:*,*:*,135]+img[*:*,*:*,136]+img[*:*,*:*,137]+img[*:*,*:*,138]+img[*:*,*:*,139]+img[*:*,*:*,140]+img[*:*,*:*,141]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 76:82]
+SELECT img[*:*,*:*,76]+img[*:*,*:*,77]+img[*:*,*:*,78]+img[*:*,*:*,79]+img[*:*,*:*,80]+img[*:*,*:*,81]+img[*:*,*:*,82]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 26:32]
+SELECT img[*:*,*:*,26]+img[*:*,*:*,27]+img[*:*,*:*,28]+img[*:*,*:*,29]+img[*:*,*:*,30]+img[*:*,*:*,31]+img[*:*,*:*,32]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 56:62]
+SELECT img[*:*,*:*,56]+img[*:*,*:*,57]+img[*:*,*:*,58]+img[*:*,*:*,59]+img[*:*,*:*,60]+img[*:*,*:*,61]+img[*:*,*:*,62]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 94:100]
+SELECT img[*:*,*:*,94]+img[*:*,*:*,95]+img[*:*,*:*,96]+img[*:*,*:*,97]+img[*:*,*:*,98]+img[*:*,*:*,99]+img[*:*,*:*,100]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 13:19]
+SELECT img[*:*,*:*,13]+img[*:*,*:*,14]+img[*:*,*:*,15]+img[*:*,*:*,16]+img[*:*,*:*,17]+img[*:*,*:*,18]+img[*:*,*:*,19]
+FROM comp_cubed_64 as img
+// ["z"] comp_cubed_64 [*:*, *:*, 22:28]
+SELECT img[*:*,*:*,22]+img[*:*,*:*,23]+img[*:*,*:*,24]+img[*:*,*:*,25]+img[*:*,*:*,26]+img[*:*,*:*,27]+img[*:*,*:*,28]
+FROM comp_cubed_64 as img
diff --git a/rasodmg/test/croll_sliced.ql b/rasodmg/test/croll_sliced.ql
new file mode 100644
index 0000000..90ab35c
--- /dev/null
+++ b/rasodmg/test/croll_sliced.ql
@@ -0,0 +1,180 @@
+// ["x"] comp_sliced [2:8,*:*,*:*]
+SELECT img[2,*:*,*:*]+img[3,*:*,*:*]+img[4,*:*,*:*]+img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]+img[8,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [86:92,*:*,*:*]
+SELECT img[86,*:*,*:*]+img[87,*:*,*:*]+img[88,*:*,*:*]+img[89,*:*,*:*]+img[90,*:*,*:*]+img[91,*:*,*:*]+img[92,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [2:8,*:*,*:*]
+SELECT img[2,*:*,*:*]+img[3,*:*,*:*]+img[4,*:*,*:*]+img[5,*:*,*:*]+img[6,*:*,*:*]+img[7,*:*,*:*]+img[8,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [104:110,*:*,*:*]
+SELECT img[104,*:*,*:*]+img[105,*:*,*:*]+img[106,*:*,*:*]+img[107,*:*,*:*]+img[108,*:*,*:*]+img[109,*:*,*:*]+img[110,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [236:242,*:*,*:*]
+SELECT img[236,*:*,*:*]+img[237,*:*,*:*]+img[238,*:*,*:*]+img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [145:151,*:*,*:*]
+SELECT img[145,*:*,*:*]+img[146,*:*,*:*]+img[147,*:*,*:*]+img[148,*:*,*:*]+img[149,*:*,*:*]+img[150,*:*,*:*]+img[151,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [242:248,*:*,*:*]
+SELECT img[242,*:*,*:*]+img[243,*:*,*:*]+img[244,*:*,*:*]+img[245,*:*,*:*]+img[246,*:*,*:*]+img[247,*:*,*:*]+img[248,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [236:242,*:*,*:*]
+SELECT img[236,*:*,*:*]+img[237,*:*,*:*]+img[238,*:*,*:*]+img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [246:252,*:*,*:*]
+SELECT img[246,*:*,*:*]+img[247,*:*,*:*]+img[248,*:*,*:*]+img[249,*:*,*:*]+img[250,*:*,*:*]+img[251,*:*,*:*]+img[252,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [189:195,*:*,*:*]
+SELECT img[189,*:*,*:*]+img[190,*:*,*:*]+img[191,*:*,*:*]+img[192,*:*,*:*]+img[193,*:*,*:*]+img[194,*:*,*:*]+img[195,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [136:142,*:*,*:*]
+SELECT img[136,*:*,*:*]+img[137,*:*,*:*]+img[138,*:*,*:*]+img[139,*:*,*:*]+img[140,*:*,*:*]+img[141,*:*,*:*]+img[142,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [100:106,*:*,*:*]
+SELECT img[100,*:*,*:*]+img[101,*:*,*:*]+img[102,*:*,*:*]+img[103,*:*,*:*]+img[104,*:*,*:*]+img[105,*:*,*:*]+img[106,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [49:55,*:*,*:*]
+SELECT img[49,*:*,*:*]+img[50,*:*,*:*]+img[51,*:*,*:*]+img[52,*:*,*:*]+img[53,*:*,*:*]+img[54,*:*,*:*]+img[55,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [101:107,*:*,*:*]
+SELECT img[101,*:*,*:*]+img[102,*:*,*:*]+img[103,*:*,*:*]+img[104,*:*,*:*]+img[105,*:*,*:*]+img[106,*:*,*:*]+img[107,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [238:244,*:*,*:*]
+SELECT img[238,*:*,*:*]+img[239,*:*,*:*]+img[240,*:*,*:*]+img[241,*:*,*:*]+img[242,*:*,*:*]+img[243,*:*,*:*]+img[244,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [56:62,*:*,*:*]
+SELECT img[56,*:*,*:*]+img[57,*:*,*:*]+img[58,*:*,*:*]+img[59,*:*,*:*]+img[60,*:*,*:*]+img[61,*:*,*:*]+img[62,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [57:63,*:*,*:*]
+SELECT img[57,*:*,*:*]+img[58,*:*,*:*]+img[59,*:*,*:*]+img[60,*:*,*:*]+img[61,*:*,*:*]+img[62,*:*,*:*]+img[63,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [146:152,*:*,*:*]
+SELECT img[146,*:*,*:*]+img[147,*:*,*:*]+img[148,*:*,*:*]+img[149,*:*,*:*]+img[150,*:*,*:*]+img[151,*:*,*:*]+img[152,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [212:218,*:*,*:*]
+SELECT img[212,*:*,*:*]+img[213,*:*,*:*]+img[214,*:*,*:*]+img[215,*:*,*:*]+img[216,*:*,*:*]+img[217,*:*,*:*]+img[218,*:*,*:*]
+FROM comp_sliced as img
+// ["x"] comp_sliced [172:178,*:*,*:*]
+SELECT img[172,*:*,*:*]+img[173,*:*,*:*]+img[174,*:*,*:*]+img[175,*:*,*:*]+img[176,*:*,*:*]+img[177,*:*,*:*]+img[178,*:*,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 57:63, *:*]
+SELECT img[*:*,57,*:*]+img[*:*,58,*:*]+img[*:*,59,*:*]+img[*:*,60,*:*]+img[*:*,61,*:*]+img[*:*,62,*:*]+img[*:*,63,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 225:231, *:*]
+SELECT img[*:*,225,*:*]+img[*:*,226,*:*]+img[*:*,227,*:*]+img[*:*,228,*:*]+img[*:*,229,*:*]+img[*:*,230,*:*]+img[*:*,231,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 96:102, *:*]
+SELECT img[*:*,96,*:*]+img[*:*,97,*:*]+img[*:*,98,*:*]+img[*:*,99,*:*]+img[*:*,100,*:*]+img[*:*,101,*:*]+img[*:*,102,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 3:9, *:*]
+SELECT img[*:*,3,*:*]+img[*:*,4,*:*]+img[*:*,5,*:*]+img[*:*,6,*:*]+img[*:*,7,*:*]+img[*:*,8,*:*]+img[*:*,9,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 60:66, *:*]
+SELECT img[*:*,60,*:*]+img[*:*,61,*:*]+img[*:*,62,*:*]+img[*:*,63,*:*]+img[*:*,64,*:*]+img[*:*,65,*:*]+img[*:*,66,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 133:139, *:*]
+SELECT img[*:*,133,*:*]+img[*:*,134,*:*]+img[*:*,135,*:*]+img[*:*,136,*:*]+img[*:*,137,*:*]+img[*:*,138,*:*]+img[*:*,139,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 62:68, *:*]
+SELECT img[*:*,62,*:*]+img[*:*,63,*:*]+img[*:*,64,*:*]+img[*:*,65,*:*]+img[*:*,66,*:*]+img[*:*,67,*:*]+img[*:*,68,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 112:118, *:*]
+SELECT img[*:*,112,*:*]+img[*:*,113,*:*]+img[*:*,114,*:*]+img[*:*,115,*:*]+img[*:*,116,*:*]+img[*:*,117,*:*]+img[*:*,118,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 206:212, *:*]
+SELECT img[*:*,206,*:*]+img[*:*,207,*:*]+img[*:*,208,*:*]+img[*:*,209,*:*]+img[*:*,210,*:*]+img[*:*,211,*:*]+img[*:*,212,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 136:142, *:*]
+SELECT img[*:*,136,*:*]+img[*:*,137,*:*]+img[*:*,138,*:*]+img[*:*,139,*:*]+img[*:*,140,*:*]+img[*:*,141,*:*]+img[*:*,142,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 22:28, *:*]
+SELECT img[*:*,22,*:*]+img[*:*,23,*:*]+img[*:*,24,*:*]+img[*:*,25,*:*]+img[*:*,26,*:*]+img[*:*,27,*:*]+img[*:*,28,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 121:127, *:*]
+SELECT img[*:*,121,*:*]+img[*:*,122,*:*]+img[*:*,123,*:*]+img[*:*,124,*:*]+img[*:*,125,*:*]+img[*:*,126,*:*]+img[*:*,127,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 42:48, *:*]
+SELECT img[*:*,42,*:*]+img[*:*,43,*:*]+img[*:*,44,*:*]+img[*:*,45,*:*]+img[*:*,46,*:*]+img[*:*,47,*:*]+img[*:*,48,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 110:116, *:*]
+SELECT img[*:*,110,*:*]+img[*:*,111,*:*]+img[*:*,112,*:*]+img[*:*,113,*:*]+img[*:*,114,*:*]+img[*:*,115,*:*]+img[*:*,116,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 75:81, *:*]
+SELECT img[*:*,75,*:*]+img[*:*,76,*:*]+img[*:*,77,*:*]+img[*:*,78,*:*]+img[*:*,79,*:*]+img[*:*,80,*:*]+img[*:*,81,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 162:168, *:*]
+SELECT img[*:*,162,*:*]+img[*:*,163,*:*]+img[*:*,164,*:*]+img[*:*,165,*:*]+img[*:*,166,*:*]+img[*:*,167,*:*]+img[*:*,168,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 80:86, *:*]
+SELECT img[*:*,80,*:*]+img[*:*,81,*:*]+img[*:*,82,*:*]+img[*:*,83,*:*]+img[*:*,84,*:*]+img[*:*,85,*:*]+img[*:*,86,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 50:56, *:*]
+SELECT img[*:*,50,*:*]+img[*:*,51,*:*]+img[*:*,52,*:*]+img[*:*,53,*:*]+img[*:*,54,*:*]+img[*:*,55,*:*]+img[*:*,56,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 174:180, *:*]
+SELECT img[*:*,174,*:*]+img[*:*,175,*:*]+img[*:*,176,*:*]+img[*:*,177,*:*]+img[*:*,178,*:*]+img[*:*,179,*:*]+img[*:*,180,*:*]
+FROM comp_sliced as img
+// ["y"] comp_sliced [*:*, 33:39, *:*]
+SELECT img[*:*,33,*:*]+img[*:*,34,*:*]+img[*:*,35,*:*]+img[*:*,36,*:*]+img[*:*,37,*:*]+img[*:*,38,*:*]+img[*:*,39,*:*]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 125:131]
+SELECT img[*:*,*:*,125]+img[*:*,*:*,126]+img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 99:105]
+SELECT img[*:*,*:*,99]+img[*:*,*:*,100]+img[*:*,*:*,101]+img[*:*,*:*,102]+img[*:*,*:*,103]+img[*:*,*:*,104]+img[*:*,*:*,105]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 138:144]
+SELECT img[*:*,*:*,138]+img[*:*,*:*,139]+img[*:*,*:*,140]+img[*:*,*:*,141]+img[*:*,*:*,142]+img[*:*,*:*,143]+img[*:*,*:*,144]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 102:108]
+SELECT img[*:*,*:*,102]+img[*:*,*:*,103]+img[*:*,*:*,104]+img[*:*,*:*,105]+img[*:*,*:*,106]+img[*:*,*:*,107]+img[*:*,*:*,108]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 89:95]
+SELECT img[*:*,*:*,89]+img[*:*,*:*,90]+img[*:*,*:*,91]+img[*:*,*:*,92]+img[*:*,*:*,93]+img[*:*,*:*,94]+img[*:*,*:*,95]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 106:112]
+SELECT img[*:*,*:*,106]+img[*:*,*:*,107]+img[*:*,*:*,108]+img[*:*,*:*,109]+img[*:*,*:*,110]+img[*:*,*:*,111]+img[*:*,*:*,112]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 38:44]
+SELECT img[*:*,*:*,38]+img[*:*,*:*,39]+img[*:*,*:*,40]+img[*:*,*:*,41]+img[*:*,*:*,42]+img[*:*,*:*,43]+img[*:*,*:*,44]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 11:17]
+SELECT img[*:*,*:*,11]+img[*:*,*:*,12]+img[*:*,*:*,13]+img[*:*,*:*,14]+img[*:*,*:*,15]+img[*:*,*:*,16]+img[*:*,*:*,17]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 112:118]
+SELECT img[*:*,*:*,112]+img[*:*,*:*,113]+img[*:*,*:*,114]+img[*:*,*:*,115]+img[*:*,*:*,116]+img[*:*,*:*,117]+img[*:*,*:*,118]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 127:133]
+SELECT img[*:*,*:*,127]+img[*:*,*:*,128]+img[*:*,*:*,129]+img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 71:77]
+SELECT img[*:*,*:*,71]+img[*:*,*:*,72]+img[*:*,*:*,73]+img[*:*,*:*,74]+img[*:*,*:*,75]+img[*:*,*:*,76]+img[*:*,*:*,77]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 57:63]
+SELECT img[*:*,*:*,57]+img[*:*,*:*,58]+img[*:*,*:*,59]+img[*:*,*:*,60]+img[*:*,*:*,61]+img[*:*,*:*,62]+img[*:*,*:*,63]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 144:150]
+SELECT img[*:*,*:*,144]+img[*:*,*:*,145]+img[*:*,*:*,146]+img[*:*,*:*,147]+img[*:*,*:*,148]+img[*:*,*:*,149]+img[*:*,*:*,150]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 130:136]
+SELECT img[*:*,*:*,130]+img[*:*,*:*,131]+img[*:*,*:*,132]+img[*:*,*:*,133]+img[*:*,*:*,134]+img[*:*,*:*,135]+img[*:*,*:*,136]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 101:107]
+SELECT img[*:*,*:*,101]+img[*:*,*:*,102]+img[*:*,*:*,103]+img[*:*,*:*,104]+img[*:*,*:*,105]+img[*:*,*:*,106]+img[*:*,*:*,107]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 104:110]
+SELECT img[*:*,*:*,104]+img[*:*,*:*,105]+img[*:*,*:*,106]+img[*:*,*:*,107]+img[*:*,*:*,108]+img[*:*,*:*,109]+img[*:*,*:*,110]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 116:122]
+SELECT img[*:*,*:*,116]+img[*:*,*:*,117]+img[*:*,*:*,118]+img[*:*,*:*,119]+img[*:*,*:*,120]+img[*:*,*:*,121]+img[*:*,*:*,122]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 12:18]
+SELECT img[*:*,*:*,12]+img[*:*,*:*,13]+img[*:*,*:*,14]+img[*:*,*:*,15]+img[*:*,*:*,16]+img[*:*,*:*,17]+img[*:*,*:*,18]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 86:92]
+SELECT img[*:*,*:*,86]+img[*:*,*:*,87]+img[*:*,*:*,88]+img[*:*,*:*,89]+img[*:*,*:*,90]+img[*:*,*:*,91]+img[*:*,*:*,92]
+FROM comp_sliced as img
+// ["z"] comp_sliced [*:*, *:*, 44:50]
+SELECT img[*:*,*:*,44]+img[*:*,*:*,45]+img[*:*,*:*,46]+img[*:*,*:*,47]+img[*:*,*:*,48]+img[*:*,*:*,49]+img[*:*,*:*,50]
+FROM comp_sliced as img
diff --git a/rasodmg/test/csel_16.ql b/rasodmg/test/csel_16.ql
new file mode 100644
index 0000000..95399ed
--- /dev/null
+++ b/rasodmg/test/csel_16.ql
@@ -0,0 +1,43 @@
+// This query tests different selectivities a query box starting at
+// the origin on comp_cubed_16.
+
+// [0.5] cubed_16, selectivity 0,5%
+
+select img[0:44,0:44,0:26]
+from comp_cubed_16 as img
+
+// [1] cubed_16, selectivity 1%
+
+select img[0:55,0:55,0:33]
+from comp_cubed_16 as img
+
+// [2] cubed_16, selectivity 2%
+
+select img[0:69,0:69,0:42]
+from comp_cubed_16 as img
+
+// [5] cubed_16, selectivity 5%
+
+select img[0:94,0:94,0:56]
+from comp_cubed_16 as img
+
+// [10] cubed_16, selectivity 10%
+
+select img[0:118,0:118,0:71]
+from comp_cubed_16 as img
+
+// [20] cubed_16, selectivity 0%
+
+select img[0:149,0:149,0:89]
+from comp_cubed_16 as img
+
+// [50] cubed_16, selectivity 50%
+
+select img[0:202,0:202,0:121]
+from comp_cubed_16 as img
+
+// [100] cubed_16, selectivity 100%
+
+select img[0:255,0:255,0:153]
+from comp_cubed_16 as img
+
diff --git a/rasodmg/test/csel_32.ql b/rasodmg/test/csel_32.ql
new file mode 100644
index 0000000..aa3466c
--- /dev/null
+++ b/rasodmg/test/csel_32.ql
@@ -0,0 +1,43 @@
+// This query tests different selectivities a query box starting at
+// the origin on comp_cubed.
+
+// [0.5] cubed, selectivity 0,5%
+
+select img[0:44,0:44,0:26]
+from comp_cubed as img
+
+// [1] cubed, selectivity 1%
+
+select img[0:55,0:55,0:33]
+from comp_cubed as img
+
+// [2] cubed, selectivity 2%
+
+select img[0:69,0:69,0:42]
+from comp_cubed as img
+
+// [5] cubed, selectivity 5%
+
+select img[0:94,0:94,0:56]
+from comp_cubed as img
+
+// [10] cubed, selectivity 10%
+
+select img[0:118,0:118,0:71]
+from comp_cubed as img
+
+// [20] cubed, selectivity 0%
+
+select img[0:149,0:149,0:89]
+from comp_cubed as img
+
+// [50] cubed, selectivity 50%
+
+select img[0:202,0:202,0:121]
+from comp_cubed as img
+
+// [100] cubed, selectivity 100%
+
+select img[0:255,0:255,0:153]
+from comp_cubed as img
+
diff --git a/rasodmg/test/csel_64.ql b/rasodmg/test/csel_64.ql
new file mode 100644
index 0000000..c81079b
--- /dev/null
+++ b/rasodmg/test/csel_64.ql
@@ -0,0 +1,43 @@
+// This query tests different selectivities a query box starting at
+// the origin on comp_cubed_64.
+
+// [0.5] cubed_64, selectivity 0,5%
+
+select img[0:44,0:44,0:26]
+from comp_cubed_64 as img
+
+// [1] cubed_64, selectivity 1%
+
+select img[0:55,0:55,0:33]
+from comp_cubed_64 as img
+
+// [2] cubed_64, selectivity 2%
+
+select img[0:69,0:69,0:42]
+from comp_cubed_64 as img
+
+// [5] cubed_64, selectivity 5%
+
+select img[0:94,0:94,0:56]
+from comp_cubed_64 as img
+
+// [10] cubed_64, selectivity 10%
+
+select img[0:118,0:118,0:71]
+from comp_cubed_64 as img
+
+// [20] cubed_64, selectivity 0%
+
+select img[0:149,0:149,0:89]
+from comp_cubed_64 as img
+
+// [50] cubed_64, selectivity 50%
+
+select img[0:202,0:202,0:121]
+from comp_cubed_64 as img
+
+// [100] cubed_64, selectivity 100%
+
+select img[0:255,0:255,0:153]
+from comp_cubed_64 as img
+
diff --git a/rasodmg/test/csel_sliced.ql b/rasodmg/test/csel_sliced.ql
new file mode 100644
index 0000000..f3d9a0b
--- /dev/null
+++ b/rasodmg/test/csel_sliced.ql
@@ -0,0 +1,43 @@
+// This query tests different selectivities a query box starting at
+// the origin on comp_sliced.
+
+// [0.5] sliced, selectivity 0,5%
+
+select img[0:44,0:44,0:26]
+from comp_sliced as img
+
+// [1] sliced, selectivity 1%
+
+select img[0:55,0:55,0:33]
+from comp_sliced as img
+
+// [2] sliced, selectivity 2%
+
+select img[0:69,0:69,0:42]
+from comp_sliced as img
+
+// [5] sliced, selectivity 5%
+
+select img[0:94,0:94,0:56]
+from comp_sliced as img
+
+// [10] sliced, selectivity 10%
+
+select img[0:118,0:118,0:71]
+from comp_sliced as img
+
+// [20] sliced, selectivity 0%
+
+select img[0:149,0:149,0:89]
+from comp_sliced as img
+
+// [50] sliced, selectivity 50%
+
+select img[0:202,0:202,0:121]
+from comp_sliced as img
+
+// [100] sliced, selectivity 100%
+
+select img[0:255,0:255,0:153]
+from comp_sliced as img
+
diff --git a/rasodmg/test/defconv.cc b/rasodmg/test/defconv.cc
new file mode 100644
index 0000000..feee2dc
--- /dev/null
+++ b/rasodmg/test/defconv.cc
@@ -0,0 +1,598 @@
+/*
+* 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>.
+/
+/**
+ * defconv.cc
+ *
+ * Covert the DEF source file to another DEF destination file.
+ * Returns 0 for succes, otherwise 1.
+ *
+ * Parameters:
+ *
+ * --inputfilename <src-file>
+ * the filename of the src file, mandatory
+ * --outputfilename <dest-file>
+ * the filename of the dest file, mandatory
+ *
+ * --inputformat name
+ * name of DEF fromat(see data_foramat from mddtypes.hh)
+ * --inputformatparams params
+ * params used by convertFrom methods(see the heder file for you DEF from conversion)
+ * --outputformat name
+ * name of DEF fromat(see data_foramat from mddtypes.hh)
+ * --outputformatparams params
+ * params used by convertFrom methods(see the heder file for you DEF from conversion)
+ *
+ * --help
+ * print usage and exit
+ */
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#ifdef __GNUG__
+#include "raslib/template_inst.hh"
+#endif
+#endif
+
+#include "defutil.hh"
+#include "raslib/miter.hh"
+
+//program data
+const char* paramPrgHelp="--help";
+bool defPrgHelp=false;
+char* prgHelp=NULL;
+
+const char* paramSrcFileName="--srcfilename";
+bool defSrcFileName=false;
+char* srcFileName=NULL;
+
+const char* paramSrcFormat="--srcformat";
+bool defSrcFormat=false;
+char* srcFormatc=NULL;
+r_Data_Format srcFormat=r_Array;
+char *srcIvc=NULL, *srcTypec=NULL;
+r_Minterval srcIv;
+r_Type* srcType=NULL;
+
+const char* paramSrcFormatParams="--srcformatparams";
+bool defSrcFormatParams=false;
+char *srcFormatParams=NULL;
+
+const char* paramDestFileName="--destfilename";
+bool defDestFileName=false;
+char *destFileName=NULL;
+
+const char* paramDestFormat="--destformat";
+bool defDestFormat=false;
+char* destFormatc=NULL;
+r_Data_Format destFormat=r_Array;
+char *destIvc=NULL, *destTypec=NULL;
+r_Minterval destIv;
+r_Type* destType=NULL;
+
+const char* paramDestFormatParams="--destformatparams";
+bool defDestFormatParams=false;
+char *destFormatParams=NULL;
+
+//data used to parase formatparams for format Array
+const char* fpDomain="domain";
+const char* fpType="type";
+
+//structures used for parseParam
+const int paramsNo=7;
+
+const char *paramsName[paramsNo]={ paramPrgHelp, paramSrcFileName, paramSrcFormat, paramSrcFormatParams,
+ paramDestFileName, paramDestFormat, paramDestFormatParams};
+
+bool *paramsPresent[paramsNo]={ &defPrgHelp, &defSrcFileName, &defSrcFormat, &defSrcFormatParams,
+ &defDestFileName, &defDestFormat, &defDestFormatParams};
+
+char **paramsValue[paramsNo]={ &prgHelp, &srcFileName, &srcFormatc, &srcFormatParams,
+ &destFileName, &destFormatc, &destFormatParams};
+
+void printStatus()
+{
+ cout << "defdiff parameters list:" << endl;
+ for (int i=0; i<paramsNo; i++)
+ cout << "--Name='" << paramsName[i]
+ << "' Present=" << ((*paramsPresent[i])? "true": "false")
+ << " Value='" << *paramsValue[i] << "'" << endl;
+}
+
+void printUsage()
+{
+ char* fileNameSrc="test.bmp";
+ char* fileNameDest="test.tiff";
+
+ cout << "defconv v 0.1 - RasDaMan Data Exchange Format Convertor Utility" << endl;
+ cout << "Description: Returns " << EXIT_SUCCESS << " for succes, otherwise " << EXIT_FAILURE << endl;
+ cout << "For " << paramSrcFormat << "/" << paramDestFormat << " Array you have to specify the "
+ << paramSrcFormatParams << "/" << paramDestFormatParams << " as following:" << endl;
+ cout << "\"" << fpDomain << "=<domain_str>," << fpType << "=<type_str>\" (e.g. \""
+ << fpDomain << "=\"[0:477,0:464]\"," << fpType << "=char\")" << endl;
+ cout << "Usage options:" << endl;
+ cout << " " << paramSrcFileName << " <src-file> ... the filename used as src mandatory" << endl;
+ cout << " " << paramSrcFormat << " name ... name of DEF fromat(see data_foramat from mddtypes.hh)," << endl;
+ cout << " default Array" << endl;
+ cout << " " << paramSrcFormatParams << " params ... params used by convertFrom methods(see the header file" << endl;
+ cout << " for you DEF from conversion), default NULL" << endl;
+ cout << " " << paramDestFileName << " <dest-file> ... the filename used as dest mandatory" << endl;
+ cout << " " << paramDestFormat << " name ... name of DEF fromat(see data_foramat from mddtypes.hh)," << endl;
+ cout << " default Array" << endl;
+ cout << " " << paramDestFormatParams << " params ... params used by convertFrom methods(see the header file" << endl;
+ cout << " for you DEF from conversion), default NULL" << endl;
+ cout << " " << paramPrgHelp << " ... this help" << endl;
+ cout << "For example:" << endl;
+ cout << "defconv " << paramSrcFileName << " " << fileNameSrc << " " << paramSrcFormat << " " << format_name_bmp <<" "
+ << paramDestFileName << " " << fileNameDest << " " << paramDestFormat <<" " << format_name_tiff << endl;
+ cout << "Report bugs to liviu.coman@active­knowledge.com" << endl;
+
+}
+
+int checkParam(int& paramIndex, char** param)
+{
+ int i=0;
+ while(i<paramsNo)
+ {
+ if(!strcmp(param[paramIndex], paramsName[i]))
+ break;
+ i++;
+ }
+
+ if(i==paramsNo)
+ {
+ cout << "checkParam(...) error processing parameters: parameter "
+ << param[paramIndex] << " is unknown!" << endl;
+ return EXIT_FAILURE;
+ }
+ if(*paramsPresent[i])
+ {
+ cout << "checkParam(...) error processing parameters: parameter "
+ << param[paramIndex] << " is present more than once!" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(paramsName[i]!=paramPrgHelp)
+ {
+ *paramsPresent[i]=true;
+ paramIndex++;
+ *paramsValue[i]=param[paramIndex];
+ }
+ else
+ *paramsPresent[i]=true;
+
+ return EXIT_SUCCESS;
+}
+
+int parseParams(int argc, char** argv)
+{
+ int argIndex=0;
+ if (argc==1)
+ {
+ cout << "parseParams(...) parameters " << paramSrcFileName << " <src-file> and "
+ << paramDestFileName << " <dest-file> are mandatatory!" << endl;
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ argIndex=1;
+ while(argIndex<argc)
+ {
+ if(checkParam(argIndex, argv)!=EXIT_SUCCESS)
+ break;
+ argIndex++;
+ }
+ if(argIndex<argc)
+ {
+ //error while parsing parameters
+ return EXIT_FAILURE;
+ }
+
+ //check rule
+ if((defSrcFileName && defDestFileName) || (defPrgHelp))
+ return EXIT_SUCCESS;
+ else
+ {
+ cout << "parseParams(...) parameters " << paramSrcFileName << " <src-file> and "
+ << paramDestFileName << " <dest-file> are mandatatory!" << endl;
+ return EXIT_FAILURE;
+ }
+ }
+}
+
+int validateParams()
+{
+
+ //check srcformat
+ if(defSrcFormat)
+ {
+ srcFormat = get_data_format_from_name(srcFormatc);
+ if((srcFormat!=r_Array) &&
+ (!r_Convertor_Factory::is_supported(srcFormat)))
+ {
+ cout << "convertDEFs(...) conversion " << srcFormatc << " not supported" << endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ //check destformat
+ if(defDestFormat)
+ {
+ destFormat = get_data_format_from_name(destFormatc);
+ if((destFormat!=r_Array) &&
+ (!r_Convertor_Factory::is_supported(destFormat)))
+ {
+ cout << "convertDEFs(...) conversion " << destFormatc << " not supported" << endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ //check srcFormatParams if srcFormat=r_Array
+ if(srcFormat == r_Array)
+ {
+ if(!defSrcFormatParams)
+ {
+ cout << "convertDEFs(...) for srcformat r_Array is necessary to provide the srcformatparams as described in help" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(parseArrayParams((const char*)srcFormatParams, fpDomain, fpType, srcIvc, srcTypec) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+
+ if(decodeMinterval(srcIvc, srcIv) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+
+ if(decodeType(srcTypec, srcType) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+ }
+
+ //check destFormatParams if destFormat=r_Array
+ if(destFormat == r_Array)
+ {
+ if(!defDestFormatParams)
+ {
+ cout << "convertDEFs(...) for destformat r_Array is necessary to provide the srcformatparams as described in help" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(parseArrayParams((const char*)destFormatParams, fpDomain, fpType, destIvc, destTypec) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+
+ if(decodeMinterval(destIvc, destIv) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+
+ if(decodeType(destTypec, destType) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+ }
+}
+
+int setCell(const char* srcCell,
+ const r_Type* srcType,
+ const r_Type* destType,
+ char* destCell,
+ bool rescale=false)
+{
+ r_Double srcTypeMin=0., srcTypeMax=0.;
+ r_Double destTypeMin=0., destTypeMax=0.;
+ r_Double srcVal=0., destVal=0.;
+
+ if(!srcCell)
+ {
+ cout << "setCell(...) srcCell is null" << endl;
+ return EXIT_FAILURE;
+ }
+ if(!srcType)
+ {
+ cout << "setCell(...) srcType is null" << endl;
+ return EXIT_FAILURE;
+ }
+ if(!destType)
+ {
+ cout << "setCell(...) destType is null" << endl;
+ return EXIT_FAILURE;
+ }
+ if(!destCell)
+ {
+ cout << "setCell(...) destCell is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ try
+ {
+ srcVal=((r_Primitive_Type*)srcType)->get_value(srcCell);
+ if(rescale)
+ {
+ ((r_Primitive_Type*)srcType)->get_limits(srcTypeMin, srcTypeMax);
+ ((r_Primitive_Type*)destType)->get_limits(destTypeMin, destTypeMax);
+ destVal=srcVal*destTypeMax/srcTypeMax;
+ }
+ else
+ destVal=srcVal;
+ ((r_Primitive_Type*)destType)->set_value(destCell,destVal);
+ }
+ catch(r_Error& err)
+ {
+ cout << "setCell(...) error while setting value to dest from src" << endl;
+ cout << "Error " << err.get_errorno() << " : " << err.what() << endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+int convertData(const r_convDesc& descSrc, r_convDesc& descDest)
+{
+ r_Minterval srcIv, destIv, commonIv;
+
+ r_Bytes srcTypeSize=0, destTypeSize=0;
+ char *srcBuffer=NULL, *destBuffer=NULL;
+
+ if(!descSrc.dest)
+ {
+ cout << "convertData(...) descSrc.dest is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(!descSrc.destType)
+ {
+ cout << "convertData(...) descSrc.destType is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(descDest.dest)
+ {
+ cout << "convertData(...) descDest.dest is not null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(!descDest.destType)
+ {
+ cout << "convertData(...) descDest.destType is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ //translate every interval to zero
+ try
+ {
+ srcIv=descSrc.destInterv.create_reverse_translation(descSrc.destInterv.get_origin());
+ destIv=descDest.destInterv.create_reverse_translation(descDest.destInterv.get_origin());
+ }
+ catch(r_Error& err)
+ {
+ cout << "convertData(...) error while translating to zero the following intervals:" << endl;
+ cout << "descSrc.destInterv=" << descSrc.destInterv << endl;
+ cout << "descDest.destInterv=" << descDest.destInterv << endl;
+ cout << "Error " << err.get_errorno() << ":" << err.what() << endl;
+ return EXIT_FAILURE;
+ }
+
+ //check intersection
+ try
+ {
+ commonIv.intersection_of(srcIv, destIv);
+ }
+ catch(r_Error& err)
+ {
+ cout << "convertData(...) error while doing the intersection of the following intervals:" << endl;
+ cout << "descSrc.destInterv=" << descSrc.destInterv << endl;
+ cout << "descDest.destInterv=" << descDest.destInterv << endl;
+ cout << "Error " << err.get_errorno() << ":" << err.what() << endl;
+ return EXIT_FAILURE;
+ }
+
+ //get type size
+ srcTypeSize=((r_Base_Type*)descSrc.destType)->size();
+ destTypeSize=((r_Base_Type*)descDest.destType)->size();
+
+ //allocate data
+ srcBuffer=new char[srcTypeSize];
+ if(!srcBuffer)
+ {
+ cout << "convertData(...) unable to claim memory for srcBuffer" << endl;
+ return EXIT_FAILURE;
+ }
+ destBuffer=new char[destTypeSize];
+ if(!destBuffer)
+ {
+ cout << "convertData(...) unable to claim memory for destBuffer" << endl;
+ delete[] srcBuffer;
+ srcBuffer=NULL;
+ return EXIT_FAILURE;
+ }
+ descDest.dest=new char[descDest.destInterv.cell_count()*destTypeSize];
+ if(!descDest.dest)
+ {
+ cout << "convertData(...) unable to claim memory for descDest.dest" << endl;
+ delete[] srcBuffer;
+ srcBuffer=NULL;
+ delete[] destBuffer;
+ destBuffer=NULL;
+ return EXIT_FAILURE;
+ }
+ memset(descDest.dest,0, descDest.destInterv.cell_count()*destTypeSize);
+
+ r_Miter srcIter( &commonIv, &srcIv, srcTypeSize, descSrc.dest );
+ r_Miter destIter( &commonIv, &destIv, destTypeSize, descDest.dest );
+ while(!srcIter.isDone() || !destIter.isDone())
+ {
+ memcpy(srcBuffer, srcIter.nextCell(), srcTypeSize);
+ if(setCell(srcBuffer, descSrc.destType, descDest.destType, destBuffer)!=EXIT_SUCCESS)
+ {
+ //abort algorithm
+ break;
+ }
+ memcpy(destIter.nextCell(), destBuffer, destTypeSize);
+ }
+
+ //clean up
+ delete[] srcBuffer;
+ srcBuffer=NULL;
+ delete[] destBuffer;
+ destBuffer=NULL;
+
+ //check algorithm
+ if(!srcIter.isDone() || !destIter.isDone())
+ {
+ cout << "convertData(...) error in algorithm" << endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+
+
+int convertDEFs()
+{
+ char *dataSrc=NULL, *dataDest=NULL;
+ r_ULong dataSrcSize=0, dataDestSize=0;
+ r_convDesc descSrc, descDest;
+
+ initConvDesc(descSrc);
+ initConvDesc(descDest);
+
+ //read the source file
+ if(readFile(srcFileName, &dataSrc, dataSrcSize)!=EXIT_SUCCESS)
+ return EXIT_FAILURE;
+
+ if(!dataSrcSize)
+ {
+ cout << "convertDEFs() size of file " << srcFileName << " is zero" << endl;
+ //clean up
+ delete [] dataSrc;
+ dataSrc=NULL;
+ return EXIT_FAILURE;
+ }
+
+ //what is the input format?
+ if(srcFormat !=r_Array)
+ {
+ //it is safe to use srcType, srcIv because the srcFormat is not r_Array
+ srcType=r_Convertor::get_external_type(r_Convertor::ctype_char);
+ srcIv = r_Minterval(1);
+ srcIv << r_Sinterval((r_Long)0, (r_Long)(dataSrcSize - 1));
+
+ //did conversion work?
+ if(convertFrom(srcFormat, srcFormatParams, dataSrc,
+ srcIv, srcType, descSrc) != EXIT_SUCCESS)
+ {
+ //clean up
+ delete [] dataSrc;
+ dataSrc=NULL;
+ return EXIT_FAILURE;
+ }
+ }
+ else
+ {
+ descSrc.dest=dataSrc;
+ descSrc.destInterv=srcIv;
+ descSrc.destType=srcType;
+ }
+
+ //what is the output format?
+ if(destFormat !=r_Array)
+ {
+ if(convertTo(destFormat, destFormatParams, descSrc.dest, descSrc.destInterv, descSrc.destType, descDest) != EXIT_SUCCESS)
+ {
+ //clean up
+ cleanConvDesc(descSrc);
+ return EXIT_FAILURE;
+ }
+ //prepare the data for writing
+ dataDest=descDest.dest;
+ dataDestSize=descDest.destInterv.cell_count() * ((r_Base_Type*)descDest.destType)->size();
+ }
+ else
+ {
+ //prepare for conversion
+ descDest.destType=destType;
+ descDest.destInterv=destIv;
+ descDest.dest=NULL;
+
+ if(descSrc.destType->isPrimitiveType())
+ {
+ if(convertData(descSrc, descDest) != EXIT_SUCCESS)
+ {
+ //clean up
+ cleanConvDesc(descSrc);
+ cleanConvDesc(descDest);
+ return EXIT_FAILURE;
+ }
+
+ //prepare the data for writing
+ dataDest=descDest.dest;
+ dataDestSize=descDest.destInterv.cell_count() * ((r_Base_Type*)descDest.destType)->size();
+ }
+ else
+ {
+ //we store the data as it is
+ dataDest=descSrc.dest;
+ dataDestSize=descSrc.destInterv.cell_count() * ((r_Base_Type*)descSrc.destType)->size();
+ }
+
+ }
+
+
+
+ //write data into destFileName
+ if(writeFile(destFileName, (const char**)&dataDest, dataDestSize)!=EXIT_SUCCESS)
+ {
+ //clean up
+ cleanConvDesc(descSrc);
+ cleanConvDesc(descDest);
+ return EXIT_FAILURE;
+ }
+
+ //clean up
+ cleanConvDesc(descSrc);
+ cleanConvDesc(descDest);
+
+ return EXIT_SUCCESS;
+}
+
+int processRequest()
+{
+ if(validateParams() != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+ return convertDEFs();
+}
+
+int main(int argc, char **argv)
+{
+ if(parseParams(argc, argv) != EXIT_SUCCESS)
+ {
+ printUsage();
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ if(!defPrgHelp)
+ {
+ printStatus();
+ return processRequest();
+ }
+ else
+ {
+ printUsage();
+ return EXIT_SUCCESS;
+ }
+ }
+}
diff --git a/rasodmg/test/defdiff.cc b/rasodmg/test/defdiff.cc
new file mode 100644
index 0000000..953435a
--- /dev/null
+++ b/rasodmg/test/defdiff.cc
@@ -0,0 +1,537 @@
+/*
+* 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>.
+/
+/*
+ * defdiff.cc
+ *
+ * Compare to DEF files and returns 0 for succes, otherwise 1
+ *
+ * Parameters:
+ *
+ * --inputfilename <src-file>
+ * the filename of the src file, mandatory
+ * --outputfilename <dest-file>
+ * the filename of the dest file, mandatory
+ *
+ * --inputformat name
+ * name of DEF fromat(see data_foramat from mddtypes.hh)
+ * --inputformatparams params
+ * params used by convertFrom methods(see the heder file for you DEF from conversion)
+ * --outputformat name
+ * name of DEF fromat(see data_foramat from mddtypes.hh)
+ * --outputformatparams params
+ * params used by convertFrom methods(see the heder file for you DEF from conversion)
+ *
+ * --help
+ * print usage and exit
+ */
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#ifdef __GNUG__
+#include "raslib/template_inst.hh"
+#endif
+#endif
+
+#include "defutil.hh"
+
+const char* diffFileName = "defdiff.tif";
+
+const char* paramPrgHelp="--help";
+bool defPrgHelp=false;
+char* prgHelp=NULL;
+
+const char* paramSrcFileName="--srcfilename";
+bool defSrcFileName=false;
+char* srcFileName=NULL;
+
+const char* paramSrcFormat="--srcformat";
+bool defSrcFormat=false;
+char* srcFormatc=NULL;
+r_Data_Format srcFormat=r_Array;
+
+const char* paramSrcFormatParams="--srcformatparams";
+bool defSrcFormatParams=false;
+char *srcFormatParams=NULL;
+
+const char* paramDestFileName="--destfilename";
+bool defDestFileName=false;
+char *destFileName=NULL;
+
+const char* paramDestFormat="--destformat";
+bool defDestFormat=false;
+char *destFormatc=NULL;
+r_Data_Format destFormat=r_Array;
+
+const char* paramDestFormatParams="--destformatparams";
+bool defDestFormatParams=false;
+char *destFormatParams=NULL;
+
+//structures used for parseParam
+const int paramsNo=7;
+
+const char *paramsName[paramsNo]={ paramPrgHelp, paramSrcFileName, paramSrcFormat, paramSrcFormatParams,
+ paramDestFileName, paramDestFormat, paramDestFormatParams};
+
+bool *paramsPresent[paramsNo]={ &defPrgHelp, &defSrcFileName, &defSrcFormat, &defSrcFormatParams,
+ &defDestFileName, &defDestFormat, &defDestFormatParams};
+
+char **paramsValue[paramsNo]={ &prgHelp, &srcFileName, &srcFormatc, &srcFormatParams,
+ &destFileName, &destFormatc, &destFormatParams};
+
+void printStatus()
+{
+ cout << "defdiff parameters list:" << endl;
+ for (int i=0; i<paramsNo; i++)
+ cout << "--Name='" << paramsName[i]
+ << "' Present=" << ((*paramsPresent[i])? "true": "false")
+ << " Value='" << (*paramsValue[i]?*paramsValue[i]: "null") << "'" << endl;
+}
+
+void printUsage()
+{
+ char* fileNameSrc="test.bmp";
+ char* fileNameDest="test.tiff";
+
+ cout << "defdiff v 0.1 - RasDaMan Data Exchange Format Difference Utility" << endl;
+ cout << "Description: Returns " << EXIT_SUCCESS << " for succes, otherwise " << EXIT_FAILURE << endl;
+ cout << "If it is possible it will create a tiff file with the difference, called " << diffFileName << endl;
+ cout << "Usage options:" << endl;
+ cout << " " << paramSrcFileName << " <src-file> ... the filename used as src mandatory" << endl;
+ cout << " " << paramSrcFormat << " name ... name of DEF fromat(see data_foramat from mddtypes.hh)," << endl;
+ cout << " default Array" << endl;
+ cout << " " << paramSrcFormatParams << " params ... params used by convertFrom methods(see the header file" << endl;
+ cout << " for you DEF from conversion), default NULL" << endl;
+ cout << " " << paramDestFileName << " <dest-file> ... the filename used as dest mandatory" << endl;
+ cout << " " << paramDestFormat << " name ... name of DEF fromat(see data_foramat from mddtypes.hh)," << endl;
+ cout << " default Array" << endl;
+ cout << " " << paramDestFormatParams << " params ... params used by convertFrom methods(see the header file" << endl;
+ cout << " for you DEF from conversion), default NULL" << endl;
+ cout << " " << paramPrgHelp << " ... this help" << endl;
+ cout << "For example:" << endl;
+ cout << "defdiff " << paramSrcFileName << " " << fileNameSrc << " " << paramSrcFormat << " " << format_name_bmp <<" "
+ << paramDestFileName << " " << fileNameDest << " " << paramDestFormat <<" " << format_name_tiff << endl;
+ cout << "Report bugs to liviu.coman@active­knowledge.com" << endl;
+
+}
+
+int checkParam(int& paramIndex, char** param)
+{
+ int i=0;
+ while(i<paramsNo)
+ {
+ if(!strcmp(param[paramIndex], paramsName[i]))
+ break;
+ i++;
+ }
+
+ if(i==paramsNo)
+ {
+ cout << "checkParam(...) error processing parameters: parameter "
+ << param[paramIndex] << " is unknown!" << endl;
+ return EXIT_FAILURE;
+ }
+ if(*paramsPresent[i])
+ {
+ cout << "checkParam(...) error processing parameters: parameter "
+ << param[paramIndex] << " is present more than once!" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(paramsName[i]!=paramPrgHelp)
+ {
+ *paramsPresent[i]=true;
+ paramIndex++;
+ *paramsValue[i]=param[paramIndex];
+ }
+ else
+ *paramsPresent[i]=true;
+
+ return EXIT_SUCCESS;
+}
+
+int parseParams(int argc, char** argv)
+{
+ int argIndex=0;
+ if (argc==1)
+ {
+ cout << "parseParams(...) parameters " << paramSrcFileName << " <src-file> and "
+ << paramDestFileName << " <dest-file> are mandatatory!" << endl;
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ argIndex=1;
+ while(argIndex<argc)
+ {
+ if(checkParam(argIndex, argv)!=EXIT_SUCCESS)
+ break;
+ argIndex++;
+ }
+ if(argIndex<argc)
+ return EXIT_FAILURE;
+
+ //check rule
+ if((defSrcFileName && defDestFileName) || (defPrgHelp))
+ return EXIT_SUCCESS;
+ else
+ {
+ cout << "parseParams(...) parameters " << paramSrcFileName << " <src-file> and "
+ << paramDestFileName << " <dest-file> are mandatatory!" << endl;
+ return EXIT_FAILURE;
+ }
+ }
+}
+
+int validateParams()
+{
+ if(defSrcFormat)
+ {
+ srcFormat = get_data_format_from_name(srcFormatc);
+ if((srcFormat!=r_Array) &&
+ (!r_Convertor_Factory::is_supported(srcFormat)))
+ {
+ cout << "validateParams() conversion of " << srcFormatc << " not supported" << endl;
+ return EXIT_FAILURE;
+ }
+ }
+ if(defDestFormat)
+ {
+ destFormat = get_data_format_from_name(destFormatc);
+ if((destFormat!=r_Array) &&
+ (!r_Convertor_Factory::is_supported(destFormat)))
+ {
+ cout << "validateParams() conversion " << destFormatc << " not supported" << endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
+
+int compareDEFs()
+{
+ char *dataSrc=NULL, *dataDest=NULL;
+ r_ULong dataSrcSize=0, dataDestSize=0;
+ r_ULong arraySrcSize=0, arrayDestSize=0;
+ r_Bytes basetypeSrcSize=0, basetypeDestSize=0;
+ r_convDesc descSrc, descDest;
+ r_Type::r_Type_Id basetypeSrcId=r_Type::UNKNOWNTYPE, basetypeDestId=r_Type::UNKNOWNTYPE;
+
+ //init conversion result data
+ initConvDesc(descSrc);
+ initConvDesc(descDest);
+
+ //read files
+ if(readFile(srcFileName, &dataSrc, dataSrcSize)!=EXIT_SUCCESS)
+ return EXIT_FAILURE;
+
+ if(readFile(destFileName, &dataDest, dataDestSize)!=EXIT_SUCCESS)
+ {
+ delete [] dataSrc;
+ dataSrc=NULL;
+ return EXIT_FAILURE;
+ }
+
+ //convert if necessary
+ if(srcFormat !=r_Array)
+ {
+ r_Minterval srcIv(1);
+ r_Type* srcType=NULL;
+
+ srcIv << r_Sinterval((r_Range)0, (r_Range)(dataSrcSize -1));
+ srcType=r_Convertor::get_external_type(r_Convertor::ctype_char);
+
+ if(convertFrom(srcFormat, srcFormatParams, dataSrc,
+ srcIv, srcType, descSrc) != EXIT_SUCCESS)
+ {
+ delete srcType;
+ srcType=NULL;
+ delete [] dataSrc;
+ dataSrc=NULL;
+ delete [] dataDest;
+ dataDest=NULL;
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ //we don't need this anymore
+ delete [] dataSrc;
+ dataSrc=NULL;
+ delete srcType;
+ srcType=NULL;
+ }
+ }
+
+ if(destFormat !=r_Array)
+ {
+ r_Minterval destIv(1);
+ r_Type* destType=NULL;
+
+ destIv << r_Sinterval((r_Range)0, (r_Range)(dataDestSize -1));
+ destType=r_Convertor::get_external_type(r_Convertor::ctype_char);
+
+ if(convertFrom(destFormat, destFormatParams, dataDest,
+ destIv, destType, descDest) != EXIT_SUCCESS)
+ {
+ delete destType;
+ destType=NULL;
+ delete [] dataDest;
+ dataDest=NULL;
+ if(srcFormat==r_Array)
+ {
+ delete [] dataSrc;
+ dataSrc=NULL;
+ }
+ else
+ {
+ dataSrc=NULL;
+ cleanConvDesc(descSrc);
+ }
+
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ //we don't need this anymore
+ delete [] dataDest;
+ dataDest=NULL;
+ delete destType;
+ destType=NULL;
+ }
+ }
+
+ //check domain
+ if((srcFormat!=r_Array) &&
+ (destFormat!=r_Array) &&
+ (descSrc.destInterv != descDest.destInterv))
+ {
+ cout << "compareDEFs() source domain " << descSrc.destInterv << " != destination domain " << descDest.destInterv << endl;
+ cleanConvDesc(descSrc);
+ cleanConvDesc(descDest);
+ return EXIT_FAILURE;
+ }
+
+ //check if celltype is a basetype
+ if((srcFormat!=r_Array) &&
+ (!descSrc.destType->isBaseType()))
+ {
+ cout << "compareDEFs() source type " << basetypeSrcId << " is not a base type" << endl;
+ if(destFormat==r_Array)
+ {
+ delete [] dataDest;
+ dataDest=NULL;
+ }
+ else
+ cleanConvDesc(descDest);
+ cleanConvDesc(descSrc);
+ return EXIT_FAILURE;
+ }
+
+ if((destFormat!=r_Array) &&
+ (!descDest.destType->isBaseType()))
+ {
+ cout << "compareDEFs() destination type " << basetypeDestId << " is not a base type" << endl;
+ if(srcFormat==r_Array)
+ {
+ delete [] dataSrc;
+ dataSrc=NULL;
+ }
+ else
+ cleanConvDesc(descSrc);
+ cleanConvDesc(descDest);
+ return EXIT_FAILURE;
+ }
+
+ //stoare info about types
+ if(srcFormat!=r_Array)
+ {
+ basetypeSrcId=descSrc.destType->type_id();
+ basetypeSrcSize=((r_Base_Type*)descSrc.destType)->size();
+ }
+ if(destFormat!=r_Array)
+ {
+ basetypeDestId=descDest.destType->type_id();
+ basetypeDestSize=((r_Base_Type*)descDest.destType)->size();
+ }
+
+ if((srcFormat!=r_Array) &&
+ (destFormat!=r_Array))
+ {
+ //FIXME basetypeSrcId!=basetypeDestId to powerfull
+ if(basetypeSrcId!=basetypeDestId)
+ cout << "compareDEFs() warning: source type " << basetypeSrcId
+ << " != destination type " << basetypeDestId << endl;
+
+ if(basetypeSrcSize!=basetypeDestSize)
+ {
+ cout << "comparetDEFs() source type " << descSrc.destType->name() << " != destination type " << descDest.destType->name() << endl;
+ cout << "source type size" << basetypeSrcSize << " != destination type size" << basetypeDestSize << endl;
+ cleanConvDesc(descSrc);
+ cleanConvDesc(descDest);
+ return EXIT_FAILURE;
+ }
+
+ if((basetypeSrcId == r_Type::STRUCTURETYPE) &&
+ (basetypeDestId == r_Type::STRUCTURETYPE) &&
+ (compareStructure((r_Structure_Type*)descSrc.destType, (r_Structure_Type*)descDest.destType) !=EXIT_SUCCESS))
+ {
+ cout << "compareDEFs() source structure type != destination structure type" << endl;
+ cout << "Source type is: " << (*(r_Structure_Type*)(descSrc.destType)) << endl;
+ cout << "Destination type is:" << (*(r_Structure_Type*)(descSrc.destType)) << endl;
+ cleanConvDesc(descSrc);
+ cleanConvDesc(descDest);
+ return EXIT_FAILURE;
+ }
+ }
+
+ if(srcFormat!=r_Array)
+ {
+ arraySrcSize=descSrc.destInterv.cell_count() * basetypeSrcSize;
+ dataSrc=descSrc.dest;
+ }
+ else
+ arraySrcSize=dataSrcSize;
+
+ if(destFormat!=r_Array)
+ {
+ arrayDestSize=descDest.destInterv.cell_count() * basetypeDestSize;
+ dataDest=descDest.dest;
+ }
+ else
+ arrayDestSize=dataDestSize;
+
+ if(arraySrcSize!=arrayDestSize)
+ {
+ cout << "compareDEFs() source data size " << arraySrcSize << " != " << " destination data size " << arrayDestSize << endl;
+ delete [] dataSrc;
+ dataSrc=NULL;
+ delete [] dataDest;
+ dataDest=NULL;
+ cleanConvDesc(descSrc);
+ cleanConvDesc(descDest);
+ return EXIT_FAILURE;
+ }
+
+ if(memcmp(dataSrc, dataDest, arraySrcSize))
+ {
+ cout << "compareDEFs() source and destination data are different" << endl;
+ r_convDesc descDiff;
+ r_ULong diffSize=0;
+ initConvDesc(descDiff);
+ //do diff
+ for(int i=0; i< arraySrcSize; i++)
+ dataDest[i]-=dataSrc[i];
+ if(convertTo(r_TIFF, NULL, dataDest, descDest.destInterv,
+ descDest.destType, descDiff) != EXIT_SUCCESS)
+ {
+ cout << "compareDEFs() error building the difference tiff file" << endl;;
+ }
+ else
+ {
+ diffSize=descDiff.destInterv.cell_count() * ((r_Base_Type*)descDiff.destType)->size();
+ if(writeFile(diffFileName, (const char**)&descDiff.dest, diffSize)!=EXIT_SUCCESS)
+ cout << "compareDEFs() error building the difference tiff file" << endl;;
+ cleanConvDesc(descDiff);
+ }
+
+ //clean up
+ if(srcFormat==r_Array)
+ {
+ delete [] dataSrc;
+ dataSrc=NULL;
+ }
+ else
+ {
+ dataSrc=NULL;
+ cleanConvDesc(descSrc);
+ }
+ if(destFormat==r_Array)
+ {
+ delete [] dataDest;
+ dataDest=NULL;
+ }
+ else
+ {
+ dataDest=NULL;
+ cleanConvDesc(descDest);
+ }
+ return EXIT_FAILURE;
+ }
+
+ cout << "compareDEFs() source and destination data are identic" << endl;
+
+ //clean up
+ if(srcFormat==r_Array)
+ {
+ delete [] dataSrc;
+ dataSrc=NULL;
+ }
+ else
+ {
+ dataSrc=NULL;
+ cleanConvDesc(descSrc);
+ }
+ if(destFormat==r_Array)
+ {
+ delete [] dataDest;
+ dataDest=NULL;
+ }
+ else
+ {
+ dataDest=NULL;
+ cleanConvDesc(descDest);
+ }
+
+ return EXIT_SUCCESS;
+}
+
+int processRequest()
+{
+ if(validateParams() != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+ return compareDEFs();
+}
+
+int main(int argc, char **argv)
+{
+ if(parseParams(argc, argv)!=EXIT_SUCCESS)
+ {
+ printUsage();
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ if(!defPrgHelp)
+ {
+#ifdef RMANDEBUG
+ printStatus();
+#endif
+ return processRequest();
+ }
+ else
+ {
+ printUsage();
+ return EXIT_SUCCESS;
+ }
+ }
+}
diff --git a/rasodmg/test/defutil.hh b/rasodmg/test/defutil.hh
new file mode 100644
index 0000000..b30a8a5
--- /dev/null
+++ b/rasodmg/test/defutil.hh
@@ -0,0 +1,412 @@
+/*
+* 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>.
+/
+/*
+ * defutil.hh
+ *
+ * COMMENTS
+ * Common functions used by defxxx programs
+*/
+
+
+#include <cstdio>
+#include <cstdlib>
+#include <iostream>
+using std::cout;
+using std::endl;
+
+#include "raslib/mddtypes.hh"
+#include "raslib/structuretype.hh"
+#include "raslib/odmgtypes.hh"
+#include "raslib/minterval.hh"
+#include "raslib/parseparams.hh"
+#include "conversion/convertor.hh"
+#include "conversion/convfactory.hh"
+
+//--I/O file
+int readFile(const char* fileName, char **data, r_ULong& dataSize)
+{
+ FILE *pFile=NULL;
+
+ if(fileName==NULL)
+ {
+ cout << "readFile(...) fileName is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(*data!=NULL)
+ {
+ cout << "readFile(...) data is not null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ pFile=fopen(fileName, "rb");
+ if(pFile==NULL)
+ {
+ cout << "readFile(...) unable to open file " << fileName << endl;
+ return EXIT_FAILURE;
+ }
+
+ fseek(pFile, 0, SEEK_END);
+ dataSize=ftell(pFile);
+
+ *data=new char[dataSize];
+ if(*data==NULL)
+ {
+ cout << "readFile(...) unable to claim memory for file " << fileName << endl;
+ fclose(pFile);
+ return EXIT_FAILURE;
+ }
+
+ fseek(pFile, 0, SEEK_SET);
+ fread(*data, 1, dataSize, pFile);
+
+ fclose(pFile);
+ return EXIT_SUCCESS;
+}
+
+int writeFile(const char* fileName, const char **data, r_ULong& dataSize)
+{
+ FILE *pFile=NULL;
+
+ if(fileName==NULL)
+ {
+ cout << "writeFile(...) fileName is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(*data==NULL)
+ {
+ cout << "writeFile(...) data is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(!dataSize)
+ {
+ cout << "writeFile(...) dataSize is zero" << endl;
+ return EXIT_FAILURE;
+ }
+
+ pFile=fopen(fileName, "wb");
+ if(pFile==NULL)
+ {
+ cout << "writeFile(...) unable to open file" << fileName << endl;
+ return EXIT_FAILURE;
+ }
+
+ fwrite(*data, 1, dataSize, pFile);
+
+ fclose(pFile);
+ pFile=NULL;
+
+ return EXIT_SUCCESS;
+}
+
+//ConvertFrom/To r_Array data
+int convertFrom(r_Data_Format fmt, const char* fmtParams,
+ const char* data, const r_Minterval& dataDom,
+ const r_Type* dataType, r_convDesc& desc)
+{
+ r_Storage_Man_CPP mySM;
+ r_Convertor *conv=NULL;
+
+ if(data==NULL)
+ {
+ cout << "convertFrom(...) data is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(dataType==NULL)
+ {
+ cout << "convertFrom(...) dataType is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ try
+ {
+ conv=r_Convertor_Factory::create(fmt, data, dataDom, dataType);
+ conv->set_storage_handler(mySM);
+ }
+ catch(r_Error& err)
+ {
+ cout << "convertFrom(...) request for convertor " << fmt << " failed" << endl
+ << "Error " << err.get_errorno() << " : " << err.what() << endl;
+ return EXIT_FAILURE;
+ }
+
+ try
+ {
+ desc = conv->convertFrom(fmtParams);
+ }
+ catch(r_Error &err)
+ {
+ cout << "convertFrom(...) conversion from " << fmt << " format to r_Array format failed! " << endl
+ << "Error " << err.get_errorno() << " : " << err.what() << endl;
+ if(conv)
+ {
+ delete conv;
+ conv=NULL;
+ }
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+int convertTo(r_Data_Format fmt, const char* fmtParams,
+ const char* data, const r_Minterval& dataDom,
+ const r_Type* dataType, r_convDesc& desc)
+{
+ r_Storage_Man_CPP mySM;
+ r_Convertor *conv=NULL;
+
+ if(data==NULL)
+ {
+ cout << "convertTo(...) data is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(dataType==NULL)
+ {
+ cout << "convertTo(...) dataType is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ try
+ {
+ conv=r_Convertor_Factory::create(fmt, data, dataDom, dataType);
+ conv->set_storage_handler(mySM);
+ }
+ catch(r_Error& err)
+ {
+ cout << "convertTo(...) request for convertor " << fmt << " failed! " << endl
+ << "Error " << err.get_errorno() << " : " << err.what() << endl;
+ return EXIT_FAILURE;
+ }
+
+ try
+ {
+ desc = conv->convertTo(fmtParams);
+ }
+ catch(r_Error &err)
+ {
+ cout << "convertTo(...) conversion from " << fmt << " format to r_Array format failed! " << endl
+ << "Error " << err.get_errorno() << " : " << err.what() << endl;
+ if(conv)
+ {
+ delete conv;
+ conv=NULL;
+ }
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+
+//init/deinit ConvDesc
+void cleanConvDesc(r_convDesc& desc)
+{
+ desc.src=NULL;
+ desc.srcType=NULL;
+ if(desc.dest!=NULL)
+ {
+ delete []desc.dest;
+ desc.dest=NULL;
+ }
+ if(desc.destType!=NULL)
+ {
+ delete desc.destType;
+ desc.destType=NULL;
+ }
+ desc.baseType = r_Convertor::ctype_void;
+}
+
+void initConvDesc(r_convDesc& desc)
+{
+ desc.dest=NULL;
+ desc.src=NULL;
+ desc.srcType=NULL;
+ desc.destType=NULL;
+ desc.baseType = r_Convertor::ctype_void;
+}
+
+//decode a minterval from a string
+int decodeMinterval(const char* src, r_Minterval& srcIv)
+{
+ if(!src)
+ {
+ cout << "decodeMinterval(...) src is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ try
+ {
+ srcIv=r_Minterval(src);
+ }
+ catch(r_Error& err)
+ {
+ cout << "decodeMinterval(...) error while constructing the minterval from " << src << endl;
+ cout << "Error " << err.get_errorno() << ":" << err.what() << endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+//decode a type from a string
+int decodeType(const char* src, r_Type*& srcType)
+{
+ if(!src)
+ {
+ cout << "decodeType(...) src is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(srcType)
+ {
+ cout << "decodeType(...) src is not null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ try
+ {
+ srcType=r_Type::get_any_type(src);
+ }
+ catch(r_Error& err)
+ {
+ cout << "decodeType(...) error while constructing the type from " << src << endl;
+ cout << "Error " << err.get_errorno() << ":" << err.what() << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(!srcType)
+ {
+ cout << "decodeType(...) the type retrived with r_Type::get_any_type(...) is null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(!srcType->isBaseType())
+ {
+ cout << "decodeType(...) the type retrived (" << srcType->type_id() << ") is not a base type" << endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+//parse r_Array params 'domain=<domain_str>,type=<type_str>'
+int parseArrayParams(const char* formatparams,
+ const char* fpDomain,
+ const char* fpType,
+ char*& domain,
+ char*& type)
+{
+ const int fpNo=2;
+ r_Parse_Params params(fpNo);
+
+ //parameter validation
+ if(formatparams==NULL) {
+ cout << "parseArrayParams(...) formatparams is null" << endl;
+ return EXIT_FAILURE;
+ }
+ if(fpDomain==NULL){
+ cout << "parseArrayParams(...) fpDomain is null" << endl;
+ return EXIT_FAILURE;
+ }
+ if(fpType==NULL){
+ cout << "parseArrayParams(...) fpType is null" << endl;
+ return EXIT_FAILURE;
+ }
+ if(domain!=NULL){
+ cout << "parseArrayParams(...) domain is not null" << endl;
+ return EXIT_FAILURE;
+ }
+ if(type!=NULL){
+ cout << "parseArrayParams(...) type is not null" << endl;
+ return EXIT_FAILURE;
+ }
+
+ params.add(fpDomain, &domain, r_Parse_Params::param_type_string);
+ params.add(fpType, &type, r_Parse_Params::param_type_string);
+
+ if(params.process(formatparams) != fpNo)
+ {
+ cout << "parseArrayParams(...) error parsing " << formatparams << endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+//compare 2 structure type
+int compareStructure(r_Structure_Type* src, r_Structure_Type* dest)
+{
+ r_Structure_Type::attribute_iterator iterSrc, iterDest;
+
+ if(src==NULL)
+ {
+ cout << "compareStructure(...) src is null !"<< endl;
+ return EXIT_FAILURE;
+ }
+
+ if(dest==NULL)
+ {
+ cout << "compareStructure(...) dest is null !"<< endl;
+ return EXIT_FAILURE;
+ }
+
+ iterSrc=src->defines_attribute_begin();
+ iterDest=dest->defines_attribute_begin();
+ while( iterSrc!=src->defines_attribute_end() || iterDest!=dest->defines_attribute_end())
+ {
+ r_Type::r_Type_Id typeSrcId=r_Type::UNKNOWNTYPE, typeDestId=r_Type::UNKNOWNTYPE;
+ typeSrcId=(*iterSrc).type_of().type_id();
+ typeDestId=(*iterDest).type_of().type_id();
+
+ if(typeSrcId!=typeDestId)
+ {
+ cout << "comparaStructure(...) typeSrcId(" << typeSrcId
+ << ") != typeDestId(" << typeDestId << ") !"<< endl;
+ return EXIT_FAILURE;
+ }
+
+ if((typeSrcId== r_Type::STRUCTURETYPE) &&
+ (compareStructure((r_Structure_Type*)(&((*iterSrc).type_of())),
+ (r_Structure_Type*)(&((*iterDest).type_of()))) != EXIT_SUCCESS))
+ return EXIT_FAILURE;
+
+ iterSrc++;
+ iterDest++;
+ }
+ if((iterSrc==src->defines_attribute_end()) &&
+ (iterDest==dest->defines_attribute_end()))
+ return EXIT_SUCCESS;
+ else
+ {
+ if(iterSrc!=src->defines_attribute_end())
+ cout << "compareStructure(...) src has more atributes then dest!" << endl;
+ else
+ cout << "compareStructure(...) dest has more atributes then src!" << endl;
+ return EXIT_FAILURE;
+ }
+}
diff --git a/rasodmg/test/deletecollection.cc b/rasodmg/test/deletecollection.cc
new file mode 100644
index 0000000..6cade1e
--- /dev/null
+++ b/rasodmg/test/deletecollection.cc
@@ -0,0 +1,720 @@
+/*
+* 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: deletecollection.cc
+ *
+ * MODULE: rasodmg
+ *
+ * PURPOSE:
+ *
+ *
+ ************************************************************/
+
+#ifdef EARLY_TEMPLATE
+#define __EXECUTABLE__
+#include "raslib/template_inst.hh"
+#endif
+
+#ifdef __VISUALC__
+#include <strstrea.h>
+#else
+#include <strstream.h>
+#endif
+
+#include <iostream>
+#include <iomanip.h>
+#include <string.h>
+#include <fstream.h>
+
+#include <math.h>
+
+#ifdef __VISUALC__
+ #define __EXECUTABLE__
+#endif
+
+#include "include/basictypes.hh"
+#include "raslib/type.hh"
+#include "rasodmg/storagelayout.hh"
+#include "rasodmg/alignedtiling.hh"
+
+#ifdef __VISUALC__
+ #undef __EXECUTABLE__
+#endif
+
+static int INIT = 0;
+
+static long minNo = 0;
+static long maxNo = 0;
+static ifstream fileStream;
+
+r_ULong initWithCounter( const r_Point& /*pt*/ )
+{
+ return INIT++;
+}
+
+
+r_Char initWithCounterChar( const r_Point& /*pt*/ )
+{
+ return (r_Char) INIT++;
+}
+
+
+r_UShort initWithCounterUShort( const r_Point& /*pt*/ )
+{
+ return (r_UShort) INIT++;
+}
+
+
+
+r_ULong initWithCrossfoot( const r_Point& pt )
+{
+ r_ULong value=0;
+
+ for( r_Dimension i=0; i< pt.dimension(); i++ )
+ value += (r_ULong)pt[i];
+
+ return value;
+}
+
+
+r_ULong initWithCoordinates( const r_Point& pt )
+{
+ r_ULong value=0;
+ r_ULong factor=1;
+
+ for( int i=pt.dimension()-1; i >= 0; i-- )
+ {
+ value += (r_ULong)(factor * pt[i]);
+ factor *= 100;
+ }
+
+ return value;
+}
+
+
+
+r_Char initWithCurve( const r_Point& pt )
+{
+ r_ULong value=0;
+
+ for( r_Dimension i=0; i < pt.dimension(); i++ )
+ value += (r_Char)( 255* sin( .25 * (float)pt[i] ) );
+
+ return (r_Char)value;
+}
+
+
+
+r_ULong initWithColorCube( const r_Point& pt )
+{
+ r_ULong value=0;
+
+ if( pt.dimension() == 3 )
+ value = ((unsigned long)(pt[0]) << 16) + ((unsigned long)(pt[1]) << 8) + (unsigned long)(pt[2]);
+
+ return value;
+}
+
+
+r_Char initWithRandomChar( const r_Point& /*pt*/ )
+{
+ // rand creates numbers between 0 and 32767
+ unsigned long number = rand();
+ double factor = (maxNo - minNo)/32767.0;
+
+ return (r_Char)(minNo + (number * factor));
+}
+
+r_ULong initWithRandomULong( const r_Point& /*pt*/ )
+{
+ // rand creates numbers between 0 and 32767
+ unsigned long number = rand();
+ double factor = (maxNo - minNo)/32767.0;
+
+ return (r_ULong)(minNo + (number * factor));
+}
+
+
+r_Char initFromFile( const r_Point& /*pt*/ )
+{
+ char ch;
+
+ if( fileStream.get(ch) )
+ return ch;
+ else
+ return 0;
+}
+
+/*
+r_Ref< r_Marray<r_ULong> > readFile( r_Database& db )
+{
+ r_Ref< r_Marray<r_ULong> > image;
+ r_Minterval domain(3);
+ long dx, dy, dz, depth, cx, cy, cz;
+ int i;
+
+ ifstream fileStream( "hw8.full.vol" );
+ if( !fileStream )
+ {
+ cout << "Error: File not found." << endl;
+ exit(-1);
+ }
+
+ // read the first 16 bytes
+ char charDummy;
+ for( i=0; i<16; i++ )
+ fileStream >> charDummy;
+
+ dx = 256;
+ dy = 256;
+ dz = 20;
+ depth = 8;
+
+ domain << r_Sinterval( 0l, (long)(dx-1) ) << r_Sinterval( 0l, (long)(dy-1) ) << r_Sinterval( 0l, (long)(dz-1) );
+
+ cout << domain << "... "; cout.flush();
+
+ image = new( &db ) r_Marray<r_ULong>( domain );
+
+ unsigned long* dataPtr = (unsigned long*)image->get_array();
+
+ r_Point pt(3);
+
+ // for( i=0; i<dx*dy*(221-dz); i++ )
+ // fileStream >> charDummy;
+
+ for( cz = 0; cz < dz; cz++ )
+ {
+ pt[2] = cz;
+ for( cy = 0; cy < dy; cy++ )
+ {
+ pt[1] = cy;
+ for( cx = 0; cx < dx; cx++ )
+ {
+ unsigned char ch;
+ fileStream.get(ch);
+
+ pt[0] = cx;
+ dataPtr[domain.cell_offset(pt)] = ((unsigned long)ch << 16) +
+ ((unsigned long)ch << 8) +
+ ((unsigned long)ch);
+ }
+ }
+ }
+
+ fileStream.close();
+
+ return image;
+}
+*/
+
+
+void printColl( r_Ref< r_Set< r_Ref< r_GMarray > > >& image_set, int output, int hexOutput )
+{
+ cout << "Collection" << endl;
+ cout << " Oid...................: " << image_set->get_oid() << endl;
+ cout << " Type Name.............: " << image_set->get_object_name() << endl;
+ cout << " Type Structure........: "
+ << ( image_set->get_type_structure() ? image_set->get_type_structure() : "<nn>" ) << endl;
+ cout << " Type Schema...........: " << flush;
+ if( image_set->get_type_schema() )
+ image_set->get_type_schema()->print_status( cout );
+ else
+ cout << "<nn>" << flush;
+ cout << endl;
+ cout << " Number of entries.....: " << image_set->cardinality() << endl;
+ cout << " Element Type Schema...: " << flush;
+ if( image_set->get_element_type_schema() )
+ image_set->get_element_type_schema()->print_status( cout );
+ else
+ cout << "<nn>" << flush;
+ cout << endl;
+
+ r_Iterator< r_Ref< r_GMarray > > iter = image_set->create_iterator();
+
+ cout << endl;
+ for ( int i=1 ; iter.not_done(); iter++, i++ )
+ {
+ // do not dereference the object
+ cout << "Image " << i << " oid: " << (*iter).get_oid() << endl;
+
+ if( output )
+ {
+ (*iter)->print_status( cout, hexOutput );
+ cout << endl;
+ }
+ }
+ cout << endl;
+}
+
+
+
+int checkArguments( int argc, char** argv, const char* searchText, int& optionValueIndex )
+{
+ int found = 0;
+ int i=1;
+
+ while( !found && i<argc )
+ found = !strcmp( searchText, argv[i++] );
+
+ if( found && i<argc && !strchr(argv[i],'-') )
+ optionValueIndex = i;
+ else
+ optionValueIndex = 0;
+
+ return found;
+}
+
+
+
+int main( int argc, char** argv )
+{
+ int optionValueIndex=0;
+ int testbed = 0;
+ unsigned long tileSize=0;
+ r_Minterval tileConfig;
+ int compressed=0;
+
+ char serverName[255];
+ char baseName[255];
+ char collName[255];
+ char setTypeName[255] = "";
+ char mddTypeName[255] = "";
+ char fileName[255]="";
+
+ if( argc < 4 || checkArguments( argc, argv, "-h", optionValueIndex ) )
+ {
+ cout << "Usage: test_insert3 server_name base_name collection_name [options]" << endl << endl;
+ cout << "Options: -h ... this help" << endl;
+ cout << " -settype <typename> ... type name used for creation of a new set." << endl;
+ cout << " -mddtype <typename> ... type name used for creation of a new mdd object." << endl;
+ cout << " -testbed ... turn on output for testbed" << endl;
+ cout << " -tileconf ... tile configuration" << endl;
+ cout << " -tilesize ... tile size" << endl;
+ cout << " -file <filename> ... file name used to read data from a file" << endl;
+ cout << " -compressed ... inserts MDD in compressed format" << endl;
+ cout << endl;
+ return 0;
+ }
+
+ strcpy( serverName, argv[1] );
+ strcpy( baseName, argv[2] );
+ strcpy( collName, argv[3] );
+
+ if( checkArguments( argc, argv, "-settype", optionValueIndex ) && optionValueIndex )
+ strcpy( setTypeName, argv[optionValueIndex] );
+
+ if( checkArguments( argc, argv, "-mddtype", optionValueIndex ) && optionValueIndex )
+ strcpy( mddTypeName, argv[optionValueIndex] );
+
+ testbed = checkArguments( argc, argv, "-testbed", optionValueIndex );
+
+ if( checkArguments( argc, argv, "-tileconf", optionValueIndex ) && optionValueIndex )
+ tileConfig = r_Minterval( argv[optionValueIndex] );
+
+ if( checkArguments( argc, argv, "-tilesize", optionValueIndex ) && optionValueIndex )
+ tileSize = strtoul( argv[optionValueIndex], (char **)NULL, 10 ) ;
+
+ if( checkArguments( argc, argv, "-file", optionValueIndex ) && optionValueIndex )
+ strcpy( fileName, argv[optionValueIndex] );
+
+ compressed = checkArguments( argc, argv, "-compressed", optionValueIndex );
+
+ cout << endl << endl;
+ cout << "Insertion of one MDD into the database" << endl;
+ cout << "======================================" << endl << endl;
+
+ r_Database db;
+ r_Transaction ta;
+ r_Ref< r_Set< r_Ref< r_GMarray > > > image_set;
+ r_Ref< r_GMarray > image;
+ r_Minterval domain;
+ r_Dimension dim;
+ r_Range low, high;
+ unsigned long initMode, initValue;
+
+ RGBPixel rgbValue = { 1, 2, 3 };
+
+ db.set_servername( serverName );
+
+ try
+ {
+ /*
+ cout << "MDD Initialization: 0 - Marray<r_ULong> with constant" << endl;
+ cout << " 1 - Marray<r_ULong> with counter" << endl;
+ cout << " 2 - Marray<r_ULong> with coordinates" << endl;
+ cout << " 3 - Marray<r_ULong> with crossfoot" << endl;
+ cout << " 4 - Marray<r_ULong> with color cube" << endl << endl;
+
+ cout << " 5 - Marray<r_Char> with constant" << endl;
+ cout << " 6 - insert RGBImage with constant" << endl;
+ cout << " 7 - Marray<r_Char> with 255*( sin(.25*x1) + ... + sin(.25*xn) )" << endl;
+
+ cout << " 8 - Marray<r_ULong> read a file (hw8.full.vol)" << endl;
+ cout << " 9 - Create just an empty collection of type Marray<r_ULong>" << endl;
+ cout << " 10 - Delete collection of type GMarray" << endl;
+ cout << " 11 - Delete an object of collection" << endl;
+
+ cout << " 13 - Marray<r_Char> with counter" << endl;
+ cout << " 14 - Marray<r_Char> with random numbers" << endl;
+ cout << " 15 - Marray<r_UShort> with counter" << endl;
+ cout << " 16 - Marray<r_ULong> with random numbers" << endl;
+ cout << " 17 - Marray<r_Boolean>" << endl;
+ cout << " 18 - Marray<r_Char> from file" << endl;
+
+ cin >> initMode;
+ cout << endl;
+ */
+ initMode = 10;
+
+ if( initMode == 18 )
+ {
+ fileStream.open( fileName );
+ if( !fileStream )
+ {
+ cout << "Error: File " << fileName << " not found." << endl;
+ exit(-1);
+ }
+ }
+
+ if( initMode == 0 || initMode == 5 || initMode == 17 )
+ {
+ cout << "Constant value : ";
+ cin >> initValue;
+ cout << endl;
+ }
+ if( initMode <= 7 || initMode >= 13 )
+ {
+ cout << "Number of dimensions : ";
+ cin >> dim;
+ cout << endl;
+
+ domain = r_Minterval(dim);
+
+ for( r_Dimension i = 1; i<=dim ; i++ )
+ {
+ cout << "Dimension " << setw(2) << i << " lower bound ";
+ cin >> low;
+ cout << " upper bound ";
+ cin >> high;
+
+ domain << r_Sinterval( low, high );
+ }
+
+ cout << endl;
+ }
+
+ if( initMode == 14 || initMode == 16 )
+ {
+ cout << "Minimum number : ";
+ cin >> minNo;
+ cout << endl;
+
+ cout << "Maximum number : ";
+ cin >> maxNo;
+ cout << endl;
+ }
+
+ cout << "Opening Database " << baseName << " on " << serverName << "... "; cout.flush();
+ db.open( baseName );
+ cout << "OK" << endl;
+
+ cout << "Starting Transaction ... " << flush;
+ ta.begin();
+ cout << "OK" << endl;
+
+ cout << "Opening the set ... " << flush;
+
+ if( initMode == 10 || initMode == 11 )
+ {
+ //
+ // get the set
+ //
+
+ try{
+ image_set = db.lookup_object( collName );
+ }
+ catch( r_Error &obj )
+ {
+ cout << "FAILED" << endl;
+ cout << obj.what() << endl;
+ return -1;
+ }
+
+ cout << "OK" << endl;
+
+ if( initMode == 10 )
+ {
+ // delete the set
+
+ if( !image_set.is_null() )
+ image_set.delete_object();
+ // delete image_set; (not implemented yet)
+ }
+ else
+ {
+ int imageNo=0;
+
+ printColl( image_set, 0, 0 );
+
+ cout << "Please enter the image number to delete: ";
+ cin >> imageNo;
+ cout << endl;
+
+ r_Iterator< r_Ref< r_GMarray > > iter = image_set->create_iterator();
+
+ for ( int i=1; iter.not_done() && i<imageNo; iter++, i++ );
+
+ if( imageNo && iter.not_done() )
+ {
+ image_set->remove_element( *iter );
+ cout << "MDD removed." << endl;
+ }
+ else
+ cout << "Number not valid." << endl << endl;
+ }
+ }
+ else
+ {
+ //
+ // get set
+ //
+
+ try{
+ image_set = db.lookup_object( collName );
+ }
+ catch( r_Error& /*obj*/ )
+ {
+ cout << "FAILED" << endl;
+ // cout << obj.what() << endl;
+
+ //
+ // set doesn't exist -> create the set
+ //
+
+ cout << "Create the set ... " << flush;
+
+ if( initMode == 5 || initMode == 7 || initMode == 13 || initMode == 14 || initMode == 18 )
+ {
+ if( !strlen( setTypeName ) )
+ strcpy( setTypeName, "GreySet" );
+
+ image_set = new( &db, setTypeName ) r_Set< r_Ref< r_Marray<r_Char> > >;
+ }
+ else if( initMode == 6 )
+ {
+ if( !strlen( setTypeName ) )
+ strcpy( setTypeName, "RGBSet" );
+
+ image_set = new( &db, setTypeName ) r_Set< r_Ref< r_Marray<RGBPixel> > >;
+ }
+ else if( initMode == 15 )
+ {
+ if( !strlen( setTypeName ) )
+ strcpy( setTypeName, "UShortSet" );
+
+ image_set = new( &db, setTypeName ) r_Set< r_Ref< r_Marray<r_UShort> > >;
+ }
+ else if( initMode == 17 )
+ {
+ if( !strlen( setTypeName ) )
+ strcpy( setTypeName, "BoolSet" );
+
+ image_set = new( &db, setTypeName ) r_Set< r_Ref< r_Marray<r_Boolean> > >;
+ }
+ else
+ {
+ if( !strlen( setTypeName ) )
+ strcpy( setTypeName, "ULongSet" );
+
+ image_set = new( &db, setTypeName ) r_Set< r_Ref< r_Marray<r_ULong> > >;
+ }
+
+ // create a name for the persistent set in order to be able to look it up again
+ db.set_object_name( *image_set, collName );
+ }
+
+ cout << " with type name " << setTypeName << " ... OK" << endl;
+
+ cout << "OId of the set is " << image_set->get_oid() << " ... " << endl;
+
+ if( initMode <= 9 || initMode >= 13 )
+ {
+ cout << "Creating an image ..." << flush;
+
+ // create storage layout object
+ r_Storage_Layout* stl = 0;
+ if( tileSize )
+ stl = new r_Storage_Layout( new r_Aligned_Tiling( tileConfig, tileSize ) );
+
+ if( compressed )
+ {
+ if( !stl )
+ stl = new r_Storage_Layout();
+
+ db.set_storage_format( r_ZLib );
+ }
+
+ // create the image
+ switch( initMode )
+ {
+ case 0:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, (r_ULong)initValue, stl );
+ break;
+ case 1:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, &initWithCounter, stl );
+ break;
+ case 2:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, &initWithCoordinates, stl );
+ break;
+ case 3:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, &initWithCrossfoot, stl );
+ break;
+ case 4:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, &initWithColorCube, stl );
+ break;
+ case 5:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "GreyImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Char>( domain, (r_Char)initValue, stl );
+ break;
+ case 6:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "RGBImage" );
+
+ image = new( &db, mddTypeName ) RGBImage( domain, rgbValue, stl );
+ break;
+ case 7:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "GreyImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Char>( domain, &initWithCurve, stl );
+ break;
+ case 13:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "GreyImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Char>( domain, &initWithCounterChar, stl );
+ break;
+ case 14:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "GreyImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Char>( domain, &initWithRandomChar, stl );
+ break;
+ case 15:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "UShortImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_UShort>( domain, &initWithCounterUShort, stl );
+ break;
+ case 16:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, &initWithRandomULong, stl );
+ break;
+ case 17:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "BoolImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Boolean>( domain, (r_Boolean)initValue, stl );
+ break;
+ case 18:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "GreyImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_Char>( domain, &initFromFile, stl );
+ break;
+ default:
+ if( !strlen( mddTypeName ) )
+ strcpy( mddTypeName, "ULongImage" );
+
+ image = new( &db, mddTypeName ) r_Marray<r_ULong>( domain, (r_ULong)0, stl );
+ }
+
+ cout << "OId of the new image is " << image->get_oid() << endl;
+
+ cout << "Inserting one image with domain " << domain << " into collection " << collName << "..." << flush;
+ // put in into the persistent list
+ image_set->insert_element( image );
+ cout << "OK" << endl << endl;
+
+ if( testbed )
+ {
+ cout << endl << "Testbed output:" << endl;
+ cout << "-- Testbed: set_oid=" << image_set->get_oid() << endl;
+ cout << "-- Testbed: image_oid=" << image->get_oid() << endl;
+ cout << endl;
+ }
+
+ }
+ }
+
+ try
+ {
+ cout << "Committing Transaction ... " << flush;
+ ta.commit();
+ cout << "OK" << endl;
+ }
+ catch( r_Error &obj )
+ {
+ cerr << obj.what() << endl;
+ return -1;
+ }
+
+ cout << "Closing Database ... " << flush;
+ db.close();
+ cout << "OK" << endl;
+
+ if( initMode == 18 )
+ fileStream.close();
+ }
+ catch( r_Error& errorObj )
+ {
+ cerr << errorObj.what() << endl;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
diff --git a/rasodmg/test/earth.ql b/rasodmg/test/earth.ql
new file mode 100644
index 0000000..5de6f1d
--- /dev/null
+++ b/rasodmg/test/earth.ql
@@ -0,0 +1,68 @@
+// This test evaluates the effort for internal operations.
+// Run on different servers with optimization of operations and
+// multidimensional operations turned on and off.
+
+// no operation
+
+select img[0:799,0:799]
+from earth1 as img
+
+// one MDD operation
+
+select img[0:799,0:799] + img[0:799,0:799]
+from earth1 as img
+
+// two MDD operations
+
+select img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799]
+from earth1 as img
+
+// three MDD operations
+
+select img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799]
+from earth1 as img
+
+// four MDD operations
+
+select img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799]
+from earth1 as img
+
+// five MDD operations
+
+select img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799] + img[0:799,0:799]
+from earth1 as img
+
+// no operation
+
+select img[0:799,0:799]
+from earth1 as img
+
+// one unary operation
+
+select not(img[0:799,0:799])
+from earth1 as img
+
+// no operation
+
+select img[0:799,0:799]
+from earth1 as img
+
+// one binary operation with a constant (+)
+
+select img[0:799,0:799] + 10c
+from earth1 as img
+
+// two binary operations with a constant (+, *)
+
+select (img[0:799,0:799] + 10c) * 10c
+from earth1 as img
+
+// three binary operations with a constant (+, *, -)
+
+select ((img[0:799,0:799] + 10c) * 10c) - 10c
+from earth1 as img
+
+// four binary operations with a constant (+, *, -, /)
+
+select (((img[0:799,0:799] + 10c) * 10c) - 10c) / 10c
+from earth1 as img
diff --git a/rasodmg/test/earth_16.ql b/rasodmg/test/earth_16.ql
new file mode 100644
index 0000000..c53508a
--- /dev/null
+++ b/rasodmg/test/earth_16.ql
@@ -0,0 +1,41 @@
+// Selection of images out of a collection with 15 800x800x8bit
+// images. There is one image each with only 255, 254, 253 as a
+// value. And there is one image each with one value each out of
+// 250, 251, 252. No other image contains value greater than 249.
+
+// one img with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE some_cell ( img = 252c )
+
+// two imgs with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE some_cell ( img = 252c OR img = 251c )
+
+// three imgs with some_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE some_cell ( img = 252c OR img = 251c OR img = 250c )
+
+// one img with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE all_cell ( img >= 255c )
+
+// two imgs with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE all_cell ( img >= 254c )
+
+// three imgs with all_cell
+
+SELECT img[0:252,0:252]
+FROM earth_16 as img
+WHERE all_cell ( img >= 253c )
+
diff --git a/rasodmg/test/earth_32.ql b/rasodmg/test/earth_32.ql
new file mode 100644
index 0000000..67145be
--- /dev/null
+++ b/rasodmg/test/earth_32.ql
@@ -0,0 +1,41 @@
+// Selection of images out of a collection with 15 800x800x8bit
+// images. There is one