/*
 * File:        sidl_bool_IOR.c
 * Copyright:   (c) 2001 Lawrence Livermore National Security, LLC
 * Revision:    @(#) $Revision: 6171 $
 * Date:        $Date: 2007-10-08 16:39:28 -0700 (Mon, 08 Oct 2007) $
 * Description: bool array implementation
 * AUTOMATICALLY GENERATED BY createarrays.py
 *
 */

#include "sidl_bool_IOR.h"
#include <stdlib.h>
#include <string.h>

#ifdef MAX
#undef MAX
#endif
#ifdef MIN
#undef MIN
#endif
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
#define MIN(x,y) (((x) < (y)) ? (x) : (y))

static void swap_i32(int32_t *i1, int32_t *i2)
{
  int32_t tmp = *i1;
  *i1 = *i2;
  *i2 = tmp;
}

#define HELPER_VARIABLE
#define COPY_VALUE(x) (x)
#define DESTROY_VALUE(x)
#define INIT_VALUES(ptr,size)

static sidl_bool const sidl_bool__array_zero = 0;

/**
 * Destroy the given borrowed array. Trying to destroy a NULL array is
 * a noop.
 */
static void
sidl_bool__array_bdestroy(struct sidl_bool__array* array)
{
  if (array) {
#ifdef SIDL_DEBUG_REFCOUNT
    sidl__array_remove((struct sidl__array *)array);
#endif
    memset(array, 0, sizeof(struct sidl_bool__array) +
           3 * (size_t)array->d_metadata.d_dimen * sizeof(int32_t));
    free(array);
  }
}

/**
 * Destroy the given array. Trying to destroy a NULL array is a noop.
 */
static void
sidl_bool__array_destroy(struct sidl_bool__array* array)
{
  if (array) {
#ifdef DESTROY_VALUES_TOO
    sidl_bool *ptr = array->d_firstElement;
    int32_t i;
    int32_t size = 1;
    HELPER_VARIABLE;
    for(i = 0; i < array->d_metadata.d_dimen;++i){
      size *= (1 + array->d_metadata.d_upper[i] -
                   array->d_metadata.d_lower[i]);
    }
    while (size--) {
      DESTROY_VALUE(*ptr);
      *(ptr++) = NULL;
    }
#endif
    free(array->d_firstElement);
    sidl_bool__array_bdestroy(array);
  }
}

/**
 * Destroy the given rarray. Actually doesn't do anything.
 */
static void
sidl_bool__array_rdestroy(struct sidl_bool__array* array)
{
#ifdef SIDL_DEBUG_REFCOUNT
  if (array) sidl__array_remove((struct sidl__array *)array);
#endif
}
/**
 * Destroy the given sliced array. Trying to destroy a NULL array is
 * a noop.
 */
static void
sidl_bool__array_sdestroy(struct sidl_bool__array* array)
{
  if (array) {
    static const size_t arraySize = sizeof(struct sidl_bool__array)
      + (sizeof(void *) - (sizeof(struct sidl_bool__array)
                        % sizeof(void *))) % sizeof(void *);
    struct sidl_bool__array **orig;
    orig = (struct sidl_bool__array **)((char *)array + arraySize);
    if (*orig) {
      sidl_bool__array_deleteRef(*orig);
      *orig = NULL;
    }
    sidl_bool__array_bdestroy(array);
  }
}

/**
 * Smart copy routine for self-sufficient and sliced arrays.  This just
 * increments the reference count and returns the same array.
 */
static struct sidl_bool__array*
sidl_bool__array_smartCp(struct sidl_bool__array* array)
{
  sidl_bool__array_addRef(array);
  return array;
}

/**
 * Smart copy routine for self-sufficient and sliced arrays.  This just
 * increments the reference count and returns the same array.
 */
static struct sidl_bool__array*
sidl_bool__array_borrowSmartCp(struct sidl_bool__array* array)
{
  struct sidl_bool__array* copy = NULL;
  if (array) {
    if (sidl_bool__array_isColumnOrder(array)) {
      copy = sidl_bool__array_createCol(array->d_metadata.d_dimen,
                                                array->d_metadata.d_lower,
                                                array->d_metadata.d_upper);
    }
    else {
      copy = sidl_bool__array_createRow(array->d_metadata.d_dimen,
                                                array->d_metadata.d_lower,
                                                array->d_metadata.d_upper);
    }
    sidl_bool__array_copy(array, copy);
  }
  return copy;
}

/**
 * Simple function to return the type of the array.
 */
static int32_t
bool_arrayType(void)
{
  return sidl_bool_array;
}
/**
 * Virtual function table for rarrays.
 */

static const struct sidl__array_vtable rarray_bool_vtable = {
  (void (*)(struct sidl__array *))sidl_bool__array_rdestroy,
  (struct sidl__array *(*)(struct sidl__array *))
    sidl_bool__array_borrowSmartCp,
  bool_arrayType
};
/**
 * Virtual function table for normal, self-sufficient arrays.
 */

static const struct sidl__array_vtable normal_bool_vtable = {
  (void (*)(struct sidl__array *))sidl_bool__array_destroy,
  (struct sidl__array *(*)(struct sidl__array *))
    sidl_bool__array_smartCp,
  bool_arrayType
};
/**
 * Virtual function table for borrowed arrays.
 */

static const struct sidl__array_vtable borrowed_bool_vtable = {
  (void (*)(struct sidl__array *))sidl_bool__array_bdestroy,
  (struct sidl__array *(*)(struct sidl__array *))
    sidl_bool__array_borrowSmartCp,
  bool_arrayType
};
/**
 * Virtual function table for sliced arrays with self-sufficient original
 * arrays.
 */

static const struct sidl__array_vtable sliced_bool_vtable = {
  (void (*)(struct sidl__array *))sidl_bool__array_sdestroy,
  (struct sidl__array *(*)(struct sidl__array *))
    sidl_bool__array_smartCp,
  bool_arrayType
};
/**
 * Virtual function table for sliced arrays with borrowed original
 * arrays.
 */

static const struct sidl__array_vtable bsliced_bool_vtable = {
  (void (*)(struct sidl__array *))sidl_bool__array_sdestroy,
  (struct sidl__array *(*)(struct sidl__array *))
    sidl_bool__array_borrowSmartCp,
  bool_arrayType
};
/**
 * Allocate memory for the array meta-data and initialize the reference
 * count to one.
 */
static struct sidl_bool__array*
newArray(int32_t dimen, const int32_t lower[], const int32_t upper[],
         struct sidl_bool__array *orig)
{
  static const size_t arraySize = sizeof(struct sidl_bool__array)
    + (sizeof(void *) - (sizeof(struct sidl_bool__array)
                      % sizeof(void *))) % sizeof(void *);
  const size_t baseSize = arraySize +
    (orig ? sizeof(struct sidl_bool__array *) : 0);
  const size_t extraBytes = 3 * sizeof(int32_t) * (size_t)dimen;
  const size_t totalSize = baseSize + extraBytes;
  struct sidl_bool__array *result = (struct sidl_bool__array *)malloc(totalSize);
  result->d_metadata.d_dimen = dimen;
  result->d_metadata.d_refcount = 1;
  result->d_metadata.d_lower = (int32_t *)((char *)result + baseSize);
  result->d_metadata.d_upper = result->d_metadata.d_lower + dimen;
  result->d_metadata.d_stride = result->d_metadata.d_upper + dimen;
  if (orig) {
    struct sidl_bool__array **ref;
    ref = (struct sidl_bool__array **)((char *)result + arraySize);
    *ref = orig;
    sidl_bool__array_addRef(orig);
    result->d_metadata.d_vtable = &sliced_bool_vtable;
  }
  else {
    result->d_metadata.d_vtable = &normal_bool_vtable;
  }
  memcpy(result->d_metadata.d_lower, lower, sizeof(int32_t)*(size_t)dimen);
  memcpy(result->d_metadata.d_upper, upper, sizeof(int32_t)*(size_t)dimen);
#ifdef SIDL_DEBUG_REFCOUNT
  sidl__array_add((struct sidl__array *)result);
#endif
  return result;
}

