re PR fortran/35993 (wrong answer for all array intrinsics with scalar mask)
authorThomas Koenig <tkoenig@gcc.gnu.org>
Wed, 30 Apr 2008 16:56:01 +0000 (16:56 +0000)
committerThomas Koenig <tkoenig@gcc.gnu.org>
Wed, 30 Apr 2008 16:56:01 +0000 (16:56 +0000)
2008-04-30  Thomas Koenig  <tkoenig@gcc.gnu.org>

PR libfortran/35993
* ifunction.m4 (SCALAR_ARRAY_FUNCTION):  Use correct
implementation for multi-dimensional return arrays when
the mask is .false.
* generated/maxloc1_16_i1.c: Regenerated.
* generated/maxloc1_16_i16.c: Regenerated.
* generated/maxloc1_16_i2.c: Regenerated.
* generated/maxloc1_16_i4.c: Regenerated.
* generated/maxloc1_16_i8.c: Regenerated.
* generated/maxloc1_16_r10.c: Regenerated.
* generated/maxloc1_16_r16.c: Regenerated.
* generated/maxloc1_16_r4.c: Regenerated.
* generated/maxloc1_16_r8.c: Regenerated.
* generated/maxloc1_4_i1.c: Regenerated.
* generated/maxloc1_4_i16.c: Regenerated.
* generated/maxloc1_4_i2.c: Regenerated.
* generated/maxloc1_4_i4.c: Regenerated.
* generated/maxloc1_4_i8.c: Regenerated.
* generated/maxloc1_4_r10.c: Regenerated.
* generated/maxloc1_4_r16.c: Regenerated.
* generated/maxloc1_4_r4.c: Regenerated.
* generated/maxloc1_4_r8.c: Regenerated.
* generated/maxloc1_8_i1.c: Regenerated.
* generated/maxloc1_8_i16.c: Regenerated.
* generated/maxloc1_8_i2.c: Regenerated.
* generated/maxloc1_8_i4.c: Regenerated.
* generated/maxloc1_8_i8.c: Regenerated.
* generated/maxloc1_8_r10.c: Regenerated.
* generated/maxloc1_8_r16.c: Regenerated.
* generated/maxloc1_8_r4.c: Regenerated.
* generated/maxloc1_8_r8.c: Regenerated.
* generated/maxval_i1.c: Regenerated.
* generated/maxval_i16.c: Regenerated.
* generated/maxval_i2.c: Regenerated.
* generated/maxval_i4.c: Regenerated.
* generated/maxval_i8.c: Regenerated.
* generated/maxval_r10.c: Regenerated.
* generated/maxval_r16.c: Regenerated.
* generated/maxval_r4.c: Regenerated.
* generated/maxval_r8.c: Regenerated.
* generated/minloc1_16_i1.c: Regenerated.
* generated/minloc1_16_i16.c: Regenerated.
* generated/minloc1_16_i2.c: Regenerated.
* generated/minloc1_16_i4.c: Regenerated.
* generated/minloc1_16_i8.c: Regenerated.
* generated/minloc1_16_r10.c: Regenerated.
* generated/minloc1_16_r16.c: Regenerated.
* generated/minloc1_16_r4.c: Regenerated.
* generated/minloc1_16_r8.c: Regenerated.
* generated/minloc1_4_i1.c: Regenerated.
* generated/minloc1_4_i16.c: Regenerated.
* generated/minloc1_4_i2.c: Regenerated.
* generated/minloc1_4_i4.c: Regenerated.
* generated/minloc1_4_i8.c: Regenerated.
* generated/minloc1_4_r10.c: Regenerated.
* generated/minloc1_4_r16.c: Regenerated.
* generated/minloc1_4_r4.c: Regenerated.
* generated/minloc1_4_r8.c: Regenerated.
* generated/minloc1_8_i1.c: Regenerated.
* generated/minloc1_8_i16.c: Regenerated.
* generated/minloc1_8_i2.c: Regenerated.
* generated/minloc1_8_i4.c: Regenerated.
* generated/minloc1_8_i8.c: Regenerated.
* generated/minloc1_8_r10.c: Regenerated.
* generated/minloc1_8_r16.c: Regenerated.
* generated/minloc1_8_r4.c: Regenerated.
* generated/minloc1_8_r8.c: Regenerated.
* generated/minval_i1.c: Regenerated.
* generated/minval_i16.c: Regenerated.
* generated/minval_i2.c: Regenerated.
* generated/minval_i4.c: Regenerated.
* generated/minval_i8.c: Regenerated.
* generated/minval_r10.c: Regenerated.
* generated/minval_r16.c: Regenerated.
* generated/minval_r4.c: Regenerated.
* generated/minval_r8.c: Regenerated.
* generated/product_c10.c: Regenerated.
* generated/product_c16.c: Regenerated.
* generated/product_c4.c: Regenerated.
* generated/product_c8.c: Regenerated.
* generated/product_i1.c: Regenerated.
* generated/product_i16.c: Regenerated.
* generated/product_i2.c: Regenerated.
* generated/product_i4.c: Regenerated.
* generated/product_i8.c: Regenerated.
* generated/product_r10.c: Regenerated.
* generated/product_r16.c: Regenerated.
* generated/product_r4.c: Regenerated.
* generated/product_r8.c: Regenerated.
* generated/sum_c10.c: Regenerated.
* generated/sum_c16.c: Regenerated.
* generated/sum_c4.c: Regenerated.
* generated/sum_c8.c: Regenerated.
* generated/sum_i1.c: Regenerated.
* generated/sum_i16.c: Regenerated.
* generated/sum_i2.c: Regenerated.
* generated/sum_i4.c: Regenerated.
* generated/sum_i8.c: Regenerated.
* generated/sum_r10.c: Regenerated.
* generated/sum_r16.c: Regenerated.
* generated/sum_r4.c: Regenerated.
* generated/sum_r8.c: Regenerated.

2008-04-30  Thomas Koenig  <tkoenig@gcc.gnu.org>

PR libfortran/35993
* gfortran.dg/intrinsic_product_1.f90:  New test case.

From-SVN: r134830

