Changeset: b65b8c5d79a2 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=b65b8c5d79a2
Modified Files:
        monetdb5/modules/mal/array.mx
Branch: sciql
Log Message:

Step 1/2 of fixing array slicing

Implemented an array.slice operator, which, based on the  assumption that the
 dimensions are stored 'canonically', computes the indices of the cells that are
 selected by the array slicing.
This operator is currently only used for array slicings with at least one
 slicing range with explicit step size.
All other slicings are handled using normal SQL selections.


diffs (182 lines):

diff --git a/monetdb5/modules/mal/array.mx b/monetdb5/modules/mal/array.mx
--- a/monetdb5/modules/mal/array.mx
+++ b/monetdb5/modules/mal/array.mx
@@ -297,14 +297,166 @@ ARRAYfiller_bat(Client cntxt, MalBlkPtr 
        return MAL_SUCCEED;
 }
 
+# define SLICE_CLEANUP() \
+{ \
+       if (dim_strt) GDKfree(dim_strt); \
+       if (dim_step) GDKfree(dim_step); \
+       if (dim_stop) GDKfree(dim_stop); \
+       if (dim_size) GDKfree(dim_size); \
+       if (dim_rept) GDKfree(dim_rept); \
+\
+       if (slc_strt) GDKfree(slc_strt); \
+       if (slc_step) GDKfree(slc_step); \
+       if (slc_stop) GDKfree(slc_stop); \
+       if (slc_size) GDKfree(slc_size); \
+       if (slc_rept) GDKfree(slc_rept); \
+       if (slc_indx) GDKfree(slc_indx); \
+}
+
+/*            Dim 1                     Dim 2                      Dim 3
+ *               size repeat               size repeat                size 
repeat
+ * dim: [1:2:10],  5,   12         [3:1:6],  3,    4         [0:4:13],  4,    1
+ * slc: [3:4: 8],  2,    4         [4:1:6],  2,    2         [0:4: 5],  2,    1
+ *
+ *      (3 + 0 * 4 - 1) / 2 * 12 + (4 + 0 * 1 - 3) / 1 * 4 + (0 + 0 * 4 - 0) / 
4 * 1 = 16
+ *      (3 + 0 * 4 - 1) / 2 * 12 + (4 + 0 * 1 - 3) / 1 * 4 + (0 + 1 * 4 - 0) / 
4 * 1 = 17
+ *
+ *      (3 + 0 * 4 - 1) / 2 * 12 + (4 + 1 * 1 - 3) / 1 * 4 + (0 + 0 * 4 - 0) / 
4 * 1 = 20
+ *      (3 + 0 * 4 - 1) / 2 * 12 + (4 + 1 * 1 - 3) / 1 * 4 + (0 + 1 * 4 - 0) / 
4 * 1 = 21
+ *
+ *      (3 + 1 * 4 - 1) / 2 * 12 + (4 + 0 * 1 - 3) / 1 * 4 + (0 + 0 * 4 - 0) / 
4 * 1 = 40
+ *      (3 + 1 * 4 - 1) / 2 * 12 + (4 + 0 * 1 - 3) / 1 * 4 + (0 + 1 * 4 - 0) / 
4 * 1 = 41
+ *
+ *      (3 + 1 * 4 - 1) / 2 * 12 + (4 + 1 * 1 - 3) / 1 * 4 + (0 + 0 * 4 - 0) / 
4 * 1 = 44
+ *      (3 + 1 * 4 - 1) / 2 * 12 + (4 + 1 * 1 - 3) / 1 * 4 + (0 + 1 * 4 - 0) / 
4 * 1 = 45
+ *
+ * The formula for each dimention (0 <= j < valence) in each iteration:
+ *  (slc_strt[j] + slc_indx[j] * slc_step[j] - dim_strt[j]) / dim_step[j] * 
dim_rept[j]
+ * To get the index of an iteration, compute the sum of the formula for all 
dimensions.
+ * The key is to compute on the fly the correct value for each slc_indx[j] for
+ *  each dimension in each iteration.
+ * The formula to compute slc_indx[j] for each dimension in each iteratino:
+ *  slc_indx[j] = (((i + 1) % slc_rept[j]) == 0)? ((slc_indx[j] + 1) % 
slc_size[j]) : slc_indx[j];
+ * The slc_indx[j] should be increased with 1 for the next iteration, if it has
+ *  been repeated enough times for this dimention, i.e., check if the next
+ *  iteration number is a multiple of slc_rept[j].
+ * Additionally, slc_indx[j] must be reset to 0 if we have iterated over all
+ *  slicing elements of this dimension, i.e., check after increasing if the
+ *  value of slc_indx[j] is a multiple of slc_size[j].
+ *
+ * a := array.slice(1:lng,2:lng,10:lng, 3:lng,4:lng,8:lng, 3:lng,1:lng,6:lng, 
4:lng,1:lng,6:lng, 0:lng,4:lng,13:lng, 0:lng,4:lng,5:lng); */
 str
 ARRAYslice(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
 {
+       int *ret = (int*) getArgReference(stk,pci,0);
+       lng *dim_strt = NULL, *dim_step = NULL, *dim_stop = NULL, *dim_size = 
NULL, *dim_rept = NULL,
+               *slc_strt = NULL, *slc_step = NULL, *slc_stop = NULL, *slc_size 
= NULL, *slc_rept = NULL, *slc_indx = NULL;
+       BUN i = 0, j = 0;
+       BUN rescnt = 1, valence = (pci->argc - pci->retc) / 6;
+       BAT *res = NULL;
+       oid *resT = NULL;
+
        (void) cntxt;
        (void) mb;
-       (void) stk;
-       (void) pci;
 
+       if ( (pci->argc - pci->retc) % 6 != 0)
+               throw(MAL, "array.slice", "Unbalanced argument sets");
+
+       dim_strt = (lng*) GDKmalloc(sizeof(lng) * valence);
+       dim_step = (lng*) GDKmalloc(sizeof(lng) * valence);
+       dim_stop = (lng*) GDKmalloc(sizeof(lng) * valence);
+       dim_size = (lng*) GDKmalloc(sizeof(lng) * valence);
+       dim_rept = (lng*) GDKmalloc(sizeof(lng) * valence);
+
+       slc_strt = (lng*) GDKmalloc(sizeof(lng) * valence);
+       slc_step = (lng*) GDKmalloc(sizeof(lng) * valence);
+       slc_stop = (lng*) GDKmalloc(sizeof(lng) * valence);
+       slc_size = (lng*) GDKmalloc(sizeof(lng) * valence);
+       slc_rept = (lng*) GDKmalloc(sizeof(lng) * valence);
+       slc_indx = (lng*) GDKzalloc(sizeof(lng) * valence);
+       
+       if (dim_strt == NULL || dim_step == NULL || dim_stop == NULL || 
dim_size == NULL || dim_rept == NULL ||
+               slc_strt == NULL || slc_step == NULL || slc_stop == NULL || 
slc_size == NULL || slc_rept == NULL || slc_indx == NULL)
+       {
+               SLICE_CLEANUP();
+               throw(MAL, "array.slice", MAL_MALLOC_FAIL);
+       }
+
+       for (i = 0; i < valence; i++) {
+               dim_strt[i] = *(lng*)getArgReference(stk,pci,1+6*i);
+               dim_step[i] = *(lng*)getArgReference(stk,pci,1+6*i+1);
+               dim_stop[i] = *(lng*)getArgReference(stk,pci,1+6*i+2);
+               dim_size[i] = (dim_stop[i] - dim_strt[i] + dim_step[i] -1) / 
dim_step[i];
+               dim_rept[i] = 1;
+
+               slc_strt[i] = *(lng*)getArgReference(stk,pci,1+6*i+3);
+               slc_step[i] = *(lng*)getArgReference(stk,pci,1+6*i+4);
+               slc_stop[i] = *(lng*)getArgReference(stk,pci,1+6*i+5);
+               slc_size[i] = (slc_stop[i] - slc_strt[i] + slc_step[i] - 1) / 
slc_step[i];
+               slc_rept[i] = 1;
+               slc_indx[i] = 0;
+
+               rescnt *= slc_size[i];
+
+               if ( (slc_step[i] > 0 && (slc_strt[i] < dim_strt[i] || 
slc_stop[i] > dim_stop[i])) || 
+                        (slc_step[i] < 0 && (slc_strt[i] > dim_strt[i] || 
slc_stop[i] < dim_stop[i])) ) {
+                       SLICE_CLEANUP();
+                       throw(MAL, "array.slice", "Slice range [%lld:%lld:%lld] 
of the " BUNFMT "-th dimension out of bound ([%lld:%lld:%lld])",
+                                       slc_strt[i], slc_step[i], slc_stop[i], 
i, dim_strt[i], dim_step[i], dim_stop[i]);
+               }
+
+               if ((slc_strt[i] - dim_strt[i]) % dim_step[i] != 0) {
+                       SLICE_CLEANUP();
+                       throw(MAL, "array.slice", "Invalid slice range of the " 
BUNFMT "-th dimension: the slicing start value '%lld' is not a valid value of 
this dimension",
+                                       i, slc_strt[i]);
+               }
+
+               if ((slc_strt[i] - dim_strt[i]) % dim_step[i] != 0) {
+                       SLICE_CLEANUP();
+                       throw(MAL, "array.slice", "Invalid slice range of the " 
BUNFMT "-th dimension: the slicing step size '%lld' is not a multiple of the 
step size '%lld' of this dimension",
+                                       i, slc_step[i], dim_step[i]);
+               }
+       }
+
+       /* The number of time the values of a dimension is repeated is the 
produce
+        * of the lengths of all its following dimensions */
+       for (i = 0; i < valence; i++) {
+               for (j = i+1; j < valence; j++) {
+                       dim_rept[i] *= dim_size[j];
+                       slc_rept[i] *= slc_size[j];
+               }
+       }
+
+       res = BATnew(TYPE_void, TYPE_oid, rescnt);
+       if(res == NULL) {
+               SLICE_CLEANUP();
+               throw(MAL, "array.filler", MAL_MALLOC_FAIL);
+       }
+
+       resT = (oid *) Tloc(res, BUNfirst(res));
+       /* the main loop: compute the index of each cell selected by the 
slicing */
+       for (i = 0; i < rescnt; i++) {
+               resT[i] = 0;
+               /* compute the formula for each dimension, then sum them up to 
get the index */
+               for (j = 0; j < valence; j++) {
+                       resT[i] += (slc_strt[j] + slc_indx[j] * slc_step[j] - 
dim_strt[j]) / dim_step[j] * dim_rept[j];
+                       /* only increase the index into the slicing elements if 
the current
+                        * element has been repeated slc_rept[j] times.
+                        * reset the index into the slicing elements if all 
elements have
+                        * already been processed once.
+                        */
+                       slc_indx[j] = (((i + 1) % slc_rept[j]) == 0)? 
((slc_indx[j] + 1) % slc_size[j]) : slc_indx[j];
+               }
+       }
+
+       BATsetcount(res, rescnt);
+       BATseqbase(res, 0);
+       res->hdense = TRUE;
+       BATkey(res, TRUE);
+       res->hsorted = res->hrevsorted = 1;
+       res->tsorted = res->trevsorted = 1;
+       res->T->nonil = TRUE;
+       BBPkeepref(*ret = res->batCacheid);
        return MAL_SUCCEED;
 }
 
@@ -333,8 +485,7 @@ ARRAYfiller(Client cntxt, MalBlkPtr mb, 
        BATseqbase(bn, 0);
        bn->hdense = TRUE;
        BATkey(bn, TRUE);
-       bn->hsorted = 1;
-       bn->hrevsorted = (cnt <= 1);
+       bn->hsorted = bn->hrevsorted = 1;
        bn->tsorted = bn->trevsorted = 1;
        switch(type){
                case TYPE_bit:
_______________________________________________
checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to