/**
 * Create a dense bool array of the given dimension with specified
 * index bounds in column-major order.  This array owns and manages its data.
 * This function does not initialize the contents of the array.
 */
struct sidl_bool__array *
sidl_bool__array_createCol(int32_t       dimen,
                           const int32_t lower[],
                           const int32_t upper[])
{
  int i;
  size_t size=1;
  struct sidl_bool__array *result = newArray(dimen, lower, upper, NULL);
  for(i = 0; i < dimen; ++i) {
    result->d_metadata.d_stride[i] = size;
    size *= (size_t)(1 + upper[i] - lower[i]);
  }
  size *= sizeof(sidl_bool);
  result->d_firstElement = (sidl_bool *)malloc(size);
  INIT_VALUES(result->d_firstElement, size);
  return result;
}

/**
 * Create a dense bool array of the given dimension with specified
 * index bounds in row-major order.  This array owns and manages its data.
 * This function does not initialize the contents of the array.
 */
struct sidl_bool__array *
sidl_bool__array_createRow(int32_t       dimen,
                           const int32_t lower[],
                           const int32_t upper[])
{
  int i;
  size_t size=1;
  struct sidl_bool__array *result = newArray(dimen, lower, upper, NULL);
  for(i = dimen-1; i >= 0; --i) {
    result->d_metadata.d_stride[i] = size;
    size *= (size_t)(1 + upper[i] - lower[i]);
  }
  size *= sizeof(sidl_bool);
  result->d_firstElement = (sidl_bool *)malloc(size);
  INIT_VALUES(result->d_firstElement, size);
  return result;
}

/**
 * Initialize the array meta-data for this sidl array from the passed
 * in pointers. This is a little wierd, but all these pointers must
 * be allocated, but only upper and c_array actually need to be
 * initialized.  (We use upper, dim, andc_array to figure out the
 * correct values for the rest of the data.)
 * This function does not initialize the contents of the array.
 */
void
sidl_bool__array_init(const sidl_bool* c_array,
struct sidl_bool__array* sidl_array, int32_t dim,
int32_t lower[], int32_t upper[], int32_t stride[])
{
  int32_t i = 0;
  int32_t size = 1;
  for(i=0; i < dim; ++i) 
     lower[i] = 0;

  for(i = 0; i < dim; ++i) {
    stride[i] = size;
    size *= (1 + upper[i] - lower[i]);
  }

  sidl_array->d_metadata.d_lower = lower;
  sidl_array->d_metadata.d_upper = upper;
  sidl_array->d_metadata.d_stride = stride;
  sidl_array->d_metadata.d_dimen = dim;	
  sidl_array->d_metadata.d_lower = lower;
  sidl_array->d_metadata.d_vtable = &rarray_bool_vtable;
  sidl_array->d_metadata.d_refcount = 1;
  sidl_array->d_firstElement = (sidl_bool *)c_array;
#ifdef SIDL_DEBUG_REFCOUNT
  sidl__array_add((struct sidl__array *)sidl_array);
#endif
}

/**
 * Create a dense one-dimensional vector of bools with a lower
 * index of 0 and an upper index of len-1. This array owns and manages
 * its data.
 * This function does not initialize the contents of the array.
 */
struct sidl_bool__array *
sidl_bool__array_create1d(int32_t len)
{
  static const int32_t zero = 0;
  --len;
  return sidl_bool__array_createCol(1, &zero, &len);
}

/**
 * Create a dense one-dimensional vector of bools with a lower
 * index of 0 and an upper index of len-1. The initial data for this
 * new array is copied from data. For strings, this will make a newly
 * malloc'ed copy of each non-NULL string. For interfaces/objects, this
 * will increment the reference count of each non-NULL object/interface
 * reference.
 * 
 * This array owns and manages its data.
 */
struct sidl_bool__array *
sidl_bool__array_create1dInit(int32_t len,
                              const sidl_bool* data)
{
  struct sidl_bool__array *result;
  if (data && (len > 0)) {
    static const int32_t lower = 0;
    const int32_t upper = len - 1;
    result = newArray(1, &lower, &upper, NULL);
    if (result) {
      const sidl_bool * restrict src =
        (const sidl_bool * restrict)data;
      sidl_bool * restrict dest;
      HELPER_VARIABLE;
      result->d_metadata.d_stride[0] = 1;
      result->d_firstElement =
        (sidl_bool *)malloc((size_t)len*sizeof(sidl_bool));
      dest = (sidl_bool * restrict)(result->d_firstElement);
      while (len--) {
        *dest = COPY_VALUE(*src);
        ++dest;
        ++src;
      }
    }
  }
  else {
    result = sidl_bool__array_create1d(len);
  }
  return result;
}

/**
 * Create a dense two-dimensional array of bools with a lower
 * indices of (0,0) and an upper indices of (m-1,n-1). The array is
 * stored in column-major order, and it owns and manages its data.
 * This function does not initialize the contents of the array.
 */
struct sidl_bool__array *
sidl_bool__array_create2dCol(int32_t m, int32_t n)
{
  static const int32_t zero[2] = {0, 0};
  int32_t upper[2];
  upper[0] = m-1;
  upper[1] = n-1;
  return sidl_bool__array_createCol(2, zero, upper);
}

/**
 * Create a dense two-dimensional array of bools with a lower
 * indices of (0,0) and an upper indices of (m-1,n-1). The array is
 * stored in row-major order, and it owns and manages its data.
 * This function does not initialize the contents of the array.
 */
struct sidl_bool__array *
sidl_bool__array_create2dRow(int32_t m, int32_t n)
{
  static const int32_t zero[2] = {0, 0};
  int32_t upper[2];
  upper[0] = m-1;
  upper[1] = n-1;
  return sidl_bool__array_createRow(2, zero, upper);
}

/**
 * Return the stride for a splice argument.
 */
static int32_t
getStride(const int32_t *srcStride, const int32_t i)
{
  return srcStride ? srcStride[i] : 1;
}
/**
 * Check the arguments of a splice call to make sure they're valid.
 */
static int
goodSliceArgs(struct sidl_bool__array* src,
               int32_t       dimen,
               const int32_t *srcStart,
               const int32_t *srcStride,
               const int32_t *newStart,
               const int32_t *numElem)
{
  if (src && numElem && (dimen > 0) && (dimen <= src->d_metadata.d_dimen)) {
    int32_t i, numZeros;
    const int32_t *srcFirst = (srcStart ? srcStart : src->d_metadata.d_lower);
    for(i = 0, numZeros=0; i < src->d_metadata.d_dimen; ++i) {
      if ((srcFirst[i] < src->d_metadata.d_lower[i]) ||
          (srcFirst[i] > src->d_metadata.d_upper[i]) ||
          (numElem[i] &&
           (((srcFirst[i] + (numElem[i]-1)*getStride(srcStride,i)) >
              src->d_metadata.d_upper[i]) ||
            ((srcFirst[i] + (numElem[i]-1)*getStride(srcStride,i)) <
              src->d_metadata.d_lower[i]))))
        return 0;
      if (!numElem[i]) ++numZeros;
    }
    return (dimen + numZeros) == src->d_metadata.d_dimen;
  }
  return 0;
}

