OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / libgfortran / m4 / ifunction.m4
index 74cc1e6..68e1c5e 100644 (file)
@@ -1,7 +1,7 @@
 dnl Support macro file for intrinsic functions.
 dnl Contains the generic sections of the array functions.
-dnl This file is part of the GNU Fortran 95 Runtime Library (libgfortran)
-dnl Distributed under the GNU LGPL.  See COPYING for details.
+dnl This file is part of the GNU Fortran Runtime Library (libgfortran)
+dnl Distributed under the GNU GPL with exception.  See COPYING for details.
 dnl
 dnl Pass the implementation for a single section as the parameter to
 dnl {MASK_}ARRAY_FUNCTION.
@@ -18,65 +18,119 @@ dnl Execution should be allowed to continue to the end of the block.
 dnl You should not return or break from the inner loop of the implementation.
 dnl Care should also be taken to avoid using the names defined in iparm.m4
 define(START_ARRAY_FUNCTION,
-`void
-`__'name`'rtype_qual`_'atype_code (rtype * retarray, atype *array, index_type *pdim)
+`
+extern void name`'rtype_qual`_'atype_code (rtype * const restrict, 
+       atype * const restrict, const index_type * const restrict);
+export_proto(name`'rtype_qual`_'atype_code);
+
+void
+name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
+       atype * const restrict array, 
+       const index_type * const restrict pdim)
 {
-  index_type count[GFC_MAX_DIMENSIONS - 1];
-  index_type extent[GFC_MAX_DIMENSIONS - 1];
-  index_type sstride[GFC_MAX_DIMENSIONS - 1];
-  index_type dstride[GFC_MAX_DIMENSIONS - 1];
-  atype_name *base;
-  rtype_name *dest;
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  const atype_name * restrict base;
+  rtype_name * restrict dest;
   index_type rank;
   index_type n;
   index_type len;
   index_type delta;
   index_type dim;
+  int continue_loop;
 
   /* Make dim zero based to avoid confusion.  */
   dim = (*pdim) - 1;
   rank = GFC_DESCRIPTOR_RANK (array) - 1;
-  assert (rank == GFC_DESCRIPTOR_RANK (retarray));
-  if (array->dim[0].stride == 0)
-    array->dim[0].stride = 1;
-  if (retarray->dim[0].stride == 0)
-    retarray->dim[0].stride = 1;
 
-  len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
-  delta = array->dim[dim].stride;
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len < 0)
+    len = 0;
+  delta = GFC_DESCRIPTOR_STRIDE(array,dim);
 
   for (n = 0; n < dim; n++)
     {
-      sstride[n] = array->dim[n].stride;
-      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+      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;
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->data == NULL)
+    {
+      size_t alloc_size, str;
+
+      for (n = 0; n < rank; n++)
+       {
+         if (n == 0)
+           str = 1;
+         else
+           str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
+
+         GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
+
+       }
+
+      retarray->offset = 0;
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (rtype_name) * GFC_DESCRIPTOR_STRIDE(retarray,rank-1)
+                  * extent[rank-1];
+
+      retarray->data = internal_malloc_size (alloc_size);
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
+         return;
+
+       }
+    }
+  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 (unlikely (compile_options.bounds_check))
+       bounds_ifunction_return ((array_t *) retarray, extent,
+                                "return value", "u_name");
     }
 
   for (n = 0; n < rank; n++)
     {
       count[n] = 0;
-      dstride[n] = retarray->dim[n].stride;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
       if (extent[n] <= 0)
-        len = 0;
+       return;
     }
 
   base = array->data;
   dest = retarray->data;
 