102 files changed:
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/intrinsic_product_1.f90 [new file with mode: 0644]
libgfortran/ChangeLog
libgfortran/generated/maxloc1_16_i1.c
libgfortran/generated/maxloc1_16_i16.c
libgfortran/generated/maxloc1_16_i2.c
libgfortran/generated/maxloc1_16_i4.c
libgfortran/generated/maxloc1_16_i8.c
libgfortran/generated/maxloc1_16_r10.c
libgfortran/generated/maxloc1_16_r16.c
libgfortran/generated/maxloc1_16_r4.c
libgfortran/generated/maxloc1_16_r8.c
libgfortran/generated/maxloc1_4_i1.c
libgfortran/generated/maxloc1_4_i16.c
libgfortran/generated/maxloc1_4_i2.c
libgfortran/generated/maxloc1_4_i4.c
libgfortran/generated/maxloc1_4_i8.c
libgfortran/generated/maxloc1_4_r10.c
libgfortran/generated/maxloc1_4_r16.c
libgfortran/generated/maxloc1_4_r4.c
libgfortran/generated/maxloc1_4_r8.c
libgfortran/generated/maxloc1_8_i1.c
libgfortran/generated/maxloc1_8_i16.c
libgfortran/generated/maxloc1_8_i2.c
libgfortran/generated/maxloc1_8_i4.c
libgfortran/generated/maxloc1_8_i8.c
libgfortran/generated/maxloc1_8_r10.c
libgfortran/generated/maxloc1_8_r16.c
libgfortran/generated/maxloc1_8_r4.c
libgfortran/generated/maxloc1_8_r8.c
libgfortran/generated/maxval_i1.c
libgfortran/generated/maxval_i16.c
libgfortran/generated/maxval_i2.c
libgfortran/generated/maxval_i4.c
libgfortran/generated/maxval_i8.c
libgfortran/generated/maxval_r10.c
libgfortran/generated/maxval_r16.c
libgfortran/generated/maxval_r4.c
libgfortran/generated/maxval_r8.c
libgfortran/generated/minloc1_16_i1.c
libgfortran/generated/minloc1_16_i16.c
libgfortran/generated/minloc1_16_i2.c
libgfortran/generated/minloc1_16_i4.c
libgfortran/generated/minloc1_16_i8.c
libgfortran/generated/minloc1_16_r10.c
libgfortran/generated/minloc1_16_r16.c
libgfortran/generated/minloc1_16_r4.c
libgfortran/generated/minloc1_16_r8.c
libgfortran/generated/minloc1_4_i1.c
libgfortran/generated/minloc1_4_i16.c
libgfortran/generated/minloc1_4_i2.c
libgfortran/generated/minloc1_4_i4.c
libgfortran/generated/minloc1_4_i8.c
libgfortran/generated/minloc1_4_r10.c
libgfortran/generated/minloc1_4_r16.c
libgfortran/generated/minloc1_4_r4.c
libgfortran/generated/minloc1_4_r8.c
libgfortran/generated/minloc1_8_i1.c
libgfortran/generated/minloc1_8_i16.c
libgfortran/generated/minloc1_8_i2.c
libgfortran/generated/minloc1_8_i4.c
libgfortran/generated/minloc1_8_i8.c
libgfortran/generated/minloc1_8_r10.c
libgfortran/generated/minloc1_8_r16.c
libgfortran/generated/minloc1_8_r4.c
libgfortran/generated/minloc1_8_r8.c
libgfortran/generated/minval_i1.c
libgfortran/generated/minval_i16.c
libgfortran/generated/minval_i2.c
libgfortran/generated/minval_i4.c
libgfortran/generated/minval_i8.c
libgfortran/generated/minval_r10.c
libgfortran/generated/minval_r16.c
libgfortran/generated/minval_r4.c
libgfortran/generated/minval_r8.c
libgfortran/generated/product_c10.c
libgfortran/generated/product_c16.c
libgfortran/generated/product_c4.c
libgfortran/generated/product_c8.c
libgfortran/generated/product_i1.c
libgfortran/generated/product_i16.c
libgfortran/generated/product_i2.c
libgfortran/generated/product_i4.c
libgfortran/generated/product_i8.c
libgfortran/generated/product_r10.c
libgfortran/generated/product_r16.c
libgfortran/generated/product_r4.c
libgfortran/generated/product_r8.c
libgfortran/generated/sum_c10.c
libgfortran/generated/sum_c16.c
libgfortran/generated/sum_c4.c
libgfortran/generated/sum_c8.c
libgfortran/generated/sum_i1.c
libgfortran/generated/sum_i16.c
libgfortran/generated/sum_i2.c
libgfortran/generated/sum_i4.c
libgfortran/generated/sum_i8.c
libgfortran/generated/sum_r10.c
libgfortran/generated/sum_r16.c
libgfortran/generated/sum_r4.c
libgfortran/generated/sum_r8.c
libgfortran/m4/ifunction.m4

index e16eaff42bd0523bfacf157b0043e5fe071d4dc9..53978ccd0f5b1024da167c6935c5bab433fe7b44 100644 (file)
@@ -1,3 +1,8 @@
+2008-04-30  Thomas Koenig  <tkoenig@gcc.gnu.org>
+
+       PR libfortran/35993
+       * gfortran.dg/intrinsic_product_1.f90:  New test case.
+
 2008-04-30  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/14847