/**
 * Create a sub-array of another array. This resulting array shares
 * data with the original array. The new array can be of the same
 * dimension or potentially less assuming the original array has
 * dimension greater than 1.  If you are removing dimension, indicate the
 * dimensions to remove by setting numElem[i] to zero for any dimension i
 * that should go away in the new array.  The meaning of each argument
 * is covered below.
 * 
 * src       the array to be created will be a subset of this array. If
 *           this argument is NULL, NULL will be returned. The array
 *           returned borrows data from src, so modifying src or the
 *           returned array will modify both arrays.
 * 
 * dimen     this argument must be greater than zero and less than or
 *           equal to the dimension of src. An illegal value will cause
 *           a NULL return value.
 *           
 * numElem   this specifies how many elements from src should be taken in
 *           each dimension. A zero entry indicates that the dimension
 *           should not appear in the new array.  This argument should be
 *           an array with an entry for each dimension of src.  Passing
 *           NULL here will cause NULL to be returned.  If
 *           srcStart[i] + numElem[i]*srcStride[i] is greater than
 *           upper[i] for src or if srcStart[i] + numElem[i]*srcStride[i]
 *           is less than lower[i] for src, NULL will be returned.
 * 
 * srcStart  this array holds the coordinates of the first element of the
 *           new array. If this argument is NULL, the first element of
 *           src will be the first element of the new array. If non-NULL,
 *           this argument should be an array with an entry for each
 *           dimension of src.  If srcStart[i] is less than lower[i] for
 *           the array src, NULL will be returned.
 * 
 * srcStride this array lets you specify the stride between elements in
 *           each dimension of src. This stride is relative to the
 *           coordinate system of the src array. If this argument is
 *           NULL, the stride is taken to be one in each dimension.
 *           If non-NULL, this argument should be an array with an entry
 *           for each dimension of src.
 * 
 * newLower  this argument is like lower in a create method. It sets the
 *           coordinates for the first element in the new array.  If this
 *           argument is NULL, the values indicated by srcStart will be
 *           used. If non-NULL, this should be an array with dimen
 *           elements.
 */
struct sidl_bool__array *
sidl_bool__array_slice(struct sidl_bool__array *src,
                       int32_t       dimen,
                       const int32_t numElem[],
                       const int32_t *srcStart,
                       const int32_t *srcStride,
                       const int32_t *newStart)
{
  struct sidl_bool__array *result = NULL;
  if (goodSliceArgs(src, dimen, srcStart, srcStride, newStart, numElem)) {
    const int32_t *srcFirst = (srcStart ? srcStart : src->d_metadata.d_lower);
    const int32_t *newFirst = (newStart ? newStart : srcFirst);
    int32_t *newLast = malloc(sizeof(int32_t)*(size_t)dimen);
    int32_t i, j;
    if (!newLast) return NULL;
    for(i = 0, j = 0; i < src->d_metadata.d_dimen; ++i) {
      if (numElem[i]) {
        newLast[j] = newFirst[j] + numElem[i] - 1;
        ++j;
      }
    }
    result = newArray(dimen, newFirst, newLast, src);
    free(newLast);
    if (result) {
      result->d_firstElement = src->d_firstElement;
      for(i = 0, j = 0; i < src->d_metadata.d_dimen; ++i) {
        result->d_firstElement +=
          ((srcFirst[i] - src->d_metadata.d_lower[i])*
           src->d_metadata.d_stride[i]);
        if (numElem[i]) {
          result->d_metadata.d_stride[j] = src->d_metadata.d_stride[i]*
            getStride(srcStride, i);
          ++j;
        }
      }
      if (src->d_metadata.d_vtable->d_smartcopy ==
          (struct sidl__array *(*)(struct sidl__array *))
           sidl_bool__array_smartCp) {
        result->d_metadata.d_vtable = &sliced_bool_vtable;
      }
      else {
        result->d_metadata.d_vtable = &bsliced_bool_vtable;
      }
    }
  }
  return result;
}

/**
 * Create an array that uses data memory from another source. This initial
 * contents are determined by the data being borrowed.
 */
struct sidl_bool__array *
sidl_bool__array_borrow(sidl_bool* firstElement,
                        int32_t        dimen,
                        const int32_t  lower[],
                        const int32_t  upper[],
                        const int32_t  stride[])
{
  struct sidl_bool__array *result = newArray(dimen, lower, upper, NULL);
  memcpy(result->d_metadata.d_stride, stride, sizeof(int32_t)*(size_t)dimen);
  result->d_firstElement = firstElement;
  result->d_metadata.d_vtable = &borrowed_bool_vtable;
  return result;
}

/**
 * If array is borrowed, allocate a new self-sufficient array and copy
 * the borrowed array into the new array; otherwise, increment the
 * reference count and return the array passed in. Use this whenever
 * you want to make a copy of a method argument because arrays passed
 * into methods aren't guaranteed to exist after the method call.
 */
struct sidl_bool__array *
sidl_bool__array_smartCopy(struct sidl_bool__array *array)
{
  return (struct sidl_bool__array *)
     sidl__array_smartCopy((struct sidl__array*)array);
}

/**
 * Increment the arrays internal reference count by one. To make a
 * persistent copy (i.e. that lives longer than the current method
 * call) use smartCopy.
 */
void
sidl_bool__array_addRef(struct sidl_bool__array* array)
{
  sidl__array_addRef((struct sidl__array*)array);
}

/**
 * Decrement the arrays internal reference count by one. If the reference
 * count goes to zero, destroy the array.
 * Return true iff the array is destroyed
 */
void
sidl_bool__array_deleteRef(struct sidl_bool__array* array)
{
  sidl__array_deleteRef((struct sidl__array*)array);
}

/**
 * Attempt to cast a generic array reference to an bool
 * array. A non-NULL return value indicates that the cast was
 * successful, and the returned pointer is a valid bool
 * array. A NULL return value indicates that the cast failed.
 * This function never alters the reference count of array.
 * 
 */
struct sidl_bool__array*
sidl_bool__array_cast(struct sidl__array* array)
{
  return (array &&
          (sidl_bool_array == ((array->d_vtable->d_arraytype)())))
    ? (struct sidl_bool__array *)array : NULL;
}

/**
 * Retrieve element i1 of a one-dimensional array.
 */
sidl_bool
sidl_bool__array_get1(const struct sidl_bool__array* array,
                      const int32_t i1)
{
  if (array && (1 == array->d_metadata.d_dimen) &&
      ((array->d_metadata.d_lower[0] <= i1) &&
      (array->d_metadata.d_upper[0] >= i1))) {
    HELPER_VARIABLE;
    return COPY_VALUE(*(array->d_firstElement +
                        (i1 - array->d_metadata.d_lower[0])*
                        array->d_metadata.d_stride[0]));
  }
  return sidl_bool__array_zero;
}

/**
 * Retrieve element (i1,i2) of a two-dimensional array.
 */
sidl_bool
sidl_bool__array_get2(const struct sidl_bool__array* array,
                      const int32_t i1,
                      const int32_t i2)
{
  if (array && (2 == array->d_metadata.d_dimen)){
    /* unserialize array bounds checking (i.e. avoid strict left to right */
    /* evaluation of && which serializes evaluation) */
    register int c1 = (array->d_metadata.d_lower[0] <= i1);
    register int c2 = (array->d_metadata.d_upper[0] >= i1);
    register int c3 = (array->d_metadata.d_lower[1] <= i2);
    register int c4 = (array->d_metadata.d_upper[1] >= i2);
    HELPER_VARIABLE;
    c1 = c1 && c2;
    c3 = c3 && c4;
    if (c1 && c3) {
      return COPY_VALUE(*(array->d_firstElement +
                          (i1 - array->d_metadata.d_lower[0])*
                           array->d_metadata.d_stride[0] +
                          (i2 - array->d_metadata.d_lower[1])*
                           array->d_metadata.d_stride[1]));
    }
  }
  return sidl_bool__array_zero;
}