-  while (base)
+  continue_loop = 1;
+  while (continue_loop)
     {
-      atype_name *src;
+      const atype_name * restrict src;
       rtype_name result;
       src = base;
       {
 ')dnl
 define(START_ARRAY_BLOCK,
-`        if (len <= 0)
+`      if (len <= 0)
          *dest = '$1`;
        else
          {
@@ -84,7 +138,8 @@ define(START_ARRAY_BLOCK,
              {
 ')dnl
 define(FINISH_ARRAY_FUNCTION,
-    `          }
+`            }
+           '$1`
            *dest = result;
          }
       }
@@ -94,110 +149,169 @@ define(FINISH_ARRAY_FUNCTION,
       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 proabably not worth it.  */
-          base -= sstride[n] * extent[n];
-          dest -= dstride[n] * extent[n];
-          n++;
-          if (n == rank)
-            {
-              /* Break out of the look.  */
-              base = NULL;
-              break;
-            }
-          else
-            {
-              count[n]++;
-              base += sstride[n];
-              dest += dstride[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.  */
+         base -= sstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n == rank)
+           {
+             /* Break out of the look.  */
+             continue_loop = 0;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             dest += dstride[n];
+           }
+       }
     }
 }')dnl
 define(START_MASKED_ARRAY_FUNCTION,
-`void
-`__m'name`'rtype_qual`_'atype_code (rtype * retarray, atype * array, index_type *pdim, gfc_array_l4 * mask)
+`
+extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict, 
+       atype * const restrict, const index_type * const restrict,
+       gfc_array_l1 * const restrict);
+export_proto(`m'name`'rtype_qual`_'atype_code);
+
+void
+`m'name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
+       atype * const restrict array, 
+       const index_type * const restrict pdim, 
+       gfc_array_l1 * const restrict mask)
 {
-  index_type count[GFC_MAX_DIMENSIONS - 1];
-  index_type extent[GFC_MAX_DIMENSIONS - 1];
-  index_type sstride[GFC_MAX_DIMENSIONS - 1];
-  index_type dstride[GFC_MAX_DIMENSIONS - 1];
-  index_type mstride[GFC_MAX_DIMENSIONS - 1];
-  rtype_name *dest;
-  atype_name *base;
-  GFC_LOGICAL_4 *mbase;
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  index_type mstride[GFC_MAX_DIMENSIONS];
+  rtype_name * restrict dest;
+  const atype_name * restrict base;
+  const GFC_LOGICAL_1 * restrict mbase;
   int rank;
   int dim;
   index_type n;
   index_type len;
   index_type delta;
   index_type mdelta;
+  int mask_kind;
 
   dim = (*pdim) - 1;
   rank = GFC_DESCRIPTOR_RANK (array) - 1;
-  assert (rank == GFC_DESCRIPTOR_RANK (retarray));
-  if (array->dim[0].stride == 0)
-    array->dim[0].stride = 1;
-  if (retarray->dim[0].stride == 0)
-    retarray->dim[0].stride = 1;
 
-  len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
   if (len <= 0)
     return;
-  delta = array->dim[dim].stride;
-  mdelta = mask->dim[dim].stride;
+
+  mbase = mask->data;
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+
+  if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
+#ifdef HAVE_GFC_LOGICAL_16
+      || mask_kind == 16
+#endif
+      )
+    mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
+  else
+    runtime_error ("Funny sized logical array");
+
+  delta = GFC_DESCRIPTOR_STRIDE(array,dim);
+  mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
 
   for (n = 0; n < dim; n++)
     {
-      sstride[n] = array->dim[n].stride;
-      mstride[n] = mask->dim[n].stride;
-      extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
+      mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+
     }
   for (n = dim; n < rank; n++)
     {
-      sstride[n] = array->dim[n + 1].stride;
-      mstride[n] = mask->dim[n + 1].stride;
-      extent[n] =
-        array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
+      mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->data == NULL)
+    {
+      size_t alloc_size, str;
+
+      for (n = 0; n < rank; n++)
+       {
+         if (n == 0)
+           str = 1;
+         else
+           str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
+
+         GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
+
+       }
+
+      alloc_size = sizeof (rtype_name) * GFC_DESCRIPTOR_STRIDE(retarray,rank-1)
+                  * extent[rank-1];
+
+      retarray->offset = 0;
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 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");
+
+      if (unlikely (compile_options.bounds_check))
+       {
+         bounds_ifunction_return ((array_t *) retarray, extent,
+                                  "return value", "u_name");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                               "MASK argument", "u_name");
+       }
     }
 
   for (n = 0; n < rank; n++)
     {
       count[n] = 0;
-      dstride[n] = retarray->dim[n].stride;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
       if (extent[n] <= 0)
-        return;
+       return;
     }
 
   dest = retarray->data;
   base = array->data;
-  mbase = mask->data;
-
-  if (GFC_DESCRIPTOR_SIZE (mask) != 4)
-    {
-      /* This allows the same loop to be used for all logical types.  */
-      assert (GFC_DESCRIPTOR_SIZE (mask) == 8);
-      for (n = 0; n < rank; n++)
-        mstride[n] <<= 1;
-      mdelta <<= 1;
-      mbase = (GFOR_POINTER_L8_TO_L4 (mbase));
-    }
 
   while (base)
     {
-      atype_name *src;
-      GFC_LOGICAL_4 *msrc;
+      const atype_name * restrict src;
+      const GFC_LOGICAL_1 * restrict msrc;
       rtype_name result;
       src = base;
       msrc = mbase;
       {
 ')dnl
 define(START_MASKED_ARRAY_BLOCK,
-`        if (len <= 0)
+`      if (len <= 0)
          *dest = '$1`;
        else
          {
@@ -205,7 +319,7 @@ define(START_MASKED_ARRAY_BLOCK,
              {
 ')dnl
 define(FINISH_MASKED_ARRAY_FUNCTION,
-`              }
+`            }
            *dest = result;
          }
       }
@@ -216,30 +330,165 @@ define(FINISH_MASKED_ARRAY_FUNCTION,
       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 proabably not worth it.  */
-          base -= sstride[n] * extent[n];
-          mbase -= mstride[n] * extent[n];
-          dest -= dstride[n] * extent[n];
-          n++;
-          if (n == rank)
-            {
-              /* Break out of the look.  */
-              base = NULL;
-              break;
-            }
-          else
-            {
-              count[n]++;
-              base += sstride[n];
-              mbase += mstride[n];
-              dest += dstride[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.  */
+         base -= sstride[n] * extent[n];
+         mbase -= mstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n == rank)
+           {
+             /* Break out of the look.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}')dnl
+define(SCALAR_ARRAY_FUNCTION,
+`
+extern void `s'name`'rtype_qual`_'atype_code (rtype * const restrict, 
+       atype * const restrict, const index_type * const restrict,
+       GFC_LOGICAL_4 *);
+export_proto(`s'name`'rtype_qual`_'atype_code);
+
+void
+`s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
+       atype * const restrict array, 
+       const index_type * const restrict pdim, 
+       GFC_LOGICAL_4 * mask)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  rtype_name * restrict dest;
+  index_type rank;
+  index_type n;
+  index_type dim;
+
+
+  if (*mask)
+    {
+      name`'rtype_qual`_'atype_code (retarray, array, pdim);
+      return;
+    }
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  for (n = 0; n < dim; n++)
+    {
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      extent[n] =
+       GFC_DESCRIPTOR_EXTENT(array,n + 1);
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->data == NULL)
+    {
+      size_t alloc_size, str;
+
+      for (n = 0; n < rank; n++)
+       {
+         if (n == 0)
+           str = 1;
+         else
+           str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
+
+         GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
+
+       }
+
+      retarray->offset = 0;
+      retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
+
+      alloc_size = sizeof (rtype_name) * GFC_DESCRIPTOR_STRIDE(retarray,rank-1)
+                  * extent[rank-1];
+
+      if (alloc_size == 0)
+       {
+         /* Make sure we have a zero-sized array.  */
+         GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 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 (unlikely (compile_options.bounds_check))
+       {
+         for (n=0; n < rank; n++)
+           {
+             index_type ret_extent;
+
+             ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
+             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]);
+           }
+       }
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+    }
+
+  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,
@@ -247,7 +496,7 @@ define(ARRAY_FUNCTION,
 $2
 START_ARRAY_BLOCK($1)
 $3
-FINISH_ARRAY_FUNCTION')dnl
+FINISH_ARRAY_FUNCTION($4)')dnl
 define(MASKED_ARRAY_FUNCTION,
 `START_MASKED_ARRAY_FUNCTION
 $2