diff --git a/gcc/testsuite/gfortran.dg/intrinsic_product_1.f90 b/gcc/testsuite/gfortran.dg/intrinsic_product_1.f90
new file mode 100644 (file)
index 0000000..34d34fe
--- /dev/null
@@ -0,0 +1,29 @@
+! { dg-do run }
+! PR 35993 - some intrinsics with mask = .false. didn't set
+! the whole return array for multi-dimensional arrays.
+! Test case adapted from Dick Hendrickson.
+
+      program try
+
+      call       ga3019(  1,  2,  3,  4)
+      end program
+
+      SUBROUTINE GA3019(nf1,nf2,nf3,nf4)
+      INTEGER IDA(NF2,NF3)
+      INTEGER IDA1(NF2,NF4,NF3)
+
+      ida1 = 3
+
+      ida = -3
+      IDA(NF1:NF2,NF1:NF3) = PRODUCT(IDA1,NF2, NF1 .LT. 0)  !fails
+      if (any(ida /= 1)) call abort
+
+      ida = -3
+      IDA(NF1:NF2,NF1:NF3) = PRODUCT(IDA1,NF2, .false. )    !fails
+      if (any(ida /= 1)) call abort
+
+      ida = -3
+      IDA(NF1:NF2,NF1:NF3) = PRODUCT(IDA1,NF2, ida1 .eq. 137 )    !works
+      if (any(ida /= 1)) call abort
+
+      END SUBROUTINE
index df959f93544c6f65ec79d220960924f4efa7eb80..0ee684858ad57b0ba82077fdc52cfd90e4e2d7d6 100644 (file)
@@ -1,3 +1,108 @@
+2008-04-30  Thomas Koenig  <tkoenig@gcc.gnu.org>
+
+       PR libfortran/35993
+       * ifunction.m4 (SCALAR_ARRAY_FUNCTION):  Use correct
+       implementation for multi-dimensional return arrays when
+       the mask is .false.
+       * generated/maxloc1_16_i1.c: Regenerated.
+       * generated/maxloc1_16_i16.c: Regenerated.
+       * generated/maxloc1_16_i2.c: Regenerated.
+       * generated/maxloc1_16_i4.c: Regenerated.
+       * generated/maxloc1_16_i8.c: Regenerated.
+       * generated/maxloc1_16_r10.c: Regenerated.
+       * generated/maxloc1_16_r16.c: Regenerated.
+       * generated/maxloc1_16_r4.c: Regenerated.
+       * generated/maxloc1_16_r8.c: Regenerated.
+       * generated/maxloc1_4_i1.c: Regenerated.
+       * generated/maxloc1_4_i16.c: Regenerated.
+       * generated/maxloc1_4_i2.c: Regenerated.
+       * generated/maxloc1_4_i4.c: Regenerated.
+       * generated/maxloc1_4_i8.c: Regenerated.
+       * generated/maxloc1_4_r10.c: Regenerated.
+       * generated/maxloc1_4_r16.c: Regenerated.
+       * generated/maxloc1_4_r4.c: Regenerated.
+       * generated/maxloc1_4_r8.c: Regenerated.
+       * generated/maxloc1_8_i1.c: Regenerated.
+       * generated/maxloc1_8_i16.c: Regenerated.
+       * generated/maxloc1_8_i2.c: Regenerated.
+       * generated/maxloc1_8_i4.c: Regenerated.
+       * generated/maxloc1_8_i8.c: Regenerated.
+       * generated/maxloc1_8_r10.c: Regenerated.
+       * generated/maxloc1_8_r16.c: Regenerated.
+       * generated/maxloc1_8_r4.c: Regenerated.
+       * generated/maxloc1_8_r8.c: Regenerated.
+       * generated/maxval_i1.c: Regenerated.
+       * generated/maxval_i16.c: Regenerated.
+       * generated/maxval_i2.c: Regenerated.
+       * generated/maxval_i4.c: Regenerated.
+       * generated/maxval_i8.c: Regenerated.
+       * generated/maxval_r10.c: Regenerated.
+       * generated/maxval_r16.c: Regenerated.
+       * generated/maxval_r4.c: Regenerated.
+       * generated/maxval_r8.c: Regenerated.
+       * generated/minloc1_16_i1.c: Regenerated.
+       * generated/minloc1_16_i16.c: Regenerated.
+       * generated/minloc1_16_i2.c: Regenerated.
+       * generated/minloc1_16_i4.c: Regenerated.
+       * generated/minloc1_16_i8.c: Regenerated.
+       * generated/minloc1_16_r10.c: Regenerated.
+       * generated/minloc1_16_r16.c: Regenerated.
+       * generated/minloc1_16_r4.c: Regenerated.
+       * generated/minloc1_16_r8.c: Regenerated.
+       * generated/minloc1_4_i1.c: Regenerated.
+       * generated/minloc1_4_i16.c: Regenerated.
+       * generated/minloc1_4_i2.c: Regenerated.
+       * generated/minloc1_4_i4.c: Regenerated.
+       * generated/minloc1_4_i8.c: Regenerated.
+       * generated/minloc1_4_r10.c: Regenerated.
+       * generated/minloc1_4_r16.c: Regenerated.
+       * generated/minloc1_4_r4.c: Regenerated.
+       * generated/minloc1_4_r8.c: Regenerated.
+       * generated/minloc1_8_i1.c: Regenerated.
+       * generated/minloc1_8_i16.c: Regenerated.
+       * generated/minloc1_8_i2.c: Regenerated.
+       * generated/minloc1_8_i4.c: Regenerated.
+       * generated/minloc1_8_i8.c: Regenerated.
+       * generated/minloc1_8_r10.c: Regenerated.
+       * generated/minloc1_8_r16.c: Regenerated.
+       * generated/minloc1_8_r4.c: Regenerated.
+       * generated/minloc1_8_r8.c: Regenerated.
+       * generated/minval_i1.c: Regenerated.
+       * generated/minval_i16.c: Regenerated.
+       * generated/minval_i2.c: Regenerated.
+       * generated/minval_i4.c: Regenerated.
+       * generated/minval_i8.c: Regenerated.
+       * generated/minval_r10.c: Regenerated.
+       * generated/minval_r16.c: Regenerated.
+       * generated/minval_r4.c: Regenerated.
+       * generated/minval_r8.c: Regenerated.
+       * generated/product_c10.c: Regenerated.
+       * generated/product_c16.c: Regenerated.
+       * generated/product_c4.c: Regenerated.
+       * generated/product_c8.c: Regenerated.
+       * generated/product_i1.c: Regenerated.
+       * generated/product_i16.c: Regenerated.
+       * generated/product_i2.c: Regenerated.
+       * generated/product_i4.c: Regenerated.
+       * generated/product_i8.c: Regenerated.
+       * generated/product_r10.c: Regenerated.
+       * generated/product_r16.c: Regenerated.
+       * generated/product_r4.c: Regenerated.
+       * generated/product_r8.c: Regenerated.
+       * generated/sum_c10.c: Regenerated.
+       * generated/sum_c16.c: Regenerated.
+       * generated/sum_c4.c: Regenerated.
+       * generated/sum_c8.c: Regenerated.
+       * generated/sum_i1.c: Regenerated.
+       * generated/sum_i16.c: Regenerated.
+       * generated/sum_i2.c: Regenerated.
+       * generated/sum_i4.c: Regenerated.
+       * generated/sum_i8.c: Regenerated.
+       * generated/sum_r10.c: Regenerated.
+       * generated/sum_r16.c: Regenerated.
+       * generated/sum_r4.c: Regenerated.
+       * generated/sum_r8.c: Regenerated.
+
 2008-04-25  Thomas Koenig  <tkoenig@gcc.gnu.org>
 
        PR libfortran/35960