/**
 * Retrieve element (i1,i2,i3) of a three-dimensional array.
 */
sidl_bool
sidl_bool__array_get3(const struct sidl_bool__array* array,
                      const int32_t i1,
                      const int32_t i2,
                      const int32_t i3)
{
  if (array && (3 == array->d_metadata.d_dimen)){
    /* unserialize array bounds checking (i.e. avoid strict left to right */
    /* evaluation of && which serializes evaluation) */
    register int c1 = (array->d_metadata.d_lower[0] <= i1);
    register int c2 = (array->d_metadata.d_lower[1] <= i2);
    register int c3 = (array->d_metadata.d_lower[2] <= i3);
    HELPER_VARIABLE;
    c1 = c1 && (array->d_metadata.d_upper[0] >= i1);
    c2 = c2 && (array->d_metadata.d_upper[1] >= i2);
    c3 = c3 && (array->d_metadata.d_upper[2] >= i3);
    if (c1 && c2 && c3) {
      return COPY_VALUE(*(array->d_firstElement +
                          (i1 - array->d_metadata.d_lower[0])*
                           array->d_metadata.d_stride[0] +
                          (i2 - array->d_metadata.d_lower[1])*
                           array->d_metadata.d_stride[1] +
                          (i3 - array->d_metadata.d_lower[2])*
                           array->d_metadata.d_stride[2]));
    }
  }
  return sidl_bool__array_zero;
}

/**
 * Retrieve element (i1,i2,i3,i4) of a four-dimensional array.
 */
sidl_bool
sidl_bool__array_get4(const struct sidl_bool__array* array,
                      const int32_t i1,
                      const int32_t i2,
                      const int32_t i3,
                      const int32_t i4)
{
  if (array && (4 == array->d_metadata.d_dimen)){
    /* unserialize array bounds checking to avoid strict left to right */
    /* evaluation of && which serializes evaluation */
    register int c1 = (array->d_metadata.d_lower[0] <= i1);
    register int c2 = (array->d_metadata.d_lower[1] <= i2);
    register int c3 = (array->d_metadata.d_lower[2] <= i3);
    register int c4 = (array->d_metadata.d_lower[3] <= i4);
    HELPER_VARIABLE;
    c1 = c1 && (array->d_metadata.d_upper[0] >= i1);
    c2 = c2 && (array->d_metadata.d_upper[1] >= i2);
    c3 = c3 && (array->d_metadata.d_upper[2] >= i3);
    c4 = c4 && (array->d_metadata.d_upper[3] >= i4);
    c1 = c1 && c2;
    c3 = c3 && c4;
    if (c1 && c3) {
      return COPY_VALUE(*(array->d_firstElement +
                         (((i1 - array->d_metadata.d_lower[0])*
                          array->d_metadata.d_stride[0] +
                           (i2 - array->d_metadata.d_lower[1])*
                            array->d_metadata.d_stride[1]) +
                          ((i3 - array->d_metadata.d_lower[2])*
                           array->d_metadata.d_stride[2] +
                           (i4 - array->d_metadata.d_lower[3])*
                            array->d_metadata.d_stride[3]))));
    }
  }
  return sidl_bool__array_zero;
}

/**
 * Retrieve element (i1,i2,i3,i4,i5) of a five-dimensional array.
 */
sidl_bool
sidl_bool__array_get5(const struct sidl_bool__array* array,
                      const int32_t i1,
                      const int32_t i2,
                      const int32_t i3,
                      const int32_t i4,
                      const int32_t i5)
{
  if (array && (5 == array->d_metadata.d_dimen)){
    /* unserialize array bounds checking (i.e. avoid strict left to right */
    /* evaluation of && which serializes evaluation) */
    register int c1 = (array->d_metadata.d_lower[0] <= i1);
    register int c2 = (array->d_metadata.d_lower[1] <= i2);
    register int c3 = (array->d_metadata.d_lower[2] <= i3);
    register int c4 = (array->d_metadata.d_lower[3] <= i4);
    register int c5 = (array->d_metadata.d_lower[4] <= i5);
    HELPER_VARIABLE;
    c1 = c1 && (array->d_metadata.d_upper[0] >= i1);
    c2 = c2 && (array->d_metadata.d_upper[1] >= i2);
    c3 = c3 && (array->d_metadata.d_upper[2] >= i3);
    c4 = c4 && (array->d_metadata.d_upper[3] >= i4);
    c5 = c5 && (array->d_metadata.d_upper[4] >= i5);
    c1 = c1 && c2;
    c3 = c3 && c4;
    c1 = c1 && c3;
    if (c1 && c5) {
      return COPY_VALUE(*(array->d_firstElement +
                          (i1 - array->d_metadata.d_lower[0])*
                           array->d_metadata.d_stride[0] +
                          (i2 - array->d_metadata.d_lower[1])*
                           array->d_metadata.d_stride[1] +
                          (i3 - array->d_metadata.d_lower[2])*
                           array->d_metadata.d_stride[2] +
                          (i4 - array->d_metadata.d_lower[3])*
                           array->d_metadata.d_stride[3] +
                          (i5 - array->d_metadata.d_lower[4])*
                           array->d_metadata.d_stride[4]));
    }
  }
  return sidl_bool__array_zero;
}

/**
 * Retrieve element (i1,i2,i3,i4,i5,i6) of a six-dimensional array.
 */
sidl_bool
sidl_bool__array_get6(const struct sidl_bool__array* array,
                      const int32_t i1,
                      const int32_t i2,
                      const int32_t i3,
                      const int32_t i4,
                      const int32_t i5,
                      const int32_t i6)
{
  if (array && (6 == array->d_metadata.d_dimen)){
    /* unserialize array bounds checking (i.e. avoid strict left to right */
    /* evaluation of && which serializes evaluation) */
    register int c1 = (array->d_metadata.d_lower[0] <= i1);
    register int c2 = (array->d_metadata.d_lower[1] <= i2);
    register int c3 = (array->d_metadata.d_lower[2] <= i3);
    register int c4 = (array->d_metadata.d_lower[3] <= i4);
    register int c5 = (array->d_metadata.d_lower[4] <= i5);
    register int c6 = (array->d_metadata.d_lower[5] <= i6);
    HELPER_VARIABLE;
    c1 = c1 && (array->d_metadata.d_upper[0] >= i1);
    c2 = c2 && (array->d_metadata.d_upper[1] >= i2);
    c3 = c3 && (array->d_metadata.d_upper[2] >= i3);
    c4 = c4 && (array->d_metadata.d_upper[3] >= i4);
    c5 = c5 && (array->d_metadata.d_upper[4] >= i5);
    c6 = c6 && (array->d_metadata.d_upper[5] >= i6);
    c1 = c1 && c2;
    c3 = c3 && c4;
    c5 = c5 && c6;
    c1 = c1 && c3;
    if (c1 && c5) {
      return COPY_VALUE(*(array->d_firstElement +
                          (i1 - array->d_metadata.d_lower[0])*
                           array->d_metadata.d_stride[0] +
                          (i2 - array->d_metadata.d_lower[1])*
                           array->d_metadata.d_stride[1] +
                          (i3 - array->d_metadata.d_lower[2])*
                           array->d_metadata.d_stride[2] +
                          (i4 - array->d_metadata.d_lower[3])*
                           array->d_metadata.d_stride[3] +
                          (i5 - array->d_metadata.d_lower[4])*
                           array->d_metadata.d_stride[4] +
                          (i6 - array->d_metadata.d_lower[5])*
                           array->d_metadata.d_stride[5]));
    }
  }
  return sidl_bool__array_zero;
}

/**
 * Retrieve element (i1,i2,i3,i4,i5,i6,i7) of a seven-dimensional array.
 */
