/*------------------------------------------------------------------------- * * arrayutils.c * This file contains some support routines required for array functions. * * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $PostgreSQL: pgsql/src/backend/utils/adt/arrayutils.c,v 1.17 2004/09/16 03:15:52 neilc Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include "utils/array.h" /* Convert subscript list into linear element number (from 0) */ int ArrayGetOffset(int n, int *dim, int *lb, int *indx) { int i, scale = 1, offset = 0; for (i = n - 1; i >= 0; i--) { offset += (indx[i] - lb[i]) * scale; scale *= dim[i]; } return offset; } /* Same, but subscripts are assumed 0-based, and use a scale array * instead of raw dimension data (see mda_get_prod to create scale array) */ int ArrayGetOffset0(int n, int *tup, int *scale) { int i, lin = 0; for (i = 0; i < n; i++) lin += tup[i] * scale[i]; return lin; } /* Convert array dimensions into number of elements */ int ArrayGetNItems(int ndim, int *dims) { int i, ret; if (ndim <= 0) return 0; ret = 1; for (i = 0; i < ndim; i++) ret *= dims[i]; return ret; } /* Compute ranges (sub-array dimensions) for an array slice */ void mda_get_range(int n, int *span, int *st, int *endp) { int i; for (i = 0; i < n; i++) span[i] = endp[i] - st[i] + 1; } /* Compute products of array dimensions, ie, scale factors for subscripts */ void mda_get_prod(int n, int *range, int *prod) { int i; prod[n - 1] = 1; for (i = n - 2; i >= 0; i--) prod[i] = prod[i + 1] * range[i + 1]; } /* From products of whole-array dimensions and spans of a sub-array, * compute offset distances needed to step through subarray within array */ void mda_get_offset_values(int n, int *dist, int *prod, int *span) { int i, j; dist[n - 1] = 0; for (j = n - 2; j >= 0; j--) { dist[j] = prod[j] - 1; for (i = j + 1; i < n; i++) dist[j] -= (span[i] - 1) * prod[i]; } } /*----------------------------------------------------------------------------- generates the tuple that is lexicographically one greater than the current n-tuple in "curr", with the restriction that the i-th element of "curr" is less than the i-th element of "span". Returns -1 if no next tuple exists, else the subscript position (0..n-1) corresponding to the dimension to advance along. ----------------------------------------------------------------------------- */ int mda_next_tuple(int n, int *curr, int *span) { int i; if (n <= 0) return -1; curr[n - 1] = (curr[n - 1] + 1) % span[n - 1]; for (i = n - 1; i && curr[i] == 0; i--) curr[i - 1] = (curr[i - 1] + 1) % span[i - 1]; if (i) return i; if (curr[0]) return 0; return -1; }