public intg narrow_into(ref idxspec dst, int d, intg s, intg o) { if (ndim <= 0) { throw new Exception("cannot narrow a scalar"); } if ((d < 0) || (d >= ndim)) { throw new Exception("narrow: illegal dimension index " + d + " in " + this); } if ((o < 0) || (s < 1) || (s + o > dim[d])) { throw new Exception("trying to narrow dimension " + d + " to size " + s + " starting at offset " + o + " in " + this); } // this preserves the dim/mod arrays if dst == this dst.setndim(ndim); dst.offset = offset + o * mod[d]; for (int j = 0; j < ndim; j++) { dst.dim[j] = dim[j]; dst.mod[j] = mod[j]; } dst.dim[d] = s; return(s); }
// select, narrow, unfold, etc // Each function has 3 version: // 1. XXX_into: which writes the result // into an existing idxspec apssed as argument. // 2. XXX_inplace: writes into the current idxspec // 3. XXX: creates a new idxspec and returns it. public intg select_into(ref idxspec dst, int d, intg n) { if (ndim <= 0) { throw new Exception("cannot select an empty idx idx that is a scalar (" + this + ")"); } if ((n < 0) || (n >= dim[d])) { throw new Exception("trying to select layer " + n + " of dimension " + d + " which is of size " + dim[d] + " in idx " + this); } // this preserves the dim/mod arrays if dst == this dst.setndim(ndim - 1); dst.offset = offset + (n * mod[d]); if (ndim - 1 > 0) { // dim and mod don't exist for idx0 for (int j = 0; j < d; j++) { dst.dim[j] = dim[j]; dst.mod[j] = mod[j]; } for (int j = d; j < ndim - 1; j++) { dst.dim[j] = dim[j + 1]; dst.mod[j] = mod[j + 1]; } } return(n); }
//////////////////////////////////////////////////////////////// // unfold // d: dimension; k: kernel size; s: stride. public intg unfold_into(ref idxspec dst, int d, intg k, intg s) { intg ns; // size of newly created dimension String err = ""; if (ndim <= 0) { err += "cannot unfold an idx of maximum order"; } else if ((d < 0) || (d >= ndim)) { err += "unfold: illegal dimension index"; } else if ((k < 1) || (s < 1)) { err += "unfold: kernel and stride must be >= 1"; } ns = 1 + (dim[d] - k) / s; if (!String.IsNullOrWhiteSpace(err) && ((ns <= 0) || (dim[d] != s * (ns - 1) + k))) { err += "unfold: kernel and stride incompatible with size"; } if (!String.IsNullOrWhiteSpace(err)) { throw new Exception(err + ", while unfolding dimension " + d + " to size " + k + " with step " + s + " from idx " + this + " into idx " + dst); } // this preserves the dim/mod arrays if dst == this dst.setndim(ndim + 1); dst.offset = offset; for (int i = 0; i < ndim; i++) { dst.dim[i] = dim[i]; dst.mod[i] = mod[i]; } dst.dim[ndim] = k; dst.mod[ndim] = mod[d]; dst.dim[d] = ns; dst.mod[d] = mod[d] * s; return(ns); }
//////////////////////////////////////////////////////////////// // transpose // tranpose two dimensions into pre-existing idxspec public int transpose_into(ref idxspec dst, int d1, int d2) { if ((d1 < 0) || (d1 >= ndim) || (d2 < 0) || (d2 >= ndim)) { throw new Exception("illegal transpose of dimension " + d1 + " to dimension " + d2); } // this preserves the dim/mod arrays if dst == this dst.setndim(ndim); dst.offset = offset; for (int j = 0; j < ndim; j++) { dst.dim[j] = dim[j]; dst.mod[j] = mod[j]; } intg tmp; // we do this in case dst = this tmp = dim[d1]; dst.dim[d1] = dim[d2]; dst.dim[d2] = tmp; tmp = mod[d1]; dst.mod[d1] = mod[d2]; dst.mod[d2] = tmp; return(ndim); }
// tranpose all dims with a permutation vector public int transpose_into(ref idxspec dst, int[] p) { for (int i = 0; i < ndim; i++) { if ((p[i] < 0) || (p[i] >= ndim)) { throw new Exception("illegal transpose of dimensions"); } } dst.setndim(ndim); dst.offset = offset; if (dst == this) { // we need temp storage if done in place intg[] tmpdim = new intg[Global.MAXDIMS]; intg[] tmpmod = new intg[Global.MAXDIMS]; for (int j = 0; j < ndim; j++) { tmpdim[j] = dim[p[j]]; tmpmod[j] = mod[p[j]]; } for (int j = 0; j < ndim; j++) { dst.dim[j] = tmpdim[j]; dst.mod[j] = tmpmod[j]; } } else { // not in place for (int j = 0; j < ndim; j++) { dst.dim[j] = dim[p[j]]; dst.mod[j] = mod[p[j]]; } } return(ndim); }