sidl_bool
sidl_bool__array_get7(const struct sidl_bool__array* array,
                      const int32_t i1,
                      const int32_t i2,
                      const int32_t i3,
                      const int32_t i4,
                      const int32_t i5,
                      const int32_t i6,
                      const int32_t i7)
{
  if (array) {
    switch(array->d_metadata.d_dimen) {
    case 1: return sidl_bool__array_get1(array, i1);
    case 2: return sidl_bool__array_get2(array, i1, i2);
    case 3: return sidl_bool__array_get3(array, i1, i2, i3);
    case 4: return sidl_bool__array_get4(array, i1, i2, i3, i4);
    case 5: return sidl_bool__array_get5(array, i1, i2, i3, i4, i5);
    case 6: return sidl_bool__array_get6(array, i1, i2, i3, i4, i5, i6);
    case 7:
      {
        /* unserialize array bounds checking (i.e. avoid strict left to right */
        /* evaluation of && which serializes evaluation) */
        register int c1 = (array->d_metadata.d_lower[0] <= i1);
        register int c2 = (array->d_metadata.d_lower[1] <= i2);
        register int c3 = (array->d_metadata.d_lower[2] <= i3);
        register int c4 = (array->d_metadata.d_lower[3] <= i4);
        register int c5 = (array->d_metadata.d_lower[4] <= i5);
        register int c6 = (array->d_metadata.d_lower[5] <= i6);
        register int c7 = (array->d_metadata.d_lower[6] <= i7);
        HELPER_VARIABLE;
        c1 = c1 && (array->d_metadata.d_upper[0] >= i1);
        c2 = c2 && (array->d_metadata.d_upper[1] >= i2);
        c3 = c3 && (array->d_metadata.d_upper[2] >= i3);
        c4 = c4 && (array->d_metadata.d_upper[3] >= i4);
        c5 = c5 && (array->d_metadata.d_upper[4] >= i5);
        c6 = c6 && (array->d_metadata.d_upper[5] >= i6);
        c7 = c7 && (array->d_metadata.d_upper[6] >= i7);
        c1 = c1 && c2;
        c3 = c3 && c4;
        c5 = c5 && c6;
        c1 = c1 && c3;
        c5 = c5 && c7;
        if (c1 && c5) {
          return COPY_VALUE(*(array->d_firstElement +
                              (i1 - array->d_metadata.d_lower[0])*
                               array->d_metadata.d_stride[0] +
                              (i2 - array->d_metadata.d_lower[1])*
                               array->d_metadata.d_stride[1] +
                              (i3 - array->d_metadata.d_lower[2])*
                               array->d_metadata.d_stride[2] +
                              (i4 - array->d_metadata.d_lower[3])*
                               array->d_metadata.d_stride[3] +
                              (i5 - array->d_metadata.d_lower[4])*
                               array->d_metadata.d_stride[4] +
                              (i6 - array->d_metadata.d_lower[5])*
                               array->d_metadata.d_stride[5] +
                              (i7 - array->d_metadata.d_lower[6])*
                               array->d_metadata.d_stride[6]));
        }
      }
    }
  }
  return sidl_bool__array_zero;
}

/**
 * Retrieve element indices of an n-dimensional array. Indices is assumed
 * to have the right number of elements for the dimension of array.
 */
sidl_bool
sidl_bool__array_get(const struct sidl_bool__array* array,
                     const int32_t indices[])
{
  if (array) {
    sidl_bool *result = array->d_firstElement;
    int32_t i = 0;
    HELPER_VARIABLE;
    while (i < array->d_metadata.d_dimen) {
      if ((indices[i] < array->d_metadata.d_lower[i]) ||
          (indices[i] > array->d_metadata.d_upper[i]))
        return sidl_bool__array_zero;
      result += ((indices[i] - array->d_metadata.d_lower[i])*
       array->d_metadata.d_stride[i]);
      ++i;
    }
    return COPY_VALUE(*result);
  }
  return sidl_bool__array_zero;
}

/**
 * Set element i1 of a one-dimensional array to value.
 */
void
sidl_bool__array_set1(struct sidl_bool__array* array,
                      const int32_t i1,
                      const sidl_bool value)
{
  if (array && (1 == array->d_metadata.d_dimen) &&
      ((array->d_metadata.d_lower[0] <= i1) &&
       (array->d_metadata.d_upper[0] >= i1))) {
    HELPER_VARIABLE;
    DESTROY_VALUE(*(array->d_firstElement +
      (i1 - array->d_metadata.d_lower[0])*array->d_metadata.d_stride[0]));
    *(array->d_firstElement +
      (i1 - array->d_metadata.d_lower[0])*array->d_metadata.d_stride[0]) =
       COPY_VALUE(value);
  }
}

/**
 * Set element (i1,i2) of a two-dimensional array to value.
 */
void
sidl_bool__array_set2(struct sidl_bool__array* array,
                      const int32_t i1,
                      const int32_t i2,
                      const sidl_bool value)
{
  if (array && (2 == array->d_metadata.d_dimen)){
    /* unserialize array bounds checking (i.e. avoid strict left to right */
    /* evaluation of && which serializes evaluation) */
    register int c1 = (array->d_metadata.d_lower[0] <= i1);
    register int c2 = (array->d_metadata.d_upper[0] >= i1);
    register int c3 = (array->d_metadata.d_lower[1] <= i2);
    register int c4 = (array->d_metadata.d_upper[1] >= i2);
    HELPER_VARIABLE;
    c1 = c1 && c2;
    c3 = c3 && c4;
    if (c1 && c3) {
      DESTROY_VALUE(*(array->d_firstElement +
        (i1 - array->d_metadata.d_lower[0])*array->d_metadata.d_stride[0] +
        (i2 - array->d_metadata.d_lower[1])*array->d_metadata.d_stride[1]));
      *(array->d_firstElement +
        (i1 - array->d_metadata.d_lower[0])*array->d_metadata.d_stride[0] +
        (i2 - array->d_metadata.d_lower[1])*array->d_metadata.d_stride[1]) =
         COPY_VALUE(value);
    }
  }
}

/**
 * Set element (i1,i2,i3) of a three-dimensional array to value.
 */
void
sidl_bool__array_set3(struct sidl_bool__array* array,
                      const int32_t i1,
                      const int32_t i2,
                      const int32_t i3,
                      const sidl_bool value)
{
  if (array && (3 == array->d_metadata.d_dimen)){
    /* unserialize array bounds checking (i.e. avoid strict left to right */
    /* evaluation of && which serializes evaluation) */
    register int c1 = (array->d_metadata.d_lower[0] <= i1);
    register int c2 = (array->d_metadata.d_lower[1] <= i2);
    register int c3 = (array->d_metadata.d_lower[2] <= i3);
    HELPER_VARIABLE;
    c1 = c1 && (array->d_metadata.d_upper[0] >= i1);
    c2 = c2 && (array->d_metadata.d_upper[1] >= i2);
    c3 = c3 && (array->d_metadata.d_upper[2] >= i3);
    if (c1 && c2 && c3) {
      DESTROY_VALUE(*(array->d_firstElement +
        (i1 - array->d_metadata.d_lower[0])*array->d_metadata.d_stride[0] +
        (i2 - array->d_metadata.d_lower[1])*array->d_metadata.d_stride[1] +
        (i3 - array->d_metadata.d_lower[2])*array->d_metadata.d_stride[2]));
      *(array->d_firstElement +
        (i1 - array->d_metadata.d_lower[0])*array->d_metadata.d_stride[0] +
        (i2 - array->d_metadata.d_lower[1])*array->d_metadata.d_stride[1] +
        (i3 - array->d_metadata.d_lower[2])*array->d_metadata.d_stride[2]) =
         COPY_VALUE(value);
    }
  }
}

/**
 * Set element (i1,i2,i3,i4) of a four-dimensional array to value.
 */