index 47e67239322cd8520ca9932d5b5f60675420089e..6e4153c3eb99ce2d71cae5313f230f1a9b334174 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_16_i1 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_16_i1 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 2c8a06cb6757a4260a6d8a913d99f53e3a56e905..b4fd55d635022661753d946911141ce09ffb4de6 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_16_i16 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_16_i16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index d7b1ca57eede2b50d82f5de4c079421731a80e36..483b90372eee4fb06f81c5f11d2f93dbafc2caa9 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_16_i2 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_16_i2 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 394c0160261d0f8e5ee2f1a60d046f97e50f7907..69d35d75556d90520050bc4d047686eef7440b51 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_16_i4 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_16_i4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 5cff65dece47f2b0a23f0c2e618c9b9d2d354bc4..54d016c2d514df60862899da11554a9c408d3186 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_16_i8 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_16_i8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 32af8cd88544e30f949ac794235a9f48aab6e186..10ea86849e5cc84a2bdfdc5c590d6455ce0bf502 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_16_r10 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_16_r10 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index d695ad8ec5d6157d363ac2f54010daae45852faf..54b2aeb90eb317f0899f7b77baa551606de995f7 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_16_r16 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_16_r16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 05dfbe380a7e891acc1c18991b22a5fcde5a9f37..f9712e6082ae3c800909f37e8c3aa7faa500caea 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_16_r4 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_16_r4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index a060e0620a8a57aae25552ec6e4613297e07980d..1e836288439494757943b0e5cfcf4b76f84a2386 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_16_r8 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_16_r8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 2244456c15448d5fd9e51e4574fe13bc45d1dbdf..271ef38e3f234cba1515c16c84893a259ac845d4 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_4_i1 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_4_i1 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index d0f260c962d99a4b5f864513ffcfe31f25f43f02..627e36030c451ab30646c4b79665c375ba75df06 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_4_i16 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_4_i16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 5415ebabacfa82155cb26ca67a3f7a514a241a1c..cf42ddfc7082193864d827a2c2197db197caad5c 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_4_i2 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_4_i2 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 291b919945d0d4edd30ec1d7582513afa17ea389..a26180f4e7f435124a6b528afd22d11a0faa04f0 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_4_i4 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_4_i4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 97a904dc6875eb68b807529a286916c52c75561e..40f2c36a93d9145ecad65f4aeeda9b4f4c166547 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_4_i8 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_4_i8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 07ccb242ae4bfed001cf7a70dc926dd2e4b4513e..75497022d7604ec7a400356c3f3a40be179522bd 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_4_r10 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_4_r10 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 5ecfffd7b044eff3c8ca961607066a1af14eb367..3ed0d96671e413ed306998e26f3bfbf942499420 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_4_r16 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_4_r16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index f859cc761996f9606c2650ffa645ddaf749ad99f..24ecf9a40e66c947b2a7788c402e3796acad66d7 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_4_r4 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_4_r4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 5d673420fd9e265e4cdf30229583c18e3d06bc5c..9a695da2b2980f7c80bfdc7bd54b7332376cf5c1 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_4_r8 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_4_r8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index f9ea707ab95df62c61fe5f023fd9d2f5da678597..489ed11a8fcd78bd84142e3080cd3ea7adf260b9 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_8_i1 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_8_i1 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 478a8bc87b0c662d6350ff128ab74f1a4e170d2e..9f8c7ad01ffee01ddbd6c5329b39779454a2b121 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_8_i16 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_8_i16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 972767f6558a4c6b77a7548d52688292d3bfc73e..28e0163919898bd33d0c14bc342b5921b9158053 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_8_i2 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_8_i2 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index e3b566d57ec4c78b6c0752b5b514d15f15dba8a9..82038dc474574e1efa95441afdb00e12fae342b6 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_8_i4 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_8_i4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index e30e104dfc6a787aa81edc080cd78e82fbfc0f3e..c7301eab6c12fd30778a307f7b66cace3c0ded34 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_8_i8 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_8_i8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 01e30f660e44abfcfb8be1d8f8c50e32ca6ae2bb..d83600d60199240966c74fb0d3aaef8f57e057c4 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_8_r10 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_8_r10 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index fbe72d1874fa0834ff09e32ec43a3cfdff8ecd9d..6d45297df7727929309885aac1dff4c64dda6709 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_8_r16 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_8_r16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 3985d684fe4f9c9831ceff10c7662f33529b3a42..470d73c1ea3ed30d27531679e5f83b42a3bc3375 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_8_r4 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_8_r4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 6e7745b31ba975872e47c5e99c67f73a83a55a09..7003594e00cbef30926282a34162fbaaa575954f 100644 (file)
@@ -428,51 +428,131 @@ smaxloc1_8_r8 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxloc1_8_r8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 901f4e7f2a7fa903884ea2b9052118b8cf584249..9468e4aad4a8ebe898c2f39135bc02ad91228613 100644 (file)
@@ -417,51 +417,131 @@ smaxval_i1 (gfc_array_i1 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_1 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_1 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxval_i1 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_1) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_1) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = (-GFC_INTEGER_1_HUGE-1) ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = (-GFC_INTEGER_1_HUGE-1);
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index c082e856922d92530ae61c7269833ac985dfbbc9..de2cac8c11300a7bf252c64bb33e8229995401e1 100644 (file)
@@ -417,51 +417,131 @@ smaxval_i16 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxval_i16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = (-GFC_INTEGER_16_HUGE-1) ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = (-GFC_INTEGER_16_HUGE-1);
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 87865e1b49b123252b9fcd3a31c72cc7d224a318..818fc29e8896cfa3d66b7f0bf34a1bd382ec797a 100644 (file)
@@ -417,51 +417,131 @@ smaxval_i2 (gfc_array_i2 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_2 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_2 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxval_i2 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_2) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_2) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = (-GFC_INTEGER_2_HUGE-1) ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = (-GFC_INTEGER_2_HUGE-1);
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 3fa4a10b1bf5f56ec613a6f142ba7389101ef5c4..e5289f1e1d8272eb0e0ea59bac7e0f604c365b65 100644 (file)
@@ -417,51 +417,131 @@ smaxval_i4 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxval_i4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = (-GFC_INTEGER_4_HUGE-1) ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = (-GFC_INTEGER_4_HUGE-1);
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 8b2106d209f6f3c1ce4d5fe9f6d94eac29d3e08d..d05737d66f1e1a6714fb296bbddb1a3425ee6327 100644 (file)
@@ -417,51 +417,131 @@ smaxval_i8 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxval_i8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = (-GFC_INTEGER_8_HUGE-1) ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = (-GFC_INTEGER_8_HUGE-1);
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index a076190e8af70b0e54a901d376381729455e6a8e..921ad487d4748b8136d0fe33de72ab2f2c910c93 100644 (file)
@@ -417,51 +417,131 @@ smaxval_r10 (gfc_array_r10 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_REAL_10 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_REAL_10 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxval_r10 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_REAL_10) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_REAL_10) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = -GFC_REAL_10_HUGE ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = -GFC_REAL_10_HUGE;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 1e36379048bc3c48d8ae42cabf328743a9534fa6..15bdd7e215a37ae7f5e26cb2d946cce2ac4e5883 100644 (file)
@@ -417,51 +417,131 @@ smaxval_r16 (gfc_array_r16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_REAL_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_REAL_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxval_r16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_REAL_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_REAL_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = -GFC_REAL_16_HUGE ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = -GFC_REAL_16_HUGE;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 222a4e3beeec9c7d6708333c1caee57a91411345..f3470e8b951c7148a3857766a5dd7b38c4a2b3dc 100644 (file)
@@ -417,51 +417,131 @@ smaxval_r4 (gfc_array_r4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_REAL_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_REAL_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxval_r4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_REAL_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_REAL_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = -GFC_REAL_4_HUGE ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = -GFC_REAL_4_HUGE;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 163ec5a1b030c47bac2f80c457641d8361c17303..b5d7f3c0d521c3a6a4ceb1ff5192ec2342fec9d6 100644 (file)
@@ -417,51 +417,131 @@ smaxval_r8 (gfc_array_r8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_REAL_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_REAL_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       maxval_r8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_REAL_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_REAL_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MAXVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MAXVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MAXVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = -GFC_REAL_8_HUGE ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = -GFC_REAL_8_HUGE;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index f4abfa8f0d1e3f2330944cd2741e1fbcbf13372a..8a20d7b453c5996f100f12a8f1b5b1ac7846c4ae 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_16_i1 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_16_i1 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 40b86eadc6c90aabda58ad44b7261aafd7a34919..f0c5b84384afdb268b2248e36fd54f4ab703ac6e 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_16_i16 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_16_i16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index f7057b2c849bc257cb21fcaa1bc206ad232c6318..234f364880abecffb2145f9d3606410f0d7bc1b4 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_16_i2 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_16_i2 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 3cf6f0de83fa14f82e1a6eac3daa88e5164dbc5c..2b55cff40b861747046c43325ce51b5e2d0a4e59 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_16_i4 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_16_i4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index a0838687ba88ec9328de1be7b8a69de855a835c4..2e2e89407c0177829fcdaad94e88a5f4924371c8 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_16_i8 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_16_i8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 20b1c5789a7d3a573c1b4c7f5c0e5b8c7b842a22..dcf291f64537784705498f50ef83db1d12e1f0e3 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_16_r10 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_16_r10 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 40fcbaea3f95c44dc79606ee67e9add1d12709d3..eb496134df7ea0162eaa15f1e3d42df4c30b9516 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_16_r16 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_16_r16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 76e7efaf0eba7ffb8d1aba46666278eae263130b..dd39b5dd02ce99bdca4fb73a5e0780fb6158bf5a 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_16_r4 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_16_r4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 97ca8661dfbbc3f04af146c6d9e1e832a5c34141..e31410f0cecedb2f68d8c9f9711303ffc6c34926 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_16_r8 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_16_r8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 330c0d9b91a1928a1080392c4e8402d6c7d880b2..5111c7d6f46045cbba9ca6a1bd9101ba19488f40 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_4_i1 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_4_i1 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index a142adb9630aa18dfda8a1dd810c84cbd5708cf4..db898320157db48b82f0f9c86b72748f963a219c 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_4_i16 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_4_i16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index d7a92804094c2df7635022eee8fd5c342d9b6fc3..3e1448dc50f265fce6c6f98ebdbcc372d03976ce 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_4_i2 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_4_i2 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index c6b12e84e2614ad103bbb19937b9088cc8d6140c..b66c23edfc1ecb4c5e180f6b5781fade3aa59002 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_4_i4 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_4_i4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index bac4eb5fc8216309e73573968840636083012634..1eb3c4cbcf01f8aba7244cc75d21dcaec8fcfae5 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_4_i8 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_4_i8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 0579519ab0deee9199666c169d4b6d5d943af3fa..a224fd3ef0576949198367e78944aea076887ea6 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_4_r10 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_4_r10 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index d74d26dc605737dd38268d887b14cb2c03680cd9..404be416cff7059fb8ffdb70ac4815f28c02d945 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_4_r16 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_4_r16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 050ed5c3c793b0f2d8e80da031d2caecbcbb30bd..4d9844ce633bde22b425ad9d662ebe9f0bbfd84c 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_4_r4 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_4_r4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 483cd19f2629332b81f549a35a4c6cff5cf4ee20..fc9b0aea239d286bbf1e19fe0423042502f38e47 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_4_r8 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_4_r8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 1fc81d106e20d2335d3a869cc538ad8c518e331d..b0fbe0d946ec48ffe34b8c7234424564b9d04603 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_8_i1 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_8_i1 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index ecbabc7a9818b11a177e3bba6fb17ad22735478d..4c4a76c75de0fd5de7590aa15225200672681810 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_8_i16 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_8_i16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 2c03443258e23761fd4dc2358c89763feffe60f7..f18cd2aea79db8fac6d9ae728b5abb7e920de7bb 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_8_i2 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_8_i2 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 945423748c5c5f1b3623ca79364dee0088ccc14a..758249e063151aab1b161e8b965a71f446f8f413 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_8_i4 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_8_i4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index df801458e09ab0e396ab964b86095f31b11e97aa..245522e579dc0063491ebb264d3694012e7c0963 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_8_i8 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_8_i8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 364bf5c6f04f77892d60228bab12ebe4d53bec90..ae8035ee0619c86e747415e62ab023a3523d7d6e 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_8_r10 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_8_r10 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index b8ad0950ec5eb6af59dbb26cebd4aefccfc3817e..af4e2ea41b22d86af33170d2498220d261009940 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_8_r16 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_8_r16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index e9df66c669f703bbfafb0ab367507c902c52e0a1..3f2b2e1dd4e7dc512eaf8c479d0c0361c69bc4fe 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_8_r4 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_8_r4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 7d2cfff7fed03cf2627e34760e5ec7a42be1d4a8..5e00272ec9bfcd05c1d5ef16bcf1df929df56fd1 100644 (file)
@@ -428,51 +428,131 @@ sminloc1_8_r8 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minloc1_8_r8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINLOC intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINLOC intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINLOC intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 1789ec9fcfad0aff7dd22200384c455530efc166..3815d44f8df08584604f8344250163553059407b 100644 (file)
@@ -417,51 +417,131 @@ sminval_i1 (gfc_array_i1 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_1 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_1 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minval_i1 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_1) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_1) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = GFC_INTEGER_1_HUGE ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = GFC_INTEGER_1_HUGE;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 2916256e3ebd361a21b4f1938bc9a92c175674e7..b8b99d33529f2a23327902d6ead7cc07ee058f91 100644 (file)
@@ -417,51 +417,131 @@ sminval_i16 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minval_i16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = GFC_INTEGER_16_HUGE ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = GFC_INTEGER_16_HUGE;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 73bf18b61673278ff596d6206acf1a62dd5108f9..1e83efd024ca5680b2e7010718b511c7fe7298b2 100644 (file)
@@ -417,51 +417,131 @@ sminval_i2 (gfc_array_i2 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_2 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_2 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minval_i2 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_2) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_2) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = GFC_INTEGER_2_HUGE ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = GFC_INTEGER_2_HUGE;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 8d6e52a2ac0cd358f66d5ccb2853898807afc574..a40fc2cfd77d03aa6bc660cd6d1bcecbccd5b155 100644 (file)
@@ -417,51 +417,131 @@ sminval_i4 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minval_i4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = GFC_INTEGER_4_HUGE ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = GFC_INTEGER_4_HUGE;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 22cf462d0605bb0dba0b8574d4eb5c0e5ad21718..af37f4369af0b0a9945c41686c2149338f128599 100644 (file)
@@ -417,51 +417,131 @@ sminval_i8 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minval_i8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = GFC_INTEGER_8_HUGE ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = GFC_INTEGER_8_HUGE;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index f4d467c0d992f8fcba563022eefcf2f579960ac6..829c630037bfa90e6aa01bb448a9cf6c41b44f69 100644 (file)
@@ -417,51 +417,131 @@ sminval_r10 (gfc_array_r10 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_REAL_10 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_REAL_10 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minval_r10 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_REAL_10) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_REAL_10) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = GFC_REAL_10_HUGE ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = GFC_REAL_10_HUGE;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 7ba19c99c1bcfb2c7013d6843bbfa771b2213d5c..c3797c7f537bb274352829477b253ed1b3218821 100644 (file)
@@ -417,51 +417,131 @@ sminval_r16 (gfc_array_r16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_REAL_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_REAL_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minval_r16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_REAL_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_REAL_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = GFC_REAL_16_HUGE ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = GFC_REAL_16_HUGE;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 3b29f2f5d3b98e7adbf7c2c34e6b2d07c07a034f..c8c8fd518090f80ce110ecaf90fbd2d04160561c 100644 (file)
@@ -417,51 +417,131 @@ sminval_r4 (gfc_array_r4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_REAL_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_REAL_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minval_r4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_REAL_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_REAL_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = GFC_REAL_4_HUGE ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = GFC_REAL_4_HUGE;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index adca8b28c7d347f064cd3104e6ddcef2151a2f2c..e404b170b915d606c90f9ace10cf6775440e8965 100644 (file)
@@ -417,51 +417,131 @@ sminval_r8 (gfc_array_r8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_REAL_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_REAL_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       minval_r8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_REAL_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_REAL_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " MINVAL intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in MINVAL intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " MINVAL intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = GFC_REAL_8_HUGE ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = GFC_REAL_8_HUGE;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index def678ab953eeca8fb477f707d59e632e712c77b..0366544a205fd7e67df11346c9d91455491bff1e 100644 (file)
@@ -416,51 +416,131 @@ sproduct_c10 (gfc_array_c10 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_COMPLEX_10 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_COMPLEX_10 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       product_c10 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_COMPLEX_10) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_COMPLEX_10) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " PRODUCT intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in PRODUCT intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " PRODUCT intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 1 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 1;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index d8750aef5b00d606a61174b236db30e761b5bd08..c4612cf2059d8d1186a83c7d5c114b17c8b6050b 100644 (file)
@@ -416,51 +416,131 @@ sproduct_c16 (gfc_array_c16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_COMPLEX_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_COMPLEX_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       product_c16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_COMPLEX_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_COMPLEX_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " PRODUCT intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in PRODUCT intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " PRODUCT intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 1 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 1;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 7cac33fc8c63a58c45a7df73abf5045aed1e2789..53c7f80b269c19711fbaacda5761aad4069a08c8 100644 (file)
@@ -416,51 +416,131 @@ sproduct_c4 (gfc_array_c4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_COMPLEX_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_COMPLEX_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       product_c4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_COMPLEX_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_COMPLEX_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " PRODUCT intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in PRODUCT intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " PRODUCT intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 1 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 1;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index e4f0f6bfd303ead4a29febf42f71f98b2fb39993..812fb3ba38e65990cde43d1d87c603eab9ec991a 100644 (file)
@@ -416,51 +416,131 @@ sproduct_c8 (gfc_array_c8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_COMPLEX_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_COMPLEX_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       product_c8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_COMPLEX_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_COMPLEX_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " PRODUCT intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in PRODUCT intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " PRODUCT intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 1 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 1;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 5a428cad202f77eeccb862b42d88b84bb9b00b65..72b894f89c41370416e3db898afbae7ee701f7a5 100644 (file)
@@ -416,51 +416,131 @@ sproduct_i1 (gfc_array_i1 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_1 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_1 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       product_i1 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_1) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_1) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " PRODUCT intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in PRODUCT intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " PRODUCT intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 1 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 1;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index a1593a4f66a4da1dcdda3879059f781b315b0f2b..e04293179a84c8f7f0afdbca03ec1e251a9f077e 100644 (file)
@@ -416,51 +416,131 @@ sproduct_i16 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       product_i16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " PRODUCT intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in PRODUCT intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " PRODUCT intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 1 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 1;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 16793f89579579663129beed34f660c24333faa8..af3da57cf979652efaef7ba4d252d417b8300daf 100644 (file)
@@ -416,51 +416,131 @@ sproduct_i2 (gfc_array_i2 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_2 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_2 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       product_i2 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_2) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_2) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " PRODUCT intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in PRODUCT intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " PRODUCT intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 1 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 1;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index cbace913d6af6ad6b6ae2409e8b57ce21aa3c67c..75028e57980a249e2325511ca590921ed7775ae7 100644 (file)
@@ -416,51 +416,131 @@ sproduct_i4 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       product_i4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " PRODUCT intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in PRODUCT intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " PRODUCT intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 1 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 1;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index f1fc56718a8110d52a932f346d20ea5ae64585e1..1fc446cf2a0db968f1cdef3ec68c3ecd145342aa 100644 (file)
@@ -416,51 +416,131 @@ sproduct_i8 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       product_i8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " PRODUCT intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in PRODUCT intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " PRODUCT intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 1 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 1;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 4b7c5803096a59391a620d74b8e045aa74fa7963..7956b30958d7534879e39638fcc482304fe72cdc 100644 (file)
@@ -416,51 +416,131 @@ sproduct_r10 (gfc_array_r10 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_REAL_10 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_REAL_10 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       product_r10 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_REAL_10) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_REAL_10) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " PRODUCT intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in PRODUCT intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " PRODUCT intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 1 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 1;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index b18155bd73ca9efa3f77e3f2a1f90e1c638c4e5f..9cfd8df0213aa300a4834921b5f03249757f96c2 100644 (file)
@@ -416,51 +416,131 @@ sproduct_r16 (gfc_array_r16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_REAL_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_REAL_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       product_r16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_REAL_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_REAL_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " PRODUCT intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in PRODUCT intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " PRODUCT intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 1 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 1;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 754cac2bfb18b5db0e8796f38de03885d1c5f602..276d91ae3fdee03adc72ed4b71c70a47f873d3a6 100644 (file)
@@ -416,51 +416,131 @@ sproduct_r4 (gfc_array_r4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_REAL_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_REAL_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       product_r4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_REAL_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_REAL_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " PRODUCT intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in PRODUCT intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " PRODUCT intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 1 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 1;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 5f68856a8b024acbac1c725df3b06b06f9227bc3..2c07381736a8e0051c367585b6aa2d33a072803f 100644 (file)
@@ -416,51 +416,131 @@ sproduct_r8 (gfc_array_r8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_REAL_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_REAL_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       product_r8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_REAL_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_REAL_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " PRODUCT intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in PRODUCT intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " PRODUCT intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 1 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 1;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index e495a0ba49779844da8ab9c062f5e6cc1cc8fc58..6c2228917533c5b88cca5c60779f7a58e49a7a10 100644 (file)
@@ -416,51 +416,131 @@ ssum_c10 (gfc_array_c10 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_COMPLEX_10 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_COMPLEX_10 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       sum_c10 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_COMPLEX_10) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_COMPLEX_10) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " SUM intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in SUM intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " SUM intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index c73083a930c25f321e2f05e411c8e430884e6fae..203c483619ae65ce733d3eb7ef8fdd8816113bf5 100644 (file)
@@ -416,51 +416,131 @@ ssum_c16 (gfc_array_c16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_COMPLEX_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_COMPLEX_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       sum_c16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_COMPLEX_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_COMPLEX_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " SUM intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in SUM intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " SUM intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 6f32327ad0b2e3149838e75521b274dc334919a4..4a91bb2631a682253dfd81538b44f8790180d735 100644 (file)
@@ -416,51 +416,131 @@ ssum_c4 (gfc_array_c4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_COMPLEX_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_COMPLEX_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       sum_c4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_COMPLEX_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_COMPLEX_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " SUM intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in SUM intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " SUM intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 80db1101cfe442a94264458bf6cf4f116a4bb77a..f877d09413535cfc9507df23435a1d9fb539727c 100644 (file)
@@ -416,51 +416,131 @@ ssum_c8 (gfc_array_c8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_COMPLEX_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_COMPLEX_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       sum_c8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_COMPLEX_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_COMPLEX_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " SUM intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in SUM intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " SUM intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index c652712d4e7f27ef9743c4783a79a51987162709..de46086a775631ac40c05e27bac0111119e7f51b 100644 (file)
@@ -416,51 +416,131 @@ ssum_i1 (gfc_array_i1 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_1 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_1 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       sum_i1 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_1) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_1) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " SUM intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in SUM intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " SUM intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 43a29a2956f8dbbced815c2e40d5ac8b37378cfe..b7fc6e1a1704b9db0535933edc7d4fcbf5a0e678 100644 (file)
@@ -416,51 +416,131 @@ ssum_i16 (gfc_array_i16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       sum_i16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " SUM intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in SUM intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " SUM intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 6c6fcc1116a3580be14cf104b9b35aa5ca4e520c..f7b85d7b6c8d35837b1a2f8d5fafb5eddeac8839 100644 (file)
@@ -416,51 +416,131 @@ ssum_i2 (gfc_array_i2 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_2 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_2 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       sum_i2 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_2) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_2) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " SUM intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in SUM intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " SUM intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index e28d2c96fdf3bc07d336ee9338612c3f9c8a4d2b..04849b5bcf18ab286af82968c5fa0c389ea486e3 100644 (file)
@@ -416,51 +416,131 @@ ssum_i4 (gfc_array_i4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       sum_i4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " SUM intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in SUM intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " SUM intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 6e824f1ca56f745aad96c6cfec48e8649ccab1b2..bf65615376b65c45c9552cd437eac9f63eb49b7d 100644 (file)
@@ -416,51 +416,131 @@ ssum_i8 (gfc_array_i8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_INTEGER_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       sum_i8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_INTEGER_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_INTEGER_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " SUM intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in SUM intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " SUM intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 1ebd1ed542541179aebd45801e52de84cefc7c7a..deefd30870a69f6941733c7d296ae299b39053e9 100644 (file)
@@ -416,51 +416,131 @@ ssum_r10 (gfc_array_r10 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_REAL_10 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_REAL_10 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       sum_r10 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_REAL_10) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_REAL_10) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " SUM intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in SUM intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " SUM intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 0038983a6b4a537c06b8e60ddd513c00a6d20b87..ee365f74d15c8274fa039d750da53229aad81f4f 100644 (file)
@@ -416,51 +416,131 @@ ssum_r16 (gfc_array_r16 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_REAL_16 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_REAL_16 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       sum_r16 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_REAL_16) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_REAL_16) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " SUM intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in SUM intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " SUM intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 1f058dcbda05d09a86a0cea69708d6a6bf8c2fe2..07f43397b7be57ca210b69b50e73fff8bf3d97bf 100644 (file)
@@ -416,51 +416,131 @@ ssum_r4 (gfc_array_r4 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_REAL_4 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_REAL_4 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       sum_r4 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_REAL_4) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_REAL_4) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " SUM intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in SUM intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " SUM intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 82a03bc81f707ffd2f30a30f5f00d46a60427089..f83c683347dd1b99b05ee4aecb1971ab47406bd8 100644 (file)
@@ -416,51 +416,131 @@ ssum_r8 (gfc_array_r8 * const restrict retarray,
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_REAL_8 * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  GFC_REAL_8 *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       sum_r8 (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (GFC_REAL_8) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (GFC_REAL_8) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " SUM intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in SUM intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " SUM intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = 0 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = 0;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }
 
 #endif
index 9769e4d2ddb626696e6459f29337382332d32b4e..5ab2952a49127baee4c7480363702e46854681be 100644 (file)
@@ -398,51 +398,131 @@ void
        const index_type * const restrict pdim, 
        GFC_LOGICAL_4 * mask)
 {
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  rtype_name * restrict dest;
   index_type rank;
   index_type n;
-  index_type dstride;
-  rtype_name *dest;
+  index_type dim;
+
 
   if (*mask)
     {
       name`'rtype_qual`_'atype_code (retarray, array, pdim);
       return;
     }
-    rank = GFC_DESCRIPTOR_RANK (array);
-  if (rank <= 0)
-    runtime_error ("Rank of array needs to be > 0");
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = array->dim[n].stride;
+      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = array->dim[n + 1].stride;
+      extent[n] =
+        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+
+      if (extent[n] <= 0)
+        extent[n] = 0;
+    }
 
   if (retarray->data == NULL)
     {
-      retarray->dim[0].lbound = 0;
-      retarray->dim[0].ubound = rank-1;
-      retarray->dim[0].stride = 1;
-      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      size_t alloc_size;
+
+      for (n = 0; n < rank; n++)
+        {
+          retarray->dim[n].lbound = 0;
+          retarray->dim[n].ubound = extent[n]-1;
+          if (n == 0)
+            retarray->dim[n].stride = 1;
+          else
+            retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
+        }
+
       retarray->offset = 0;
-      retarray->data = internal_malloc_size (sizeof (rtype_name) * rank);
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (rtype_name) * retarray->dim[rank-1].stride
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         retarray->dim[0].lbound = 0;
+         retarray->dim[0].ubound = -1;
+         return;
+       }
+      else
+       retarray->data = internal_malloc_size (alloc_size);
     }
   else
     {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in"
+                      " u_name intrinsic: is %ld, should be %ld",
+                      (long int) (GFC_DESCRIPTOR_RANK (retarray)),
+                      (long int) rank);
+
       if (compile_options.bounds_check)
        {
-         int ret_rank;
-         index_type ret_extent;
-
-         ret_rank = GFC_DESCRIPTOR_RANK (retarray);
-         if (ret_rank != 1)
-           runtime_error ("rank of return array in u_name intrinsic"
-                          " should be 1, is %ld", (long int) ret_rank);
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
 
-         ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
-           if (ret_extent != rank)
-             runtime_error ("dimension of return array incorrect");
+             ret_extent = retarray->dim[n].ubound + 1
+               - retarray->dim[n].lbound;
+             if (extent[n] != ret_extent)
+               runtime_error ("Incorrect extent in return value of"
+                              " u_name intrinsic in dimension %ld:"
+                              " is %ld, should be %ld", (long int) n + 1,
+                              (long int) ret_extent, (long int) extent[n]);
+           }
        }
     }
-    dstride = retarray->dim[0].stride;
-    dest = retarray->data;
 
-    for (n = 0; n < rank; n++)
-      dest[n * dstride] = $1 ;
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = retarray->dim[n].stride;
+    }
+
+  dest = retarray->data;
+
+  while(1)
+    {
+      *dest = '$1`;
+      count[0]++;
+      dest += dstride[0];
+      n = 0;
+      while (count[n] == extent[n])
+        {
+         /* When we get to the end of a dimension, reset it and increment
+             the next dimension.  */
+          count[n] = 0;
+          /* We could precalculate these products, but this is a less
+             frequently used path so probably not worth it.  */
+          dest -= dstride[n] * extent[n];
+          n++;
+          if (n == rank)
+           return;
+          else
+            {
+              count[n]++;
+              dest += dstride[n];
+            }
+       }
+    }
 }')dnl
 define(ARRAY_FUNCTION,
 `START_ARRAY_FUNCTION