void
sidl_bool__array_set4(struct sidl_bool__array* array,
                      const int32_t i1,
                      const int32_t i2,
                      const int32_t i3,
                      const int32_t i4,
                      const sidl_bool value)
{
  if (array && (array->d_metadata.d_dimen == 4)) {
    /* unserialize array bounds checking to. avoid strict left to right */
    /* evaluation of && which serializes evaluation */
    register int c1 = (array->d_metadata.d_lower[0] <= i1);
    register int c2 = (array->d_metadata.d_lower[1] <= i2);
    register int c3 = (array->d_metadata.d_lower[2] <= i3);
    register int c4 = (array->d_metadata.d_lower[3] <= i4);
    HELPER_VARIABLE;
    c1 = c1 && (array->d_metadata.d_upper[0] >= i1);
    c2 = c2 && (array->d_metadata.d_upper[1] >= i2);
    c3 = c3 && (array->d_metadata.d_upper[2] >= i3);
    c4 = c4 && (array->d_metadata.d_upper[3] >= i4);
    c1 = c1 && c2;
    c3 = c3 && c4;
    if (c1 && c3) {
      DESTROY_VALUE(*(array->d_firstElement +
        (((i1 - array->d_metadata.d_lower[0])*array->d_metadata.d_stride[0] +
          (i2 - array->d_metadata.d_lower[1])*array->d_metadata.d_stride[1]) +
         ((i3 - array->d_metadata.d_lower[2])*array->d_metadata.d_stride[2] +
          (i4 - array->d_metadata.d_lower[3])*
           array->d_metadata.d_stride[3]))));
      *(array->d_firstElement +
        (((i1 - array->d_metadata.d_lower[0])*array->d_metadata.d_stride[0] +
          (i2 - array->d_metadata.d_lower[1])*array->d_metadata.d_stride[1]) +
         ((i3 - array->d_metadata.d_lower[2])*array->d_metadata.d_stride[2] +
         (i4 - array->d_metadata.d_lower[3])*array->d_metadata.d_stride[3]))) =
         COPY_VALUE(value);
    }
  }
}

/**
 * Set element (i1,i2,i3,i4,i5) of a five-dimensional array to value.
 */
void
sidl_bool__array_set5(struct sidl_bool__array* array,
                      const int32_t i1,
                      const int32_t i2,
                      const int32_t i3,
                      const int32_t i4,
                      const int32_t i5,
                      const sidl_bool value)
{
  if (array && (5 == array->d_metadata.d_dimen)){
    /* unserialize array bounds checking (i.e. avoid strict left to right */
    /* evaluation of && which serializes evaluation) */
    register int c1 = (array->d_metadata.d_lower[0] <= i1);
    register int c2 = (array->d_metadata.d_lower[1] <= i2);
    register int c3 = (array->d_metadata.d_lower[2] <= i3);
    register int c4 = (array->d_metadata.d_lower[3] <= i4);
    register int c5 = (array->d_metadata.d_lower[4] <= i5);
    HELPER_VARIABLE;
    c1 = c1 && (array->d_metadata.d_upper[0] >= i1);
    c2 = c2 && (array->d_metadata.d_upper[1] >= i2);
    c3 = c3 && (array->d_metadata.d_upper[2] >= i3);
    c4 = c4 && (array->d_metadata.d_upper[3] >= i4);
    c5 = c5 && (array->d_metadata.d_upper[4] >= i5);
    c1 = c1 && c2;
    c3 = c3 && c4;
    c1 = c1 && c3;
    if (c1 && c5) {
      DESTROY_VALUE(*(array->d_firstElement +
        (i1 - array->d_metadata.d_lower[0])*array->d_metadata.d_stride[0] +
        (i2 - array->d_metadata.d_lower[1])*array->d_metadata.d_stride[1] +
        (i3 - array->d_metadata.d_lower[2])*array->d_metadata.d_stride[2] +
        (i4 - array->d_metadata.d_lower[3])*array->d_metadata.d_stride[3] +
        (i5 - array->d_metadata.d_lower[4])*array->d_metadata.d_stride[4]));
      *(array->d_firstElement +
        (i1 - array->d_metadata.d_lower[0])*array->d_metadata.d_stride[0] +
        (i2 - array->d_metadata.d_lower[1])*array->d_metadata.d_stride[1] +
        (i3 - array->d_metadata.d_lower[2])*array->d_metadata.d_stride[2] +
        (i4 - array->d_metadata.d_lower[3])*array->d_metadata.d_stride[3] +
        (i5 - array->d_metadata.d_lower[4])*array->d_metadata.d_stride[4]) =
         COPY_VALUE(value);
    }
  }
}

/**
 * Set element (i1,i2,i3,i4,i5,i6) of a six-dimensional array to value.
 */
void
sidl_bool__array_set6(struct sidl_bool__array* array,
                      const int32_t i1,
                      const int32_t i2,
                      const int32_t i3,
                      const int32_t i4,
                      const int32_t i5,
                      const int32_t i6,
                      const sidl_bool value)
{
  if (array && (6 == array->d_metadata.d_dimen)){
    /* unserialize array bounds checking (i.e. avoid strict left to right */
    /* evaluation of && which serializes evaluation) */
    register int c1 = (array->d_metadata.d_lower[0] <= i1);
    register int c2 = (array->d_metadata.d_lower[1] <= i2);
    register int c3 = (array->d_metadata.d_lower[2] <= i3);
    register int c4 = (array->d_metadata.d_lower[3] <= i4);
    register int c5 = (array->d_metadata.d_lower[4] <= i5);
    register int c6 = (array->d_metadata.d_lower[5] <= i6);
    HELPER_VARIABLE;
    c1 = c1 && (array->d_metadata.d_upper[0] >= i1);
    c2 = c2 && (array->d_metadata.d_upper[1] >= i2);
    c3 = c3 && (array->d_metadata.d_upper[2] >= i3);
    c4 = c4 && (array->d_metadata.d_upper[3] >= i4);
    c5 = c5 && (array->d_metadata.d_upper[4] >= i5);
    c6 = c6 && (array->d_metadata.d_upper[5] >= i6);
    c1 = c1 && c2;
    c3 = c3 && c4;
    c5 = c5 && c6;
    c1 = c1 && c3;
    if (c1 && c5) {
      DESTROY_VALUE(*(array->d_firstElement +
        (i1 - array->d_metadata.d_lower[0])*array->d_metadata.d_stride[0] +
        (i2 - array->d_metadata.d_lower[1])*array->d_metadata.d_stride[1] +
        (i3 - array->d_metadata.d_lower[2])*array->d_metadata.d_stride[2] +
        (i4 - array->d_metadata.d_lower[3])*array->d_metadata.d_stride[3] +
        (i5 - array->d_metadata.d_lower[4])*array->d_metadata.d_stride[4] +
        (i6 - array->d_metadata.d_lower[5])*array->d_metadata.d_stride[5]));
      *(array->d_firstElement +
        (i1 - array->d_metadata.d_lower[0])*array->d_metadata.d_stride[0] +
        (i2 - array->d_metadata.d_lower[1])*array->d_metadata.d_stride[1] +
        (i3 - array->d_metadata.d_lower[2])*array->d_metadata.d_stride[2] +
        (i4 - array->d_metadata.d_lower[3])*array->d_metadata.d_stride[3] +
        (i5 - array->d_metadata.d_lower[4])*array->d_metadata.d_stride[4] +
        (i6 - array->d_metadata.d_lower[5])*array->d_metadata.d_stride[5]) =
         COPY_VALUE(value);
    }
  }
}

/**
 * Set element (i1,i2,i3,i4,i5,i6,i7) of a seven-dimensional array to value.
 */
void
sidl_bool__array_set7(struct sidl_bool__array* array,
                      const int32_t i1,
                      const int32_t i2,
                      const int32_t i3,
                      const int32_t i4,
                      const int32_t i5,
                      const int32_t i6,
                      const int32_t i7,
                      const sidl_bool value)
{
  if (array) {
    switch(array->d_metadata.d_dimen) {
    case 1: sidl_bool__array_set1(array, i1, value); break;
    case 2: sidl_bool__array_set2(array, i1, i2, value); break;
    case 3: sidl_bool__array_set3(array, i1, i2, i3, value); break;
    case 4: sidl_bool__array_set4(array, i1, i2, i3, i4, value); break;
    case 5: sidl_bool__array_set5(array, i1, i2, i3, i4, i5, value); break;
    case 6: sidl_bool__array_set6(array, i1, i2, i3, i4, i5, i6, value); break;
    case 7:
      {
        /* unserialize array bounds checking (i.e. avoid strict left to right */
        /* evaluation of && which serializes evaluation) */
        register int c1 = (array->d_metadata.d_lower[0] <= i1);
        register int c2 = (array->d_metadata.d_lower[1] <= i2);
        register int c3 = (array->d_metadata.d_lower[2] <= i3);
        register int c4 = (array->d_metadata.d_lower[3] <= i4);
        register int c5 = (array->d_metadata.d_lower[4] <= i5);
        register int c6 = (array->d_metadata.d_lower[5] <= i6);
        register int c7 = (array->d_metadata.d_lower[6] <= i7);
        HELPER_VARIABLE;
        c1 = c1 && (array->d_metadata.d_upper[0] >= i1);
        c2 = c2 && (array->d_metadata.d_upper[1] >= i2);
        c3 = c3 && (array->d_metadata.d_upper[2] >= i3);
        c4 = c4 && (array->d_metadata.d_upper[3] >= i4);
        c5 = c5 && (array->d_metadata.d_upper[4] >= i5);
        c6 = c6 && (array->d_metadata.d_upper[5] >= i6);
        c7 = c7 && (array->d_metadata.d_upper[6] >= i7);
        c1 = c1 && c2;
        c3 = c3 && c4;
        c5 = c5 && c6;
        c1 = c1 && c3;
        c5 = c5 && c7;
        if (c1 && c5) {
           DESTROY_VALUE(*(array->d_firstElement +
            (i1 - array->d_metadata.d_lower[0])*array->d_metadata.d_stride[0] +
            (i2 - array->d_metadata.d_lower[1])*array->d_metadata.d_stride[1] +
            (i3 - array->d_metadata.d_lower[2])*array->d_metadata.d_stride[2] +
            (i4 - array->d_metadata.d_lower[3])*array->d_metadata.d_stride[3] +
            (i5 - array->d_metadata.d_lower[4])*array->d_metadata.d_stride[4] +
            (i6 - array->d_metadata.d_lower[5])*array->d_metadata.d_stride[5] +
            (i7 - array->d_metadata.d_lower[6])*array->d_metadata.d_stride[6]));
          *(array->d_firstElement +
            (i1 - array->d_metadata.d_lower[0])*array->d_metadata.d_stride[0] +
            (i2 - array->d_metadata.d_lower[1])*array->d_metadata.d_stride[1] +
            (i3 - array->d_metadata.d_lower[2])*array->d_metadata.d_stride[2] +
            (i4 - array->d_metadata.d_lower[3])*array->d_metadata.d_stride[3] +
            (i5 - array->d_metadata.d_lower[4])*array->d_metadata.d_stride[4] +
            (i6 - array->d_metadata.d_lower[5])*array->d_metadata.d_stride[5] +
            (i7 - array->d_metadata.d_lower[6])*array->d_metadata.d_stride[6])
             = COPY_VALUE(value);
        }
      }
    }
  }
}

/**
 * Set element indices of an n-dimensional array to value. indices is assumed
 * to have the right number of elements for the dimension of array.
 */
void
sidl_bool__array_set(struct sidl_bool__array* array,
                     const int32_t indices[],
                     const sidl_bool value)
{
  if (array) {
    sidl_bool *result = array->d_firstElement;
    int32_t i = 0;
    HELPER_VARIABLE;
    while (i < array->d_metadata.d_dimen) {
      if ((indices[i] < array->d_metadata.d_lower[i]) ||
          (indices[i] > array->d_metadata.d_upper[i])) return;
      result += ((indices[i] - array->d_metadata.d_lower[i])*
       array->d_metadata.d_stride[i]);
      ++i;
    }
    DESTROY_VALUE(*result);
    *result = COPY_VALUE(value);
  }
}

/**
 * Return the dimension of array. If the array pointer is NULL,
 * zero is returned.
 */
int32_t
sidl_bool__array_dimen(const struct sidl_bool__array* array)
{
  return sidl__array_dimen((const struct sidl__array*)array);
}

/**
 * Return the lower index bound on dimension ind. If ind is not a valid
 * dimension, zero is returned. The valid range for ind is 0 to dimen-1.
 */
int32_t
sidl_bool__array_lower(const struct sidl_bool__array* array,
                       const int32_t ind)
{
  return sidl__array_lower((const struct sidl__array*)array, ind);
}

/**
 * Return the upper index bound on dimension ind. If ind is not a valid
 * dimension, negative one is returned. The valid range for ind is 0 to
 * dimen-1.
 */
int32_t
sidl_bool__array_upper(const struct sidl_bool__array* array,
                       const int32_t ind)
{
  return sidl__array_upper((const struct sidl__array*)array, ind);
}

/**
 * Return the number of element in dimension ind. If ind is not a valid
 * dimension, negative one is returned. The valid range for ind is 0 to
 * dimen-1.
 */
int32_t
sidl_bool__array_length(const struct sidl_bool__array* array,
                        const int32_t ind)
{
  return sidl__array_length((const struct sidl__array*)array, ind);
}

/**
 * Return the stride of dimension ind. If ind is not a valid
 * dimension, zero is returned. The valid range for ind is 0 to
 * dimen-1.
 */
int32_t
sidl_bool__array_stride(const struct sidl_bool__array* array,
                        const int32_t ind)
{
  return sidl__array_stride((const struct sidl__array*)array, ind);
}

/**
 * Return a true value iff the array is a contiguous column-major ordered
 * array.  A NULL array argument causes 0 to be returned.
 */
sidl_bool
sidl_bool__array_isColumnOrder(const struct sidl_bool__array* array)
{
  return sidl__array_isColumnOrder((const struct sidl__array*)array);
}

/**
 * Return a true value iff the array is a contiguous row-major ordered
 * array.  A NULL array argument causes 0 to be returned.
 */
sidl_bool
sidl_bool__array_isRowOrder(const struct sidl_bool__array* array)
{
  return sidl__array_isRowOrder((const struct sidl__array*)array);
}

/**
 * Copy the contents of one array (src) to a second array (dest). For
 * the copy to take place, both arrays must exist and be of the same
 * dimension. This method will not modify dest's size, index bounds,
 * or stride; only the array element values of dest may be changed by
 * this function. No part of src is ever changed by copy.
 * 
 * On exit, dest[i][j][k]... = src[i][j][k]... for all indices i,j,k...
 * that are in both arrays. If dest and src have no indices in common,
 * nothing is copied. For example, if src is a 1-d array with elements
 * 0-5 and dest is a 1-d array with elements 2-3, this function will
 * make the following assignments:
 *   dest[2] = src[2],
 *   dest[3] = src[3].
 * The function copied the elements that both arrays have in common.
 * If dest had elements 4-10, this function will make the following
 * assignments:
 *   dest[4] = src[4],
 *   dest[5] = src[5].
 * 
 */
void
sidl_bool__array_copy(const struct sidl_bool__array* src,
                            struct sidl_bool__array* dest)
{
  if (src && dest && (src != dest) &&
     (src->d_metadata.d_dimen == dest->d_metadata.d_dimen) &&
      src->d_metadata.d_dimen) {
    const int32_t dimen = src->d_metadata.d_dimen;
    int32_t * restrict overlap = (int32_t *)malloc(sizeof(int32_t)*(size_t)dimen*4);
    HELPER_VARIABLE;
    if (overlap) {
      register sidl_bool const * restrict srcFirst =
        src->d_firstElement;
      register sidl_bool * restrict destFirst =
        dest->d_firstElement;
      register int32_t i;
      int32_t * restrict current = overlap + dimen;
      int32_t * restrict src_stride = current + dimen;
      int32_t * restrict dst_stride = src_stride + dimen;
      int32_t lower, upper, fastMover = dimen - 1, moverRank = 0;
      for(i = 0; i < dimen; ++i){
        lower = MAX(src->d_metadata.d_lower[i],dest->d_metadata.d_lower[i]);
        upper = MIN(src->d_metadata.d_upper[i],dest->d_metadata.d_upper[i]);
        overlap[i] = 1 + upper - lower;
        if (overlap[i] <= 0) goto cleanup;
        srcFirst += (src->d_metadata.d_stride[i]*
           (lower - src->d_metadata.d_lower[i]));
        destFirst += (dest->d_metadata.d_stride[i]*
           (lower - dest->d_metadata.d_lower[i]));
        current[i] = 0;
        src_stride[i] = src->d_metadata.d_stride[i];
        dst_stride[i] = dest->d_metadata.d_stride[i];
        if (((src_stride[i] == 1) || (src_stride[i] == -1) ||
             (dst_stride[i] == 1) || (dst_stride[i] == -1)) &&
            (overlap[i] >= moverRank)) {
          moverRank = overlap[i];
          fastMover = i;
        }
      }
      if (fastMover != dimen - 1) { /* move stride 1 to inner loop */
        /* this *might* improve cache performance */
        swap_i32(&overlap[fastMover], &overlap[dimen-1]);
        swap_i32(&src_stride[fastMover], &src_stride[dimen-1]);
        swap_i32(&dst_stride[fastMover], &dst_stride[dimen-1]);
      }
      switch(dimen) {
      case 1: /* handle a common special case */
        {
          const int32_t bound = overlap[0];
          const int32_t dstride = dst_stride[0];
          const int32_t sstride = src_stride[0];
          for(i = 0; i < bound; ++i) {
            DESTROY_VALUE(*destFirst);
            *destFirst = COPY_VALUE(*srcFirst);
            destFirst += dstride;
            srcFirst += sstride;
          }
        }
        break;
      case 2: /* handle a common special case (2-d arrays) */
        {
          const int32_t bound0 = overlap[0];
          const int32_t bound1 = overlap[1];
          const int32_t dstride1 = dst_stride[1];
          const int32_t sstride1 = src_stride[1];
          const int32_t dstride0 = dst_stride[0] - bound1*dstride1;
          const int32_t sstride0 = src_stride[0] - bound1*sstride1;
          int32_t j;
          for(i = 0; i < bound0; ++i) {
            for(j = 0; j < bound1; ++j) {
              DESTROY_VALUE(*destFirst);
              *destFirst = COPY_VALUE(*srcFirst);
              destFirst += dstride1;
              srcFirst += sstride1;
            }
            destFirst += dstride0;
            srcFirst += sstride0;
          }
        }
        break;
      case 3: /* handle a common special case (3-d arrays) */
        {
          const int32_t bound0 = overlap[0];
          const int32_t bound1 = overlap[1];
          const int32_t bound2 = overlap[2];
          const int32_t dstride2 = dst_stride[2];
          const int32_t sstride2 = src_stride[2];
          const int32_t dstride1 = dst_stride[1] - bound2*dstride2;
          const int32_t sstride1 = src_stride[1] - bound2*sstride2;
          const int32_t dstride0 = dst_stride[0] - bound1*(dstride1 + bound2*dstride2);
          const int32_t sstride0 = src_stride[0] - bound1*(sstride1 + bound2*sstride2);
          
          int32_t j, k;
          for(i = 0; i < bound0; ++i) {
            for(j = 0; j < bound1; ++j) {
              for(k = 0; k < bound2; ++k) {
                DESTROY_VALUE(*destFirst);
                *destFirst = COPY_VALUE(*srcFirst);
                destFirst += dstride2;
                srcFirst += sstride2;
              }
              destFirst += dstride1;
              srcFirst += sstride1;
            }
            destFirst += dstride0;
            srcFirst += sstride0;
          }
        }
        break;
      default: /* handle the general case */
        do {
          DESTROY_VALUE(*destFirst);
          *destFirst = COPY_VALUE(*srcFirst);
          /* the whole point of this for-loop is to move forward one element */
          for(i = dimen - 1; i >= 0; --i) {
            ++(current[i]);
            if (current[i] >= overlap[i]) {
            /* this dimension has been enumerated already reset to beginning */
              current[i] = 0;
              /* prepare to next iteration of for-loop for i-1 */
              destFirst -= ((overlap[i]-1) * dst_stride[i]);
              srcFirst -= ((overlap[i]-1) * src_stride[i]);
            }
            else {
              /* move forward one element in dimension i */
              destFirst += dst_stride[i];
              srcFirst += src_stride[i];
              break; /* exit for loop */
            }
          }
        } while (i >= 0);
        break;
      }
cleanup:
      free(overlap);
    }
  }
}

/**
 * If necessary, convert a general matrix into a matrix with the required
 * properties. This checks the dimension and ordering of the matrix.
 * If both these match, it simply returns a new reference to the existing
 * matrix. If the dimension of the incoming array doesn't match, it
 * returns NULL. If the ordering of the incoming array doesn't match the
 * specification, a new array is created with the desired ordering and
 * the content of the incoming array is copied to the new array.
 * 
 * The ordering parameter should be one of the constants defined in
 * enum sidl_array_ordering (e.g. sidl_general_order,
 * sidl_column_major_order, or sidl_row_major_order). If you
 * specify sidl_general_order, this routine will only check the
 * dimension because any matrix is sidl_general_order.
 * 
 * The caller assumes ownership of the returned reference unless it's NULL.
 * 
 */
struct sidl_bool__array*
sidl_bool__array_ensure(struct sidl_bool__array* src,
                        int32_t                dimen,
                        int                    ordering)
{
  struct sidl_bool__array* result = NULL;
  if (src && (src->d_metadata.d_dimen == dimen)) {
    switch(ordering) {
    case sidl_column_major_order:
      if (sidl_bool__array_isColumnOrder(src)) {
        sidl_bool__array_addRef(src);
        result = src;
      }
      else {
        result = sidl_bool__array_createCol
          (dimen, src->d_metadata.d_lower, src->d_metadata.d_upper);
        sidl_bool__array_copy(src, result);
      }
      break;
    case sidl_row_major_order:
      if (sidl_bool__array_isRowOrder(src)) {
        sidl_bool__array_addRef(src);
        result = src;
      }
      else {
        result = sidl_bool__array_createRow
          (dimen, src->d_metadata.d_lower, src->d_metadata.d_upper);
        sidl_bool__array_copy(src, result);
      }
      break;
    default:
      sidl_bool__array_addRef(src);
      result = src;
      break;
    }
  }
  return result;
}

/**
 * Return a pointer to the first element of the data space of the array.
 * Using the lower and stride information, you can access elements of the
 * array without using a function call. NULL is returned iff array is NULL.
 * 
 * Direct access should only be used when efficiency requires it.
 */
sidl_bool *
sidl_bool__array_first(const struct sidl_bool__array* array)
{
  return array ? array->d_firstElement : NULL;
}

