re PR fortran/36313 ([F03] {MIN,MAX}{LOC,VAL} should accept character arguments)
authorThomas Koenig <tkoenig@gcc.gnu.org>
Wed, 22 Nov 2017 18:08:07 +0000 (18:08 +0000)
committerThomas Koenig <tkoenig@gcc.gnu.org>
Wed, 22 Nov 2017 18:08:07 +0000 (18:08 +0000)
2017-11-22  Thomas Koenig  <tkoenig@gcc.gnu.org>

PR fortran/36313
* Makefile.am: Add i_maxloc0s_c, i_maxloc1s_c, i_maxloc2s_c,
i_minloc0s_c, i_minloc1s_c and i_minloc2s_c.
* Makefile.in: Regenerated.
        * generated/maxloc0_16_s1.c: New file.
        * generated/maxloc0_16_s4.c: New file.
        * generated/maxloc0_4_s1.c: New file.
        * generated/maxloc0_4_s4.c: New file.
        * generated/maxloc0_8_s1.c: New file.
        * generated/maxloc0_8_s4.c: New file.
        * generated/maxloc1_16_s1.c: New file.
        * generated/maxloc1_16_s4.c: New file.
        * generated/maxloc1_4_s1.c: New file.
        * generated/maxloc1_4_s4.c: New file.
        * generated/maxloc1_8_s1.c: New file.
        * generated/maxloc1_8_s4.c: New file.
        * generated/maxloc2_16_s1.c: New file.
        * generated/maxloc2_16_s4.c: New file.
        * generated/maxloc2_4_s1.c: New file.
        * generated/maxloc2_4_s4.c: New file.
        * generated/maxloc2_8_s1.c: New file.
        * generated/maxloc2_8_s4.c: New file.
        * generated/minloc0_16_s1.c: New file.
        * generated/minloc0_16_s4.c: New file.
        * generated/minloc0_4_s1.c: New file.
        * generated/minloc0_4_s4.c: New file.
        * generated/minloc0_8_s1.c: New file.
        * generated/minloc0_8_s4.c: New file.
        * generated/minloc1_16_s1.c: New file.
        * generated/minloc1_16_s4.c: New file.
        * generated/minloc1_4_s1.c: New file.
        * generated/minloc1_4_s4.c: New file.
        * generated/minloc1_8_s1.c: New file.
        * generated/minloc1_8_s4.c: New file.
        * generated/minloc2_16_s1.c: New file.
        * generated/minloc2_16_s4.c: New file.
        * generated/minloc2_4_s1.c: New file.
        * generated/minloc2_4_s4.c: New file.
        * generated/minloc2_8_s1.c: New file.
        * generated/minloc2_8_s4.c: New file.
        * m4/iforeach-s.m4: New file.
        * m4/ifunction-s.m4: New file.
        * m4/maxloc0s.m4: New file.
        * m4/maxloc1s.m4: New file.
        * m4/maxloc2s.m4: New file.
        * m4/minloc0s.m4: New file.
        * m4/minloc1s.m4: New file.
        * m4/minloc2s.m4: New file.
* gfortran.map: Add new functions.
* libgfortran.h: Add gfc_array_s1 and gfc_array_s4.

2017-11-22  Thomas Koenig  <tkoenig@gcc.gnu.org>

PR fortran/36313
* check.c (int_or_real_or_char_check_f2003): New function.
* iresolve.c (gfc_resolve_maxloc): Add number "2" for
character arguments and rank-zero return value.
(gfc_resolve_minloc): Likewise.
* trans-intrinsic.c (gfc_conv_intrinsic_minmaxloc): Handle case of
character arguments and rank-zero return value by removing
unneeded arguments and calling the library function.

2017-11-22  Thomas Koenig  <tkoenig@gcc.gnu.org>

PR fortran/36313
* gfortran.dg/maxloc_string_1.f90: New test.
* gfortran.dg/minloc_string_1.f90: New test.

From-SVN: r255070

58 files changed:
gcc/fortran/ChangeLog
gcc/fortran/check.c
gcc/fortran/iresolve.c
gcc/fortran/trans-intrinsic.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/maxloc_string_1.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/minloc_string_1.f90 [new file with mode: 0644]
libgfortran/ChangeLog
libgfortran/Makefile.am
libgfortran/Makefile.in
libgfortran/generated/maxloc0_16_s1.c [new file with mode: 0644]
libgfortran/generated/maxloc0_16_s4.c [new file with mode: 0644]
libgfortran/generated/maxloc0_4_s1.c [new file with mode: 0644]
libgfortran/generated/maxloc0_4_s4.c [new file with mode: 0644]
libgfortran/generated/maxloc0_8_s1.c [new file with mode: 0644]
libgfortran/generated/maxloc0_8_s4.c [new file with mode: 0644]
libgfortran/generated/maxloc1_16_s1.c [new file with mode: 0644]
libgfortran/generated/maxloc1_16_s4.c [new file with mode: 0644]
libgfortran/generated/maxloc1_4_s1.c [new file with mode: 0644]
libgfortran/generated/maxloc1_4_s4.c [new file with mode: 0644]
libgfortran/generated/maxloc1_8_s1.c [new file with mode: 0644]
libgfortran/generated/maxloc1_8_s4.c [new file with mode: 0644]
libgfortran/generated/maxloc2_16_s1.c [new file with mode: 0644]
libgfortran/generated/maxloc2_16_s4.c [new file with mode: 0644]
libgfortran/generated/maxloc2_4_s1.c [new file with mode: 0644]
libgfortran/generated/maxloc2_4_s4.c [new file with mode: 0644]
libgfortran/generated/maxloc2_8_s1.c [new file with mode: 0644]
libgfortran/generated/maxloc2_8_s4.c [new file with mode: 0644]
libgfortran/generated/minloc0_16_s1.c [new file with mode: 0644]
libgfortran/generated/minloc0_16_s4.c [new file with mode: 0644]
libgfortran/generated/minloc0_4_s1.c [new file with mode: 0644]
libgfortran/generated/minloc0_4_s4.c [new file with mode: 0644]
libgfortran/generated/minloc0_8_s1.c [new file with mode: 0644]
libgfortran/generated/minloc0_8_s4.c [new file with mode: 0644]
libgfortran/generated/minloc1_16_s1.c [new file with mode: 0644]
libgfortran/generated/minloc1_16_s4.c [new file with mode: 0644]
libgfortran/generated/minloc1_4_s1.c [new file with mode: 0644]
libgfortran/generated/minloc1_4_s4.c [new file with mode: 0644]
libgfortran/generated/minloc1_8_s1.c [new file with mode: 0644]
libgfortran/generated/minloc1_8_s4.c [new file with mode: 0644]
libgfortran/generated/minloc2_16_s1.c [new file with mode: 0644]
libgfortran/generated/minloc2_16_s4.c [new file with mode: 0644]
libgfortran/generated/minloc2_4_s1.c [new file with mode: 0644]
libgfortran/generated/minloc2_4_s4.c [new file with mode: 0644]
libgfortran/generated/minloc2_8_s1.c [new file with mode: 0644]
libgfortran/generated/minloc2_8_s4.c [new file with mode: 0644]
libgfortran/gfortran.map
libgfortran/libgfortran.h
libgfortran/m4/iforeach-s.m4 [new file with mode: 0644]
libgfortran/m4/ifunction-s.m4 [new file with mode: 0644]
libgfortran/m4/ifunction.m4
libgfortran/m4/iparm.m4
libgfortran/m4/maxloc0s.m4 [new file with mode: 0644]
libgfortran/m4/maxloc1s.m4 [new file with mode: 0644]
libgfortran/m4/maxloc2s.m4 [new file with mode: 0644]
libgfortran/m4/minloc0s.m4 [new file with mode: 0644]
libgfortran/m4/minloc1s.m4 [new file with mode: 0644]
libgfortran/m4/minloc2s.m4 [new file with mode: 0644]

index 7fc965baf81c6a1351a8426e95520a34ac9e6353..30e033afa399e98a9e9c589b9870c050684cf61e 100644 (file)
@@ -1,3 +1,14 @@
+2017-11-22  Thomas Koenig  <tkoenig@gcc.gnu.org>
+
+       PR fortran/36313
+       * check.c (int_or_real_or_char_check_f2003): New function.
+       * iresolve.c (gfc_resolve_maxloc): Add number "2" for
+       character arguments and rank-zero return value.
+       (gfc_resolve_minloc): Likewise.
+       * trans-intrinsic.c (gfc_conv_intrinsic_minmaxloc): Handle case of
+       character arguments and rank-zero return value by removing
+       unneeded arguments and calling the library function.
+
 2017-11-22  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/79072
index a147449bf707c768369e7dc43bd0aae35f9d2e1d..29281723b8d4a8f3adcb7c4dec9650b34e30aae4 100644 (file)
@@ -117,6 +117,37 @@ int_or_real_check (gfc_expr *e, int n)
   return true;
 }
 
+/* Check that an expression is integer or real; allow character for
+   F2003 or later.  */
+
+static bool
+int_or_real_or_char_check_f2003 (gfc_expr *e, int n)
+{
+  if (e->ts.type != BT_INTEGER && e->ts.type != BT_REAL)
+    {
+      if (e->ts.type == BT_CHARACTER)
+       return gfc_notify_std (GFC_STD_F2003, "Fortran 2003: Character for "
+                              "%qs argument of %qs intrinsic at %L",
+                              gfc_current_intrinsic_arg[n]->name,
+                              gfc_current_intrinsic, &e->where);
+      else
+       {
+         if (gfc_option.allow_std & GFC_STD_F2003)
+           gfc_error ("%qs argument of %qs intrinsic at %L must be INTEGER "
+                      "or REAL or CHARACTER",
+                      gfc_current_intrinsic_arg[n]->name,
+                      gfc_current_intrinsic, &e->where);
+         else
+           gfc_error ("%qs argument of %qs intrinsic at %L must be INTEGER "
+                      "or REAL", gfc_current_intrinsic_arg[n]->name,
+                      gfc_current_intrinsic, &e->where);
+       }
+      return false;
+    }
+
+  return true;
+}
+
 
 /* Check that an expression is real or complex.  */
 
@@ -3189,7 +3220,7 @@ gfc_check_minloc_maxloc (gfc_actual_arglist *ap)
   gfc_expr *a, *m, *d, *k;
 
   a = ap->expr;
-  if (!int_or_real_check (a, 0) || !array_check (a, 0))
+  if (!int_or_real_or_char_check_f2003 (a, 0) || !array_check (a, 0))
     return false;
 
   d = ap->next->expr;
index a54ed2295b576a72c2dc636f0723147a5cd9de4a..be1c35bc57e30ab55cf652ba2b0ef5690039bca4 100644 (file)
@@ -1702,6 +1702,7 @@ gfc_resolve_maxloc (gfc_expr *f, gfc_expr *array, gfc_expr *dim,
   const char *name;
   int i, j, idim;
   int fkind;
+  int d_num;
 
   f->ts.type = BT_INTEGER;
 
@@ -1752,8 +1753,18 @@ gfc_resolve_maxloc (gfc_expr *f, gfc_expr *array, gfc_expr *dim,
   else
     name = "maxloc";
 
+  if (dim)
+    {
+      if (array->ts.type != BT_CHARACTER || f->rank != 0)
+       d_num = 1;
+      else
+       d_num = 2;
+    }
+  else
+    d_num = 0;
+
   f->value.function.name
-    = gfc_get_string (PREFIX ("%s%d_%d_%c%d"), name, dim != NULL, f->ts.kind,
+    = gfc_get_string (PREFIX ("%s%d_%d_%c%d"), name, d_num, f->ts.kind,
                      gfc_type_letter (array->ts.type), array->ts.kind);
 
   if (kind)
@@ -1896,6 +1907,7 @@ gfc_resolve_minloc (gfc_expr *f, gfc_expr *array, gfc_expr *dim,
   const char *name;
   int i, j, idim;
   int fkind;
+  int d_num;
 
   f->ts.type = BT_INTEGER;
 
@@ -1946,8 +1958,18 @@ gfc_resolve_minloc (gfc_expr *f, gfc_expr *array, gfc_expr *dim,
   else
     name = "minloc";
 
+  if (dim)
+    {
+      if (array->ts.type != BT_CHARACTER || f->rank != 0)
+       d_num = 1;
+      else
+       d_num = 2;
+    }
+  else
+    d_num = 0;
+
   f->value.function.name
-    = gfc_get_string (PREFIX ("%s%d_%d_%c%d"), name, dim != NULL, f->ts.kind,
+    = gfc_get_string (PREFIX ("%s%d_%d_%c%d"), name, d_num, f->ts.kind,
                      gfc_type_letter (array->ts.type), array->ts.kind);
 
   if (fkind != f->ts.kind)
index b7c57210b8cff3d4dd8f3e5ce7421490f972f2a2..90d5e59a0501618c0cb999f48dec994e9ea2a56d 100644 (file)
@@ -4568,14 +4568,41 @@ gfc_conv_intrinsic_minmaxloc (gfc_se * se, gfc_expr * expr, enum tree_code op)
       return;
     }
 
+  actual = expr->value.function.actual;
+  arrayexpr = actual->expr;
+
+  /* Special case for character maxval.  Remove unneeded actual
+     arguments, then call a library function.  */
+  
+  if (arrayexpr->ts.type == BT_CHARACTER)
+    {
+      gfc_actual_arglist *a2, *a3, *a4;
+      a2 = actual->next;
+      a3 = a2->next;
+      a4 = a3->next;
+      a4->next = NULL;
+      if (a3->expr == NULL)
+       {
+         actual->next = NULL;
+         gfc_free_actual_arglist (a2);
+       }
+      else
+       {
+         actual->next = a3;  /* dim */
+         a3->next = NULL;
+         a2->next = a4;
+         gfc_free_actual_arglist (a4);
+       }
+      gfc_conv_intrinsic_funcall (se, expr);
+      return;
+    }
+
   /* Initialize the result.  */
   pos = gfc_create_var (gfc_array_index_type, "pos");
   offset = gfc_create_var (gfc_array_index_type, "offset");
   type = gfc_typenode_for_spec (&expr->ts);
 
   /* Walk the arguments.  */
-  actual = expr->value.function.actual;
-  arrayexpr = actual->expr;
   arrayss = gfc_walk_expr (arrayexpr);
   gcc_assert (arrayss != gfc_ss_terminator);
 
index 737424b1fd9ab33dba821f53a068ef38f033c333..573a97a4762fc49be78c85aba627906417b75e76 100644 (file)
@@ -1,3 +1,9 @@
+2017-11-22  Thomas Koenig  <tkoenig@gcc.gnu.org>
+
+       PR fortran/36313
+       * gfortran.dg/maxloc_string_1.f90: New test.
+       * gfortran.dg/minloc_string_1.f90: New test.
+
 2017-11-22  Marc Glisse  <marc.glisse@inria.fr>
 
        PR tree-optimization/83104
diff --git a/gcc/testsuite/gfortran.dg/maxloc_string_1.f90 b/gcc/testsuite/gfortran.dg/maxloc_string_1.f90
new file mode 100644 (file)
index 0000000..a551162
--- /dev/null
@@ -0,0 +1,91 @@
+! { dg-do run }
+! Test maxloc for strings for different code paths
+
+program main
+  implicit none
+  integer, parameter :: n=4
+  character(len=4), dimension(n,n) :: c
+  integer, dimension(n,n) :: a
+  integer, dimension(2) :: res1, res2
+  real, dimension(n,n) :: r
+  logical, dimension(n,n) :: amask
+  logical(kind=8) :: smask
+  integer :: i,j
+  integer, dimension(n) :: q1, q2
+  character(len=4,kind=4), dimension(n,n) :: c4
+  character(len=4), dimension(n*n) :: e
+  integer, dimension(n*n) :: f
+  logical, dimension(n*n) :: cmask
+
+  call random_number (r)
+  a = int(r*100)
+  do j=1,n
+     do i=1,n
+        write (unit=c(i,j),fmt='(I4.4)') a(i,j)
+        write (unit=c4(i,j),fmt='(I4.4)') a(i,j)
+     end do
+  end do
+  res1 = maxloc(c)
+  res2 = maxloc(a)
+
+  if (any(res1 /= res2)) call abort
+  res1 = maxloc(c4)
+  if (any(res1 /= res2)) call abort
+
+  amask = a < 50
+  res1 = maxloc(c,mask=amask)
+  res2 = maxloc(a,mask=amask)
+
+ if (any(res1 /= res2)) call abort
+
+ amask = .false.
+ res1 = maxloc(c,mask=amask)
+ if (any(res1 /= 0)) call abort
+
+ amask(2,3) = .true.
+ res1 = maxloc(c,mask=amask)
+ if (any(res1 /= [2,3])) call abort
+
+ res1 = maxloc(c,mask=.false.)
+ if (any(res1 /= 0)) call abort
+
+ res2 = maxloc(a)
+ res1 = maxloc(c,mask=.true.)
+ if (any(res1 /= res2)) call abort
+
+ q1 = maxloc(c, dim=1)
+ q2 = maxloc(a, dim=1)
+ if (any(q1 /= q2)) call abort
+
+ q1 = maxloc(c, dim=2)
+ q2 = maxloc(a, dim=2)
+ if (any(q1 /= q2)) call abort
+
+ q1 = maxloc(c, dim=1, mask=amask)
+ q2 = maxloc(a, dim=1, mask=amask)
+ if (any(q1 /= q2)) call abort
+
+ q1 = maxloc(c, dim=2, mask=amask)
+ q2 = maxloc(a, dim=2, mask=amask)
+ if (any(q1 /= q2)) call abort
+
+  amask = a < 50
+
+ q1 = maxloc(c, dim=1, mask=amask)
+ q2 = maxloc(a, dim=1, mask=amask)
+ if (any(q1 /= q2)) call abort
+
+ q1 = maxloc(c, dim=2, mask=amask)
+ q2 = maxloc(a, dim=2, mask=amask)
+ if (any(q1 /= q2)) call abort
+
+ e = reshape(c, shape(e))
+ f = reshape(a, shape(f))
+ if (maxloc(e,dim=1) /= maxloc(f,dim=1)) call abort
+
+ cmask = .false.
+ if (maxloc(e,dim=1,mask=cmask) /= 0) call abort
+
+ cmask = f > 50
+ if ( maxloc(e, dim=1, mask=cmask) /= maxloc (f, dim=1, mask=cmask)) call abort
+end program main
diff --git a/gcc/testsuite/gfortran.dg/minloc_string_1.f90 b/gcc/testsuite/gfortran.dg/minloc_string_1.f90
new file mode 100644 (file)
index 0000000..88847cc
--- /dev/null
@@ -0,0 +1,91 @@
+! { dg-do run }
+! Test minloc for strings for different code paths
+
+program main
+  implicit none
+  integer, parameter :: n=4
+  character(len=4), dimension(n,n) :: c
+  integer, dimension(n,n) :: a
+  integer, dimension(2) :: res1, res2
+  real, dimension(n,n) :: r
+  logical, dimension(n,n) :: amask
+  logical(kind=8) :: smask
+  integer :: i,j
+  integer, dimension(n) :: q1, q2
+  character(len=4,kind=4), dimension(n,n) :: c4
+  character(len=4), dimension(n*n) :: e
+  integer, dimension(n*n) :: f
+  logical, dimension(n*n) :: cmask
+
+  call random_number (r)
+  a = int(r*100)
+  do j=1,n
+     do i=1,n
+        write (unit=c(i,j),fmt='(I4.4)') a(i,j)
+        write (unit=c4(i,j),fmt='(I4.4)') a(i,j)
+     end do
+  end do
+  res1 = minloc(c)
+  res2 = minloc(a)
+
+  if (any(res1 /= res2)) call abort
+  res1 = minloc(c4)
+  if (any(res1 /= res2)) call abort
+
+  amask = a < 50
+  res1 = minloc(c,mask=amask)
+  res2 = minloc(a,mask=amask)
+
+ if (any(res1 /= res2)) call abort
+
+ amask = .false.
+ res1 = minloc(c,mask=amask)
+ if (any(res1 /= 0)) call abort
+
+ amask(2,3) = .true.
+ res1 = minloc(c,mask=amask)
+ if (any(res1 /= [2,3])) call abort
+
+ res1 = minloc(c,mask=.false.)
+ if (any(res1 /= 0)) call abort
+
+ res2 = minloc(a)
+ res1 = minloc(c,mask=.true.)
+ if (any(res1 /= res2)) call abort
+
+ q1 = minloc(c, dim=1)
+ q2 = minloc(a, dim=1)
+ if (any(q1 /= q2)) call abort
+
+ q1 = minloc(c, dim=2)
+ q2 = minloc(a, dim=2)
+ if (any(q1 /= q2)) call abort
+
+ q1 = minloc(c, dim=1, mask=amask)
+ q2 = minloc(a, dim=1, mask=amask)
+ if (any(q1 /= q2)) call abort
+
+ q1 = minloc(c, dim=2, mask=amask)
+ q2 = minloc(a, dim=2, mask=amask)
+ if (any(q1 /= q2)) call abort
+
+  amask = a < 50
+
+ q1 = minloc(c, dim=1, mask=amask)
+ q2 = minloc(a, dim=1, mask=amask)
+ if (any(q1 /= q2)) call abort
+
+ q1 = minloc(c, dim=2, mask=amask)
+ q2 = minloc(a, dim=2, mask=amask)
+ if (any(q1 /= q2)) call abort
+
+ e = reshape(c, shape(e))
+ f = reshape(a, shape(f))
+ if (minloc(e,dim=1) /= minloc(f,dim=1)) call abort
+
+ cmask = .false.
+ if (minloc(e,dim=1,mask=cmask) /= 0) call abort
+
+ cmask = f > 50
+ if ( minloc(e, dim=1, mask=cmask) /= minloc (f, dim=1, mask=cmask)) call abort
+end program main
index 2c7b3f1e00fe70592261b91d3133cdf1ad9a34d4..85d73951ac676a8b48c8d78ae2d1fdba9f6fc2f1 100644 (file)
@@ -1,3 +1,56 @@
+2017-11-22  Thomas Koenig  <tkoenig@gcc.gnu.org>
+
+       PR fortran/36313
+       * Makefile.am: Add i_maxloc0s_c, i_maxloc1s_c, i_maxloc2s_c,
+       i_minloc0s_c, i_minloc1s_c and i_minloc2s_c.
+       * Makefile.in: Regenerated.
+        * generated/maxloc0_16_s1.c: New file.
+        * generated/maxloc0_16_s4.c: New file.
+        * generated/maxloc0_4_s1.c: New file.
+        * generated/maxloc0_4_s4.c: New file.
+        * generated/maxloc0_8_s1.c: New file.
+        * generated/maxloc0_8_s4.c: New file.
+        * generated/maxloc1_16_s1.c: New file.
+        * generated/maxloc1_16_s4.c: New file.
+        * generated/maxloc1_4_s1.c: New file.
+        * generated/maxloc1_4_s4.c: New file.
+        * generated/maxloc1_8_s1.c: New file.
+        * generated/maxloc1_8_s4.c: New file.
+        * generated/maxloc2_16_s1.c: New file.
+        * generated/maxloc2_16_s4.c: New file.
+        * generated/maxloc2_4_s1.c: New file.
+        * generated/maxloc2_4_s4.c: New file.
+        * generated/maxloc2_8_s1.c: New file.
+        * generated/maxloc2_8_s4.c: New file.
+        * generated/minloc0_16_s1.c: New file.
+        * generated/minloc0_16_s4.c: New file.
+        * generated/minloc0_4_s1.c: New file.
+        * generated/minloc0_4_s4.c: New file.
+        * generated/minloc0_8_s1.c: New file.
+        * generated/minloc0_8_s4.c: New file.
+        * generated/minloc1_16_s1.c: New file.
+        * generated/minloc1_16_s4.c: New file.
+        * generated/minloc1_4_s1.c: New file.
+        * generated/minloc1_4_s4.c: New file.
+        * generated/minloc1_8_s1.c: New file.
+        * generated/minloc1_8_s4.c: New file.
+        * generated/minloc2_16_s1.c: New file.
+        * generated/minloc2_16_s4.c: New file.
+        * generated/minloc2_4_s1.c: New file.
+        * generated/minloc2_4_s4.c: New file.
+        * generated/minloc2_8_s1.c: New file.
+        * generated/minloc2_8_s4.c: New file.
+        * m4/iforeach-s.m4: New file.
+        * m4/ifunction-s.m4: New file.
+        * m4/maxloc0s.m4: New file.
+        * m4/maxloc1s.m4: New file.
+        * m4/maxloc2s.m4: New file.
+        * m4/minloc0s.m4: New file.
+        * m4/minloc1s.m4: New file.
+        * m4/minloc2s.m4: New file.
+       * gfortran.map: Add new functions.
+       * libgfortran.h: Add gfc_array_s1 and gfc_array_s4.
+
 2017-11-22  Janne Blomqvist  <jb@gcc.gnu.org>
 
        PR libfortran/83070
index c5982a7d9db3c6d782efa2e9de5bb784628ce25c..b88d62b685732aa5f174b0b531bd1334f4fc3701 100644 (file)
@@ -293,6 +293,14 @@ $(srcdir)/generated/maxloc0_4_r16.c \
 $(srcdir)/generated/maxloc0_8_r16.c \
 $(srcdir)/generated/maxloc0_16_r16.c
 
+i_maxloc0s_c = \
+$(srcdir)/generated/maxloc0_4_s1.c \
+$(srcdir)/generated/maxloc0_4_s4.c \
+$(srcdir)/generated/maxloc0_8_s1.c \
+$(srcdir)/generated/maxloc0_8_s4.c \
+$(srcdir)/generated/maxloc0_16_s1.c \
+$(srcdir)/generated/maxloc0_16_s4.c
+
 i_maxloc1_c= \
 $(srcdir)/generated/maxloc1_4_i1.c \
 $(srcdir)/generated/maxloc1_8_i1.c \
@@ -322,6 +330,22 @@ $(srcdir)/generated/maxloc1_4_r16.c \
 $(srcdir)/generated/maxloc1_8_r16.c \
 $(srcdir)/generated/maxloc1_16_r16.c
 
+i_maxloc1s_c= \
+$(srcdir)/generated/maxloc1_4_s1.c \
+$(srcdir)/generated/maxloc1_4_s4.c \
+$(srcdir)/generated/maxloc1_8_s1.c \
+$(srcdir)/generated/maxloc1_8_s4.c \
+$(srcdir)/generated/maxloc1_16_s1.c \
+$(srcdir)/generated/maxloc1_16_s4.c
+
+i_maxloc2s_c= \
+$(srcdir)/generated/maxloc2_4_s1.c \
+$(srcdir)/generated/maxloc2_4_s4.c \
+$(srcdir)/generated/maxloc2_8_s1.c \
+$(srcdir)/generated/maxloc2_8_s4.c \
+$(srcdir)/generated/maxloc2_16_s1.c \
+$(srcdir)/generated/maxloc2_16_s4.c
+
 i_maxval_c= \
 $(srcdir)/generated/maxval_i1.c \
 $(srcdir)/generated/maxval_i2.c \
@@ -362,6 +386,14 @@ $(srcdir)/generated/minloc0_4_r16.c \
 $(srcdir)/generated/minloc0_8_r16.c \
 $(srcdir)/generated/minloc0_16_r16.c
 
+i_minloc0s_c = \
+$(srcdir)/generated/minloc0_4_s1.c \
+$(srcdir)/generated/minloc0_4_s4.c \
+$(srcdir)/generated/minloc0_8_s1.c \
+$(srcdir)/generated/minloc0_8_s4.c \
+$(srcdir)/generated/minloc0_16_s1.c \
+$(srcdir)/generated/minloc0_16_s4.c
+
 i_minloc1_c= \
 $(srcdir)/generated/minloc1_4_i1.c \
 $(srcdir)/generated/minloc1_8_i1.c \
@@ -391,6 +423,22 @@ $(srcdir)/generated/minloc1_4_r16.c \
 $(srcdir)/generated/minloc1_8_r16.c \
 $(srcdir)/generated/minloc1_16_r16.c
 
+i_minloc1s_c= \
+$(srcdir)/generated/minloc1_4_s1.c \
+$(srcdir)/generated/minloc1_4_s4.c \
+$(srcdir)/generated/minloc1_8_s1.c \
+$(srcdir)/generated/minloc1_8_s4.c \
+$(srcdir)/generated/minloc1_16_s1.c \
+$(srcdir)/generated/minloc1_16_s4.c
+
+i_minloc2s_c= \
+$(srcdir)/generated/minloc2_4_s1.c \
+$(srcdir)/generated/minloc2_4_s4.c \
+$(srcdir)/generated/minloc2_8_s1.c \
+$(srcdir)/generated/minloc2_8_s4.c \
+$(srcdir)/generated/minloc2_16_s1.c \
+$(srcdir)/generated/minloc2_16_s4.c
+
 i_minval_c= \
 $(srcdir)/generated/minval_i1.c \
 $(srcdir)/generated/minval_i2.c \
@@ -688,7 +736,7 @@ m4_files= m4/iparm.m4 m4/ifunction.m4 m4/iforeach.m4 m4/all.m4 \
     m4/pow.m4 \
     m4/misc_specifics.m4 m4/pack.m4 \
     m4/unpack.m4 m4/spread.m4 m4/bessel.m4 m4/norm2.m4 m4/parity.m4 \
-    m4/iall.m4 m4/iany.m4 m4/iparity.m4
+    m4/iall.m4 m4/iany.m4 m4/iparity.m4 m4/iforeach-s.m4
 
 gfor_built_src= $(i_all_c) $(i_any_c) $(i_count_c) $(i_maxloc0_c) \
     $(i_maxloc1_c) $(i_maxval_c) $(i_minloc0_c) $(i_minloc1_c) $(i_minval_c) \
@@ -699,7 +747,8 @@ gfor_built_src= $(i_all_c) $(i_any_c) $(i_count_c) $(i_maxloc0_c) \
     $(i_pow_c) $(i_pack_c) $(i_unpack_c) $(i_matmulavx128_c) \
     $(i_spread_c) selected_int_kind.inc selected_real_kind.inc kinds.h \
     $(i_cshift0_c) kinds.inc c99_protos.inc fpu-target.h fpu-target.inc \
-    $(i_cshift1a_c)
+    $(i_cshift1a_c) $(i_maxloc0s_c) $(i_minloc0s_c) $(i_maxloc1s_c) \
+    $(i_minloc1s_c) $(i_maxloc2s_c) $(i_minloc2s_c)
 
 # Machine generated specifics
 gfor_built_specific_src= \
@@ -922,6 +971,8 @@ I_M4_DEPS=m4/iparm.m4
 I_M4_DEPS0=$(I_M4_DEPS) m4/iforeach.m4
 I_M4_DEPS1=$(I_M4_DEPS) m4/ifunction.m4
 I_M4_DEPS2=$(I_M4_DEPS) m4/ifunction_logical.m4
+I_M4_DEPS3=$(I_M4_DEPS) m4/iforeach-s.m4
+I_M4_DEPS4=$(I_M4_DEPS) m4/ifunction-s.m4
 
 kinds.h: $(srcdir)/mk-kinds-h.sh
        $(SHELL) $(srcdir)/mk-kinds-h.sh '$(FCCOMPILE)' > $@ || rm $@
@@ -973,18 +1024,36 @@ $(i_iparity_c): m4/iparity.m4 $(I_M4_DEPS1)
 $(i_maxloc0_c): m4/maxloc0.m4 $(I_M4_DEPS0)
        $(M4) -Dfile=$@ -I$(srcdir)/m4 maxloc0.m4 > $@
 
+$(i_maxloc0s_c) : m4/maxloc0s.m4 $(I_M4_DEPS3)
+       $(M4) -Dfile=$@ -I$(srcdir)/m4 maxloc0s.m4 > $@
+
 $(i_maxloc1_c): m4/maxloc1.m4 $(I_M4_DEPS1)
        $(M4) -Dfile=$@ -I$(srcdir)/m4 maxloc1.m4 > $@
 
+$(i_maxloc1s_c): m4/maxloc1s.m4 $(I_M4_DEPS4)
+       $(M4) -Dfile=$@ -I$(srcdir)/m4 maxloc1s.m4 > $@
+
+$(i_maxloc2s_c): m4/maxloc2s.m4 $(I_M4_DEPS)
+       $(M4) -Dfile=$@ -I$(srcdir)/m4 maxloc2s.m4 > $@
+
 $(i_maxval_c): m4/maxval.m4 $(I_M4_DEPS1)
        $(M4) -Dfile=$@ -I$(srcdir)/m4 maxval.m4 > $@
 
 $(i_minloc0_c): m4/minloc0.m4 $(I_M4_DEPS0)
        $(M4) -Dfile=$@ -I$(srcdir)/m4 minloc0.m4 > $@
 
+$(i_minloc0s_c) : m4/minloc0s.m4 $(I_M4_DEPS3)
+       $(M4) -Dfile=$@ -I$(srcdir)/m4 minloc0s.m4 > $@
+
 $(i_minloc1_c): m4/minloc1.m4 $(I_M4_DEPS1)
        $(M4) -Dfile=$@ -I$(srcdir)/m4 minloc1.m4 > $@
 
+$(i_minloc1s_c): m4/minloc1s.m4 $(I_M4_DEPS4)
+       $(M4) -Dfile=$@ -I$(srcdir)/m4 minloc1s.m4 > $@
+
+$(i_minloc2s_c): m4/minloc2s.m4 $(I_M4_DEPS)
+       $(M4) -Dfile=$@ -I$(srcdir)/m4 minloc2s.m4 > $@
+
 $(i_minval_c): m4/minval.m4 $(I_M4_DEPS1)
        $(M4) -Dfile=$@ -I$(srcdir)/m4 minval.m4 > $@
 
index e97d1bc425581ba23ecd8ad8e730cde0e3c93431..0263498878267a91024b2126f096ce76078005e6 100644 (file)
@@ -317,7 +317,19 @@ am__objects_36 = cshift1_4_i1.lo cshift1_4_i2.lo cshift1_4_i4.lo \
        cshift1_16_i16.lo cshift1_16_r4.lo cshift1_16_r8.lo \
        cshift1_16_r10.lo cshift1_16_r16.lo cshift1_16_c4.lo \
        cshift1_16_c8.lo cshift1_16_c10.lo cshift1_16_c16.lo
-am__objects_37 = $(am__objects_4) $(am__objects_5) $(am__objects_6) \
+am__objects_37 = maxloc0_4_s1.lo maxloc0_4_s4.lo maxloc0_8_s1.lo \
+       maxloc0_8_s4.lo maxloc0_16_s1.lo maxloc0_16_s4.lo
+am__objects_38 = minloc0_4_s1.lo minloc0_4_s4.lo minloc0_8_s1.lo \
+       minloc0_8_s4.lo minloc0_16_s1.lo minloc0_16_s4.lo
+am__objects_39 = maxloc1_4_s1.lo maxloc1_4_s4.lo maxloc1_8_s1.lo \
+       maxloc1_8_s4.lo maxloc1_16_s1.lo maxloc1_16_s4.lo
+am__objects_40 = minloc1_4_s1.lo minloc1_4_s4.lo minloc1_8_s1.lo \
+       minloc1_8_s4.lo minloc1_16_s1.lo minloc1_16_s4.lo
+am__objects_41 = maxloc2_4_s1.lo maxloc2_4_s4.lo maxloc2_8_s1.lo \
+       maxloc2_8_s4.lo maxloc2_16_s1.lo maxloc2_16_s4.lo
+am__objects_42 = minloc2_4_s1.lo minloc2_4_s4.lo minloc2_8_s1.lo \
+       minloc2_8_s4.lo minloc2_16_s1.lo minloc2_16_s4.lo
+am__objects_43 = $(am__objects_4) $(am__objects_5) $(am__objects_6) \
        $(am__objects_7) $(am__objects_8) $(am__objects_9) \
        $(am__objects_10) $(am__objects_11) $(am__objects_12) \
        $(am__objects_13) $(am__objects_14) $(am__objects_15) \
@@ -327,14 +339,16 @@ am__objects_37 = $(am__objects_4) $(am__objects_5) $(am__objects_6) \
        $(am__objects_25) $(am__objects_26) $(am__objects_27) \
        $(am__objects_28) $(am__objects_29) $(am__objects_30) \
        $(am__objects_31) $(am__objects_32) $(am__objects_33) \
-       $(am__objects_34) $(am__objects_35) $(am__objects_36)
-@LIBGFOR_MINIMAL_FALSE@am__objects_38 = close.lo file_pos.lo format.lo \
+       $(am__objects_34) $(am__objects_35) $(am__objects_36) \
+       $(am__objects_37) $(am__objects_38) $(am__objects_39) \
+       $(am__objects_40) $(am__objects_41) $(am__objects_42)
+@LIBGFOR_MINIMAL_FALSE@am__objects_44 = close.lo file_pos.lo format.lo \
 @LIBGFOR_MINIMAL_FALSE@        inquire.lo intrinsics.lo list_read.lo \
 @LIBGFOR_MINIMAL_FALSE@        lock.lo open.lo read.lo transfer.lo \
 @LIBGFOR_MINIMAL_FALSE@        transfer128.lo unit.lo unix.lo write.lo \
 @LIBGFOR_MINIMAL_FALSE@        fbuf.lo
-am__objects_39 = size_from_kind.lo $(am__objects_38)
-@LIBGFOR_MINIMAL_FALSE@am__objects_40 = access.lo c99_functions.lo \
+am__objects_45 = size_from_kind.lo $(am__objects_44)
+@LIBGFOR_MINIMAL_FALSE@am__objects_46 = access.lo c99_functions.lo \
 @LIBGFOR_MINIMAL_FALSE@        chdir.lo chmod.lo clock.lo cpu_time.lo \
 @LIBGFOR_MINIMAL_FALSE@        ctime.lo date_and_time.lo dtime.lo \
 @LIBGFOR_MINIMAL_FALSE@        env.lo etime.lo execute_command_line.lo \
@@ -344,19 +358,19 @@ am__objects_39 = size_from_kind.lo $(am__objects_38)
 @LIBGFOR_MINIMAL_FALSE@        rename.lo stat.lo symlnk.lo \
 @LIBGFOR_MINIMAL_FALSE@        system_clock.lo time.lo umask.lo \
 @LIBGFOR_MINIMAL_FALSE@        unlink.lo
-@IEEE_SUPPORT_TRUE@am__objects_41 = ieee_helper.lo
-am__objects_42 = associated.lo abort.lo args.lo cshift0.lo eoshift0.lo \
+@IEEE_SUPPORT_TRUE@am__objects_47 = ieee_helper.lo
+am__objects_48 = associated.lo abort.lo args.lo cshift0.lo eoshift0.lo \
        eoshift2.lo erfc_scaled.lo extends_type_of.lo fnum.lo \
        ierrno.lo ishftc.lo mvbits.lo move_alloc.lo pack_generic.lo \
        selected_char_kind.lo size.lo spread_generic.lo \
        string_intrinsics.lo rand.lo random.lo reshape_generic.lo \
        reshape_packed.lo selected_int_kind.lo selected_real_kind.lo \
        unpack_generic.lo in_pack_generic.lo in_unpack_generic.lo \
-       $(am__objects_40) $(am__objects_41)
-@IEEE_SUPPORT_TRUE@am__objects_43 = ieee_arithmetic.lo \
+       $(am__objects_46) $(am__objects_47)
+@IEEE_SUPPORT_TRUE@am__objects_49 = ieee_arithmetic.lo \
 @IEEE_SUPPORT_TRUE@    ieee_exceptions.lo ieee_features.lo
-am__objects_44 =
-am__objects_45 = _abs_c4.lo _abs_c8.lo _abs_c10.lo _abs_c16.lo \
+am__objects_50 =
+am__objects_51 = _abs_c4.lo _abs_c8.lo _abs_c10.lo _abs_c16.lo \
        _abs_i4.lo _abs_i8.lo _abs_i16.lo _abs_r4.lo _abs_r8.lo \
        _abs_r10.lo _abs_r16.lo _aimag_c4.lo _aimag_c8.lo \
        _aimag_c10.lo _aimag_c16.lo _exp_r4.lo _exp_r8.lo _exp_r10.lo \
@@ -380,19 +394,19 @@ am__objects_45 = _abs_c4.lo _abs_c8.lo _abs_c10.lo _abs_c16.lo \
        _conjg_c4.lo _conjg_c8.lo _conjg_c10.lo _conjg_c16.lo \
        _aint_r4.lo _aint_r8.lo _aint_r10.lo _aint_r16.lo _anint_r4.lo \
        _anint_r8.lo _anint_r10.lo _anint_r16.lo
-am__objects_46 = _sign_i4.lo _sign_i8.lo _sign_i16.lo _sign_r4.lo \
+am__objects_52 = _sign_i4.lo _sign_i8.lo _sign_i16.lo _sign_r4.lo \
        _sign_r8.lo _sign_r10.lo _sign_r16.lo _dim_i4.lo _dim_i8.lo \
        _dim_i16.lo _dim_r4.lo _dim_r8.lo _dim_r10.lo _dim_r16.lo \
        _atan2_r4.lo _atan2_r8.lo _atan2_r10.lo _atan2_r16.lo \
        _mod_i4.lo _mod_i8.lo _mod_i16.lo _mod_r4.lo _mod_r8.lo \
        _mod_r10.lo _mod_r16.lo
-am__objects_47 = misc_specifics.lo
-am__objects_48 = $(am__objects_45) $(am__objects_46) $(am__objects_47) \
+am__objects_53 = misc_specifics.lo
+am__objects_54 = $(am__objects_51) $(am__objects_52) $(am__objects_53) \
        dprod_r8.lo f2c_specifics.lo
-am__objects_49 = $(am__objects_3) $(am__objects_37) $(am__objects_39) \
-       $(am__objects_42) $(am__objects_43) $(am__objects_44) \
-       $(am__objects_48)
-@onestep_FALSE@am_libgfortran_la_OBJECTS = $(am__objects_49)
+am__objects_55 = $(am__objects_3) $(am__objects_43) $(am__objects_45) \
+       $(am__objects_48) $(am__objects_49) $(am__objects_50) \
+       $(am__objects_54)
+@onestep_FALSE@am_libgfortran_la_OBJECTS = $(am__objects_55)
 @onestep_TRUE@am_libgfortran_la_OBJECTS = libgfortran_c.lo
 libgfortran_la_OBJECTS = $(am_libgfortran_la_OBJECTS)
 DEFAULT_INCLUDES = -I.@am__isrc@
@@ -732,6 +746,14 @@ $(srcdir)/generated/maxloc0_4_r16.c \
 $(srcdir)/generated/maxloc0_8_r16.c \
 $(srcdir)/generated/maxloc0_16_r16.c
 
+i_maxloc0s_c = \
+$(srcdir)/generated/maxloc0_4_s1.c \
+$(srcdir)/generated/maxloc0_4_s4.c \
+$(srcdir)/generated/maxloc0_8_s1.c \
+$(srcdir)/generated/maxloc0_8_s4.c \
+$(srcdir)/generated/maxloc0_16_s1.c \
+$(srcdir)/generated/maxloc0_16_s4.c
+
 i_maxloc1_c = \
 $(srcdir)/generated/maxloc1_4_i1.c \
 $(srcdir)/generated/maxloc1_8_i1.c \
@@ -761,6 +783,22 @@ $(srcdir)/generated/maxloc1_4_r16.c \
 $(srcdir)/generated/maxloc1_8_r16.c \
 $(srcdir)/generated/maxloc1_16_r16.c
 
+i_maxloc1s_c = \
+$(srcdir)/generated/maxloc1_4_s1.c \
+$(srcdir)/generated/maxloc1_4_s4.c \
+$(srcdir)/generated/maxloc1_8_s1.c \
+$(srcdir)/generated/maxloc1_8_s4.c \
+$(srcdir)/generated/maxloc1_16_s1.c \
+$(srcdir)/generated/maxloc1_16_s4.c
+
+i_maxloc2s_c = \
+$(srcdir)/generated/maxloc2_4_s1.c \
+$(srcdir)/generated/maxloc2_4_s4.c \
+$(srcdir)/generated/maxloc2_8_s1.c \
+$(srcdir)/generated/maxloc2_8_s4.c \
+$(srcdir)/generated/maxloc2_16_s1.c \
+$(srcdir)/generated/maxloc2_16_s4.c
+
 i_maxval_c = \
 $(srcdir)/generated/maxval_i1.c \
 $(srcdir)/generated/maxval_i2.c \
@@ -801,6 +839,14 @@ $(srcdir)/generated/minloc0_4_r16.c \
 $(srcdir)/generated/minloc0_8_r16.c \
 $(srcdir)/generated/minloc0_16_r16.c
 
+i_minloc0s_c = \
+$(srcdir)/generated/minloc0_4_s1.c \
+$(srcdir)/generated/minloc0_4_s4.c \
+$(srcdir)/generated/minloc0_8_s1.c \
+$(srcdir)/generated/minloc0_8_s4.c \
+$(srcdir)/generated/minloc0_16_s1.c \
+$(srcdir)/generated/minloc0_16_s4.c
+
 i_minloc1_c = \
 $(srcdir)/generated/minloc1_4_i1.c \
 $(srcdir)/generated/minloc1_8_i1.c \
@@ -830,6 +876,22 @@ $(srcdir)/generated/minloc1_4_r16.c \
 $(srcdir)/generated/minloc1_8_r16.c \
 $(srcdir)/generated/minloc1_16_r16.c
 
+i_minloc1s_c = \
+$(srcdir)/generated/minloc1_4_s1.c \
+$(srcdir)/generated/minloc1_4_s4.c \
+$(srcdir)/generated/minloc1_8_s1.c \
+$(srcdir)/generated/minloc1_8_s4.c \
+$(srcdir)/generated/minloc1_16_s1.c \
+$(srcdir)/generated/minloc1_16_s4.c
+
+i_minloc2s_c = \
+$(srcdir)/generated/minloc2_4_s1.c \
+$(srcdir)/generated/minloc2_4_s4.c \
+$(srcdir)/generated/minloc2_8_s1.c \
+$(srcdir)/generated/minloc2_8_s4.c \
+$(srcdir)/generated/minloc2_16_s1.c \
+$(srcdir)/generated/minloc2_16_s4.c
+
 i_minval_c = \
 $(srcdir)/generated/minval_i1.c \
 $(srcdir)/generated/minval_i2.c \
@@ -1127,7 +1189,7 @@ m4_files = m4/iparm.m4 m4/ifunction.m4 m4/iforeach.m4 m4/all.m4 \
     m4/pow.m4 \
     m4/misc_specifics.m4 m4/pack.m4 \
     m4/unpack.m4 m4/spread.m4 m4/bessel.m4 m4/norm2.m4 m4/parity.m4 \
-    m4/iall.m4 m4/iany.m4 m4/iparity.m4
+    m4/iall.m4 m4/iany.m4 m4/iparity.m4 m4/iforeach-s.m4
 
 gfor_built_src = $(i_all_c) $(i_any_c) $(i_count_c) $(i_maxloc0_c) \
     $(i_maxloc1_c) $(i_maxval_c) $(i_minloc0_c) $(i_minloc1_c) $(i_minval_c) \
@@ -1138,7 +1200,8 @@ gfor_built_src = $(i_all_c) $(i_any_c) $(i_count_c) $(i_maxloc0_c) \
     $(i_pow_c) $(i_pack_c) $(i_unpack_c) $(i_matmulavx128_c) \
     $(i_spread_c) selected_int_kind.inc selected_real_kind.inc kinds.h \
     $(i_cshift0_c) kinds.inc c99_protos.inc fpu-target.h fpu-target.inc \
-    $(i_cshift1a_c)
+    $(i_cshift1a_c) $(i_maxloc0s_c) $(i_minloc0s_c) $(i_maxloc1s_c) \
+    $(i_minloc1s_c) $(i_maxloc2s_c) $(i_minloc2s_c)
 
 
 # Machine generated specifics
@@ -1314,6 +1377,8 @@ I_M4_DEPS = m4/iparm.m4
 I_M4_DEPS0 = $(I_M4_DEPS) m4/iforeach.m4
 I_M4_DEPS1 = $(I_M4_DEPS) m4/ifunction.m4
 I_M4_DEPS2 = $(I_M4_DEPS) m4/ifunction_logical.m4
+I_M4_DEPS3 = $(I_M4_DEPS) m4/iforeach-s.m4
+I_M4_DEPS4 = $(I_M4_DEPS) m4/ifunction-s.m4
 EXTRA_DIST = $(m4_files)
 all: $(BUILT_SOURCES) config.h
        $(MAKE) $(AM_MAKEFLAGS) all-am
@@ -1656,6 +1721,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_16_r16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_16_r4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_16_r8.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_16_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_16_s4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_4_i1.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_4_i16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_4_i2.Plo@am__quote@
@@ -1665,6 +1732,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_4_r16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_4_r4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_4_r8.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_4_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_4_s4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_8_i1.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_8_i16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_8_i2.Plo@am__quote@
@@ -1674,6 +1743,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_8_r16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_8_r4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_8_r8.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_8_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc0_8_s4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_16_i1.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_16_i16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_16_i2.Plo@am__quote@
@@ -1683,6 +1754,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_16_r16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_16_r4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_16_r8.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_16_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_16_s4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_4_i1.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_4_i16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_4_i2.Plo@am__quote@
@@ -1692,6 +1765,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_4_r16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_4_r4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_4_r8.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_4_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_4_s4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_8_i1.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_8_i16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_8_i2.Plo@am__quote@
@@ -1701,6 +1776,14 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_8_r16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_8_r4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_8_r8.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_8_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc1_8_s4.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc2_16_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc2_16_s4.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc2_4_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc2_4_s4.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc2_8_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxloc2_8_s4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxval_i1.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxval_i16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxval_i2.Plo@am__quote@
@@ -1721,6 +1804,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_16_r16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_16_r4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_16_r8.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_16_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_16_s4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_4_i1.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_4_i16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_4_i2.Plo@am__quote@
@@ -1730,6 +1815,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_4_r16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_4_r4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_4_r8.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_4_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_4_s4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_8_i1.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_8_i16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_8_i2.Plo@am__quote@
@@ -1739,6 +1826,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_8_r16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_8_r4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_8_r8.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_8_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc0_8_s4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_16_i1.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_16_i16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_16_i2.Plo@am__quote@
@@ -1748,6 +1837,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_16_r16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_16_r4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_16_r8.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_16_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_16_s4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_4_i1.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_4_i16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_4_i2.Plo@am__quote@
@@ -1757,6 +1848,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_4_r16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_4_r4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_4_r8.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_4_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_4_s4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_8_i1.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_8_i16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_8_i2.Plo@am__quote@
@@ -1766,6 +1859,14 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_8_r16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_8_r4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_8_r8.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_8_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc1_8_s4.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc2_16_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc2_16_s4.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc2_4_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc2_4_s4.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc2_8_s1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minloc2_8_s4.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minval_i1.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minval_i16.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/minval_i2.Plo@am__quote@
@@ -5259,6 +5360,258 @@ cshift1_16_c16.lo: $(srcdir)/generated/cshift1_16_c16.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cshift1_16_c16.lo `test -f '$(srcdir)/generated/cshift1_16_c16.c' || echo '$(srcdir)/'`$(srcdir)/generated/cshift1_16_c16.c
 
+maxloc0_4_s1.lo: $(srcdir)/generated/maxloc0_4_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc0_4_s1.lo -MD -MP -MF $(DEPDIR)/maxloc0_4_s1.Tpo -c -o maxloc0_4_s1.lo `test -f '$(srcdir)/generated/maxloc0_4_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc0_4_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc0_4_s1.Tpo $(DEPDIR)/maxloc0_4_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc0_4_s1.c' object='maxloc0_4_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc0_4_s1.lo `test -f '$(srcdir)/generated/maxloc0_4_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc0_4_s1.c
+
+maxloc0_4_s4.lo: $(srcdir)/generated/maxloc0_4_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc0_4_s4.lo -MD -MP -MF $(DEPDIR)/maxloc0_4_s4.Tpo -c -o maxloc0_4_s4.lo `test -f '$(srcdir)/generated/maxloc0_4_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc0_4_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc0_4_s4.Tpo $(DEPDIR)/maxloc0_4_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc0_4_s4.c' object='maxloc0_4_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc0_4_s4.lo `test -f '$(srcdir)/generated/maxloc0_4_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc0_4_s4.c
+
+maxloc0_8_s1.lo: $(srcdir)/generated/maxloc0_8_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc0_8_s1.lo -MD -MP -MF $(DEPDIR)/maxloc0_8_s1.Tpo -c -o maxloc0_8_s1.lo `test -f '$(srcdir)/generated/maxloc0_8_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc0_8_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc0_8_s1.Tpo $(DEPDIR)/maxloc0_8_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc0_8_s1.c' object='maxloc0_8_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc0_8_s1.lo `test -f '$(srcdir)/generated/maxloc0_8_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc0_8_s1.c
+
+maxloc0_8_s4.lo: $(srcdir)/generated/maxloc0_8_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc0_8_s4.lo -MD -MP -MF $(DEPDIR)/maxloc0_8_s4.Tpo -c -o maxloc0_8_s4.lo `test -f '$(srcdir)/generated/maxloc0_8_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc0_8_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc0_8_s4.Tpo $(DEPDIR)/maxloc0_8_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc0_8_s4.c' object='maxloc0_8_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc0_8_s4.lo `test -f '$(srcdir)/generated/maxloc0_8_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc0_8_s4.c
+
+maxloc0_16_s1.lo: $(srcdir)/generated/maxloc0_16_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc0_16_s1.lo -MD -MP -MF $(DEPDIR)/maxloc0_16_s1.Tpo -c -o maxloc0_16_s1.lo `test -f '$(srcdir)/generated/maxloc0_16_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc0_16_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc0_16_s1.Tpo $(DEPDIR)/maxloc0_16_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc0_16_s1.c' object='maxloc0_16_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc0_16_s1.lo `test -f '$(srcdir)/generated/maxloc0_16_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc0_16_s1.c
+
+maxloc0_16_s4.lo: $(srcdir)/generated/maxloc0_16_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc0_16_s4.lo -MD -MP -MF $(DEPDIR)/maxloc0_16_s4.Tpo -c -o maxloc0_16_s4.lo `test -f '$(srcdir)/generated/maxloc0_16_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc0_16_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc0_16_s4.Tpo $(DEPDIR)/maxloc0_16_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc0_16_s4.c' object='maxloc0_16_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc0_16_s4.lo `test -f '$(srcdir)/generated/maxloc0_16_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc0_16_s4.c
+
+minloc0_4_s1.lo: $(srcdir)/generated/minloc0_4_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc0_4_s1.lo -MD -MP -MF $(DEPDIR)/minloc0_4_s1.Tpo -c -o minloc0_4_s1.lo `test -f '$(srcdir)/generated/minloc0_4_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc0_4_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc0_4_s1.Tpo $(DEPDIR)/minloc0_4_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc0_4_s1.c' object='minloc0_4_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc0_4_s1.lo `test -f '$(srcdir)/generated/minloc0_4_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc0_4_s1.c
+
+minloc0_4_s4.lo: $(srcdir)/generated/minloc0_4_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc0_4_s4.lo -MD -MP -MF $(DEPDIR)/minloc0_4_s4.Tpo -c -o minloc0_4_s4.lo `test -f '$(srcdir)/generated/minloc0_4_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc0_4_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc0_4_s4.Tpo $(DEPDIR)/minloc0_4_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc0_4_s4.c' object='minloc0_4_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc0_4_s4.lo `test -f '$(srcdir)/generated/minloc0_4_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc0_4_s4.c
+
+minloc0_8_s1.lo: $(srcdir)/generated/minloc0_8_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc0_8_s1.lo -MD -MP -MF $(DEPDIR)/minloc0_8_s1.Tpo -c -o minloc0_8_s1.lo `test -f '$(srcdir)/generated/minloc0_8_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc0_8_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc0_8_s1.Tpo $(DEPDIR)/minloc0_8_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc0_8_s1.c' object='minloc0_8_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc0_8_s1.lo `test -f '$(srcdir)/generated/minloc0_8_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc0_8_s1.c
+
+minloc0_8_s4.lo: $(srcdir)/generated/minloc0_8_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc0_8_s4.lo -MD -MP -MF $(DEPDIR)/minloc0_8_s4.Tpo -c -o minloc0_8_s4.lo `test -f '$(srcdir)/generated/minloc0_8_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc0_8_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc0_8_s4.Tpo $(DEPDIR)/minloc0_8_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc0_8_s4.c' object='minloc0_8_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc0_8_s4.lo `test -f '$(srcdir)/generated/minloc0_8_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc0_8_s4.c
+
+minloc0_16_s1.lo: $(srcdir)/generated/minloc0_16_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc0_16_s1.lo -MD -MP -MF $(DEPDIR)/minloc0_16_s1.Tpo -c -o minloc0_16_s1.lo `test -f '$(srcdir)/generated/minloc0_16_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc0_16_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc0_16_s1.Tpo $(DEPDIR)/minloc0_16_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc0_16_s1.c' object='minloc0_16_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc0_16_s1.lo `test -f '$(srcdir)/generated/minloc0_16_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc0_16_s1.c
+
+minloc0_16_s4.lo: $(srcdir)/generated/minloc0_16_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc0_16_s4.lo -MD -MP -MF $(DEPDIR)/minloc0_16_s4.Tpo -c -o minloc0_16_s4.lo `test -f '$(srcdir)/generated/minloc0_16_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc0_16_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc0_16_s4.Tpo $(DEPDIR)/minloc0_16_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc0_16_s4.c' object='minloc0_16_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc0_16_s4.lo `test -f '$(srcdir)/generated/minloc0_16_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc0_16_s4.c
+
+maxloc1_4_s1.lo: $(srcdir)/generated/maxloc1_4_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc1_4_s1.lo -MD -MP -MF $(DEPDIR)/maxloc1_4_s1.Tpo -c -o maxloc1_4_s1.lo `test -f '$(srcdir)/generated/maxloc1_4_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc1_4_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc1_4_s1.Tpo $(DEPDIR)/maxloc1_4_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc1_4_s1.c' object='maxloc1_4_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc1_4_s1.lo `test -f '$(srcdir)/generated/maxloc1_4_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc1_4_s1.c
+
+maxloc1_4_s4.lo: $(srcdir)/generated/maxloc1_4_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc1_4_s4.lo -MD -MP -MF $(DEPDIR)/maxloc1_4_s4.Tpo -c -o maxloc1_4_s4.lo `test -f '$(srcdir)/generated/maxloc1_4_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc1_4_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc1_4_s4.Tpo $(DEPDIR)/maxloc1_4_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc1_4_s4.c' object='maxloc1_4_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc1_4_s4.lo `test -f '$(srcdir)/generated/maxloc1_4_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc1_4_s4.c
+
+maxloc1_8_s1.lo: $(srcdir)/generated/maxloc1_8_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc1_8_s1.lo -MD -MP -MF $(DEPDIR)/maxloc1_8_s1.Tpo -c -o maxloc1_8_s1.lo `test -f '$(srcdir)/generated/maxloc1_8_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc1_8_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc1_8_s1.Tpo $(DEPDIR)/maxloc1_8_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc1_8_s1.c' object='maxloc1_8_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc1_8_s1.lo `test -f '$(srcdir)/generated/maxloc1_8_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc1_8_s1.c
+
+maxloc1_8_s4.lo: $(srcdir)/generated/maxloc1_8_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc1_8_s4.lo -MD -MP -MF $(DEPDIR)/maxloc1_8_s4.Tpo -c -o maxloc1_8_s4.lo `test -f '$(srcdir)/generated/maxloc1_8_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc1_8_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc1_8_s4.Tpo $(DEPDIR)/maxloc1_8_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc1_8_s4.c' object='maxloc1_8_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc1_8_s4.lo `test -f '$(srcdir)/generated/maxloc1_8_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc1_8_s4.c
+
+maxloc1_16_s1.lo: $(srcdir)/generated/maxloc1_16_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc1_16_s1.lo -MD -MP -MF $(DEPDIR)/maxloc1_16_s1.Tpo -c -o maxloc1_16_s1.lo `test -f '$(srcdir)/generated/maxloc1_16_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc1_16_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc1_16_s1.Tpo $(DEPDIR)/maxloc1_16_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc1_16_s1.c' object='maxloc1_16_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc1_16_s1.lo `test -f '$(srcdir)/generated/maxloc1_16_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc1_16_s1.c
+
+maxloc1_16_s4.lo: $(srcdir)/generated/maxloc1_16_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc1_16_s4.lo -MD -MP -MF $(DEPDIR)/maxloc1_16_s4.Tpo -c -o maxloc1_16_s4.lo `test -f '$(srcdir)/generated/maxloc1_16_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc1_16_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc1_16_s4.Tpo $(DEPDIR)/maxloc1_16_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc1_16_s4.c' object='maxloc1_16_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc1_16_s4.lo `test -f '$(srcdir)/generated/maxloc1_16_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc1_16_s4.c
+
+minloc1_4_s1.lo: $(srcdir)/generated/minloc1_4_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc1_4_s1.lo -MD -MP -MF $(DEPDIR)/minloc1_4_s1.Tpo -c -o minloc1_4_s1.lo `test -f '$(srcdir)/generated/minloc1_4_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc1_4_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc1_4_s1.Tpo $(DEPDIR)/minloc1_4_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc1_4_s1.c' object='minloc1_4_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc1_4_s1.lo `test -f '$(srcdir)/generated/minloc1_4_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc1_4_s1.c
+
+minloc1_4_s4.lo: $(srcdir)/generated/minloc1_4_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc1_4_s4.lo -MD -MP -MF $(DEPDIR)/minloc1_4_s4.Tpo -c -o minloc1_4_s4.lo `test -f '$(srcdir)/generated/minloc1_4_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc1_4_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc1_4_s4.Tpo $(DEPDIR)/minloc1_4_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc1_4_s4.c' object='minloc1_4_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc1_4_s4.lo `test -f '$(srcdir)/generated/minloc1_4_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc1_4_s4.c
+
+minloc1_8_s1.lo: $(srcdir)/generated/minloc1_8_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc1_8_s1.lo -MD -MP -MF $(DEPDIR)/minloc1_8_s1.Tpo -c -o minloc1_8_s1.lo `test -f '$(srcdir)/generated/minloc1_8_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc1_8_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc1_8_s1.Tpo $(DEPDIR)/minloc1_8_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc1_8_s1.c' object='minloc1_8_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc1_8_s1.lo `test -f '$(srcdir)/generated/minloc1_8_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc1_8_s1.c
+
+minloc1_8_s4.lo: $(srcdir)/generated/minloc1_8_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc1_8_s4.lo -MD -MP -MF $(DEPDIR)/minloc1_8_s4.Tpo -c -o minloc1_8_s4.lo `test -f '$(srcdir)/generated/minloc1_8_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc1_8_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc1_8_s4.Tpo $(DEPDIR)/minloc1_8_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc1_8_s4.c' object='minloc1_8_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc1_8_s4.lo `test -f '$(srcdir)/generated/minloc1_8_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc1_8_s4.c
+
+minloc1_16_s1.lo: $(srcdir)/generated/minloc1_16_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc1_16_s1.lo -MD -MP -MF $(DEPDIR)/minloc1_16_s1.Tpo -c -o minloc1_16_s1.lo `test -f '$(srcdir)/generated/minloc1_16_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc1_16_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc1_16_s1.Tpo $(DEPDIR)/minloc1_16_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc1_16_s1.c' object='minloc1_16_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc1_16_s1.lo `test -f '$(srcdir)/generated/minloc1_16_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc1_16_s1.c
+
+minloc1_16_s4.lo: $(srcdir)/generated/minloc1_16_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc1_16_s4.lo -MD -MP -MF $(DEPDIR)/minloc1_16_s4.Tpo -c -o minloc1_16_s4.lo `test -f '$(srcdir)/generated/minloc1_16_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc1_16_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc1_16_s4.Tpo $(DEPDIR)/minloc1_16_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc1_16_s4.c' object='minloc1_16_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc1_16_s4.lo `test -f '$(srcdir)/generated/minloc1_16_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc1_16_s4.c
+
+maxloc2_4_s1.lo: $(srcdir)/generated/maxloc2_4_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc2_4_s1.lo -MD -MP -MF $(DEPDIR)/maxloc2_4_s1.Tpo -c -o maxloc2_4_s1.lo `test -f '$(srcdir)/generated/maxloc2_4_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc2_4_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc2_4_s1.Tpo $(DEPDIR)/maxloc2_4_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc2_4_s1.c' object='maxloc2_4_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc2_4_s1.lo `test -f '$(srcdir)/generated/maxloc2_4_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc2_4_s1.c
+
+maxloc2_4_s4.lo: $(srcdir)/generated/maxloc2_4_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc2_4_s4.lo -MD -MP -MF $(DEPDIR)/maxloc2_4_s4.Tpo -c -o maxloc2_4_s4.lo `test -f '$(srcdir)/generated/maxloc2_4_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc2_4_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc2_4_s4.Tpo $(DEPDIR)/maxloc2_4_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc2_4_s4.c' object='maxloc2_4_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc2_4_s4.lo `test -f '$(srcdir)/generated/maxloc2_4_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc2_4_s4.c
+
+maxloc2_8_s1.lo: $(srcdir)/generated/maxloc2_8_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc2_8_s1.lo -MD -MP -MF $(DEPDIR)/maxloc2_8_s1.Tpo -c -o maxloc2_8_s1.lo `test -f '$(srcdir)/generated/maxloc2_8_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc2_8_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc2_8_s1.Tpo $(DEPDIR)/maxloc2_8_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc2_8_s1.c' object='maxloc2_8_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc2_8_s1.lo `test -f '$(srcdir)/generated/maxloc2_8_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc2_8_s1.c
+
+maxloc2_8_s4.lo: $(srcdir)/generated/maxloc2_8_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc2_8_s4.lo -MD -MP -MF $(DEPDIR)/maxloc2_8_s4.Tpo -c -o maxloc2_8_s4.lo `test -f '$(srcdir)/generated/maxloc2_8_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc2_8_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc2_8_s4.Tpo $(DEPDIR)/maxloc2_8_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc2_8_s4.c' object='maxloc2_8_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc2_8_s4.lo `test -f '$(srcdir)/generated/maxloc2_8_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc2_8_s4.c
+
+maxloc2_16_s1.lo: $(srcdir)/generated/maxloc2_16_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc2_16_s1.lo -MD -MP -MF $(DEPDIR)/maxloc2_16_s1.Tpo -c -o maxloc2_16_s1.lo `test -f '$(srcdir)/generated/maxloc2_16_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc2_16_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc2_16_s1.Tpo $(DEPDIR)/maxloc2_16_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc2_16_s1.c' object='maxloc2_16_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc2_16_s1.lo `test -f '$(srcdir)/generated/maxloc2_16_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc2_16_s1.c
+
+maxloc2_16_s4.lo: $(srcdir)/generated/maxloc2_16_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT maxloc2_16_s4.lo -MD -MP -MF $(DEPDIR)/maxloc2_16_s4.Tpo -c -o maxloc2_16_s4.lo `test -f '$(srcdir)/generated/maxloc2_16_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc2_16_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/maxloc2_16_s4.Tpo $(DEPDIR)/maxloc2_16_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/maxloc2_16_s4.c' object='maxloc2_16_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o maxloc2_16_s4.lo `test -f '$(srcdir)/generated/maxloc2_16_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/maxloc2_16_s4.c
+
+minloc2_4_s1.lo: $(srcdir)/generated/minloc2_4_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc2_4_s1.lo -MD -MP -MF $(DEPDIR)/minloc2_4_s1.Tpo -c -o minloc2_4_s1.lo `test -f '$(srcdir)/generated/minloc2_4_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc2_4_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc2_4_s1.Tpo $(DEPDIR)/minloc2_4_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc2_4_s1.c' object='minloc2_4_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc2_4_s1.lo `test -f '$(srcdir)/generated/minloc2_4_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc2_4_s1.c
+
+minloc2_4_s4.lo: $(srcdir)/generated/minloc2_4_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc2_4_s4.lo -MD -MP -MF $(DEPDIR)/minloc2_4_s4.Tpo -c -o minloc2_4_s4.lo `test -f '$(srcdir)/generated/minloc2_4_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc2_4_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc2_4_s4.Tpo $(DEPDIR)/minloc2_4_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc2_4_s4.c' object='minloc2_4_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc2_4_s4.lo `test -f '$(srcdir)/generated/minloc2_4_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc2_4_s4.c
+
+minloc2_8_s1.lo: $(srcdir)/generated/minloc2_8_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc2_8_s1.lo -MD -MP -MF $(DEPDIR)/minloc2_8_s1.Tpo -c -o minloc2_8_s1.lo `test -f '$(srcdir)/generated/minloc2_8_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc2_8_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc2_8_s1.Tpo $(DEPDIR)/minloc2_8_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc2_8_s1.c' object='minloc2_8_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc2_8_s1.lo `test -f '$(srcdir)/generated/minloc2_8_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc2_8_s1.c
+
+minloc2_8_s4.lo: $(srcdir)/generated/minloc2_8_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc2_8_s4.lo -MD -MP -MF $(DEPDIR)/minloc2_8_s4.Tpo -c -o minloc2_8_s4.lo `test -f '$(srcdir)/generated/minloc2_8_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc2_8_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc2_8_s4.Tpo $(DEPDIR)/minloc2_8_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc2_8_s4.c' object='minloc2_8_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc2_8_s4.lo `test -f '$(srcdir)/generated/minloc2_8_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc2_8_s4.c
+
+minloc2_16_s1.lo: $(srcdir)/generated/minloc2_16_s1.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc2_16_s1.lo -MD -MP -MF $(DEPDIR)/minloc2_16_s1.Tpo -c -o minloc2_16_s1.lo `test -f '$(srcdir)/generated/minloc2_16_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc2_16_s1.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc2_16_s1.Tpo $(DEPDIR)/minloc2_16_s1.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc2_16_s1.c' object='minloc2_16_s1.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc2_16_s1.lo `test -f '$(srcdir)/generated/minloc2_16_s1.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc2_16_s1.c
+
+minloc2_16_s4.lo: $(srcdir)/generated/minloc2_16_s4.c
+@am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT minloc2_16_s4.lo -MD -MP -MF $(DEPDIR)/minloc2_16_s4.Tpo -c -o minloc2_16_s4.lo `test -f '$(srcdir)/generated/minloc2_16_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc2_16_s4.c
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/minloc2_16_s4.Tpo $(DEPDIR)/minloc2_16_s4.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$(srcdir)/generated/minloc2_16_s4.c' object='minloc2_16_s4.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o minloc2_16_s4.lo `test -f '$(srcdir)/generated/minloc2_16_s4.c' || echo '$(srcdir)/'`$(srcdir)/generated/minloc2_16_s4.c
+
 size_from_kind.lo: io/size_from_kind.c
 @am__fastdepCC_TRUE@   $(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT size_from_kind.lo -MD -MP -MF $(DEPDIR)/size_from_kind.Tpo -c -o size_from_kind.lo `test -f 'io/size_from_kind.c' || echo '$(srcdir)/'`io/size_from_kind.c
 @am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/size_from_kind.Tpo $(DEPDIR)/size_from_kind.Plo
@@ -6139,18 +6492,36 @@ fpu-target.inc: fpu-target.h $(srcdir)/libgfortran.h
 @MAINTAINER_MODE_TRUE@$(i_maxloc0_c): m4/maxloc0.m4 $(I_M4_DEPS0)
 @MAINTAINER_MODE_TRUE@ $(M4) -Dfile=$@ -I$(srcdir)/m4 maxloc0.m4 > $@
 
+@MAINTAINER_MODE_TRUE@$(i_maxloc0s_c) : m4/maxloc0s.m4 $(I_M4_DEPS3)
+@MAINTAINER_MODE_TRUE@ $(M4) -Dfile=$@ -I$(srcdir)/m4 maxloc0s.m4 > $@
+
 @MAINTAINER_MODE_TRUE@$(i_maxloc1_c): m4/maxloc1.m4 $(I_M4_DEPS1)
 @MAINTAINER_MODE_TRUE@ $(M4) -Dfile=$@ -I$(srcdir)/m4 maxloc1.m4 > $@
 
+@MAINTAINER_MODE_TRUE@$(i_maxloc1s_c): m4/maxloc1s.m4 $(I_M4_DEPS4)
+@MAINTAINER_MODE_TRUE@ $(M4) -Dfile=$@ -I$(srcdir)/m4 maxloc1s.m4 > $@
+
+@MAINTAINER_MODE_TRUE@$(i_maxloc2s_c): m4/maxloc2s.m4 $(I_M4_DEPS)
+@MAINTAINER_MODE_TRUE@ $(M4) -Dfile=$@ -I$(srcdir)/m4 maxloc2s.m4 > $@
+
 @MAINTAINER_MODE_TRUE@$(i_maxval_c): m4/maxval.m4 $(I_M4_DEPS1)
 @MAINTAINER_MODE_TRUE@ $(M4) -Dfile=$@ -I$(srcdir)/m4 maxval.m4 > $@
 
 @MAINTAINER_MODE_TRUE@$(i_minloc0_c): m4/minloc0.m4 $(I_M4_DEPS0)
 @MAINTAINER_MODE_TRUE@ $(M4) -Dfile=$@ -I$(srcdir)/m4 minloc0.m4 > $@
 
+@MAINTAINER_MODE_TRUE@$(i_minloc0s_c) : m4/minloc0s.m4 $(I_M4_DEPS3)
+@MAINTAINER_MODE_TRUE@ $(M4) -Dfile=$@ -I$(srcdir)/m4 minloc0s.m4 > $@
+
 @MAINTAINER_MODE_TRUE@$(i_minloc1_c): m4/minloc1.m4 $(I_M4_DEPS1)
 @MAINTAINER_MODE_TRUE@ $(M4) -Dfile=$@ -I$(srcdir)/m4 minloc1.m4 > $@
 
+@MAINTAINER_MODE_TRUE@$(i_minloc1s_c): m4/minloc1s.m4 $(I_M4_DEPS4)
+@MAINTAINER_MODE_TRUE@ $(M4) -Dfile=$@ -I$(srcdir)/m4 minloc1s.m4 > $@
+
+@MAINTAINER_MODE_TRUE@$(i_minloc2s_c): m4/minloc2s.m4 $(I_M4_DEPS)
+@MAINTAINER_MODE_TRUE@ $(M4) -Dfile=$@ -I$(srcdir)/m4 minloc2s.m4 > $@
+
 @MAINTAINER_MODE_TRUE@$(i_minval_c): m4/minval.m4 $(I_M4_DEPS1)
 @MAINTAINER_MODE_TRUE@ $(M4) -Dfile=$@ -I$(srcdir)/m4 minval.m4 > $@
 
diff --git a/libgfortran/generated/maxloc0_16_s1.c b/libgfortran/generated/maxloc0_16_s1.c
new file mode 100644 (file)
index 0000000..949fb20
--- /dev/null
@@ -0,0 +1,327 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_16)
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+
+}
+
+extern void maxloc0_16_s1 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, gfc_charlen_type len);
+export_proto(maxloc0_16_s1);
+
+void
+maxloc0_16_s1 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  const GFC_INTEGER_1 *base;
+  GFC_INTEGER_16 * restrict dest;
+  index_type rank;
+  index_type n;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_16));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                               "MAXLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 1;
+  {
+
+  const GFC_INTEGER_1 *maxval;
+   maxval = base;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (compare_fcn (base, maxval, len) > 0)
+    {
+      maxval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void mmaxloc0_16_s1 (gfc_array_i16 * const restrict, 
+       gfc_array_s1 * const restrict, gfc_array_l1 * const restrict, gfc_charlen_type len);
+export_proto(mmaxloc0_16_s1);
+
+void
+mmaxloc0_16_s1 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s1 * const restrict array,
+       gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type mstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  GFC_INTEGER_16 *dest;
+  const GFC_INTEGER_1 *base;
+  GFC_LOGICAL_1 *mbase;
+  int rank;
+  index_type n;
+  int mask_kind;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_16));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       {
+
+         bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                                 "MAXLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                                 "MASK argument", "MAXLOC");
+       }
+    }
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+
+  mbase = mask->base_addr;
+
+  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");
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 0;
+  {
+
+  const GFC_INTEGER_1 *maxval;
+
+  maxval = NULL;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (*mbase && (maxval == NULL || compare_fcn (base, maxval, len) > 0))
+    {
+      maxval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+         mbase += mstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void smaxloc0_16_s1 (gfc_array_i16 * const restrict, 
+       gfc_array_s1 * const restrict, GFC_LOGICAL_4 *, gfc_charlen_type len);
+export_proto(smaxloc0_16_s1);
+
+void
+smaxloc0_16_s1 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s1 * const restrict array,
+       GFC_LOGICAL_4 * mask, gfc_charlen_type len)
+{
+  index_type rank;
+  index_type dstride;
+  index_type n;
+  GFC_INTEGER_16 *dest;
+
+  if (*mask)
+    {
+      maxloc0_16_s1 (retarray, array, len);
+      return;
+    }
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_16));
+    }
+  else if (unlikely (compile_options.bounds_check))
+    {
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                              "MAXLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n<rank; n++)
+    dest[n * dstride] = 0 ;
+}
+#endif
diff --git a/libgfortran/generated/maxloc0_16_s4.c b/libgfortran/generated/maxloc0_16_s4.c
new file mode 100644 (file)
index 0000000..1ac7a9d
--- /dev/null
@@ -0,0 +1,327 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_16)
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+
+}
+
+extern void maxloc0_16_s4 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, gfc_charlen_type len);
+export_proto(maxloc0_16_s4);
+
+void
+maxloc0_16_s4 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  const GFC_INTEGER_4 *base;
+  GFC_INTEGER_16 * restrict dest;
+  index_type rank;
+  index_type n;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_16));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                               "MAXLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 1;
+  {
+
+  const GFC_INTEGER_4 *maxval;
+   maxval = base;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (compare_fcn (base, maxval, len) > 0)
+    {
+      maxval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void mmaxloc0_16_s4 (gfc_array_i16 * const restrict, 
+       gfc_array_s4 * const restrict, gfc_array_l1 * const restrict, gfc_charlen_type len);
+export_proto(mmaxloc0_16_s4);
+
+void
+mmaxloc0_16_s4 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s4 * const restrict array,
+       gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type mstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  GFC_INTEGER_16 *dest;
+  const GFC_INTEGER_4 *base;
+  GFC_LOGICAL_1 *mbase;
+  int rank;
+  index_type n;
+  int mask_kind;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_16));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       {
+
+         bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                                 "MAXLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                                 "MASK argument", "MAXLOC");
+       }
+    }
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+
+  mbase = mask->base_addr;
+
+  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");
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 0;
+  {
+
+  const GFC_INTEGER_4 *maxval;
+
+  maxval = NULL;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (*mbase && (maxval == NULL || compare_fcn (base, maxval, len) > 0))
+    {
+      maxval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+         mbase += mstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void smaxloc0_16_s4 (gfc_array_i16 * const restrict, 
+       gfc_array_s4 * const restrict, GFC_LOGICAL_4 *, gfc_charlen_type len);
+export_proto(smaxloc0_16_s4);
+
+void
+smaxloc0_16_s4 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s4 * const restrict array,
+       GFC_LOGICAL_4 * mask, gfc_charlen_type len)
+{
+  index_type rank;
+  index_type dstride;
+  index_type n;
+  GFC_INTEGER_16 *dest;
+
+  if (*mask)
+    {
+      maxloc0_16_s4 (retarray, array, len);
+      return;
+    }
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_16));
+    }
+  else if (unlikely (compile_options.bounds_check))
+    {
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                              "MAXLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n<rank; n++)
+    dest[n * dstride] = 0 ;
+}
+#endif
diff --git a/libgfortran/generated/maxloc0_4_s1.c b/libgfortran/generated/maxloc0_4_s1.c
new file mode 100644 (file)
index 0000000..6d897d8
--- /dev/null
@@ -0,0 +1,327 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_4)
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+
+}
+
+extern void maxloc0_4_s1 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, gfc_charlen_type len);
+export_proto(maxloc0_4_s1);
+
+void
+maxloc0_4_s1 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  const GFC_INTEGER_1 *base;
+  GFC_INTEGER_4 * restrict dest;
+  index_type rank;
+  index_type n;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_4));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                               "MAXLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 1;
+  {
+
+  const GFC_INTEGER_1 *maxval;
+   maxval = base;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (compare_fcn (base, maxval, len) > 0)
+    {
+      maxval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void mmaxloc0_4_s1 (gfc_array_i4 * const restrict, 
+       gfc_array_s1 * const restrict, gfc_array_l1 * const restrict, gfc_charlen_type len);
+export_proto(mmaxloc0_4_s1);
+
+void
+mmaxloc0_4_s1 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s1 * const restrict array,
+       gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type mstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  GFC_INTEGER_4 *dest;
+  const GFC_INTEGER_1 *base;
+  GFC_LOGICAL_1 *mbase;
+  int rank;
+  index_type n;
+  int mask_kind;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_4));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       {
+
+         bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                                 "MAXLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                                 "MASK argument", "MAXLOC");
+       }
+    }
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+
+  mbase = mask->base_addr;
+
+  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");
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 0;
+  {
+
+  const GFC_INTEGER_1 *maxval;
+
+  maxval = NULL;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (*mbase && (maxval == NULL || compare_fcn (base, maxval, len) > 0))
+    {
+      maxval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+         mbase += mstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void smaxloc0_4_s1 (gfc_array_i4 * const restrict, 
+       gfc_array_s1 * const restrict, GFC_LOGICAL_4 *, gfc_charlen_type len);
+export_proto(smaxloc0_4_s1);
+
+void
+smaxloc0_4_s1 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s1 * const restrict array,
+       GFC_LOGICAL_4 * mask, gfc_charlen_type len)
+{
+  index_type rank;
+  index_type dstride;
+  index_type n;
+  GFC_INTEGER_4 *dest;
+
+  if (*mask)
+    {
+      maxloc0_4_s1 (retarray, array, len);
+      return;
+    }
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_4));
+    }
+  else if (unlikely (compile_options.bounds_check))
+    {
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                              "MAXLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n<rank; n++)
+    dest[n * dstride] = 0 ;
+}
+#endif
diff --git a/libgfortran/generated/maxloc0_4_s4.c b/libgfortran/generated/maxloc0_4_s4.c
new file mode 100644 (file)
index 0000000..3a8e603
--- /dev/null
@@ -0,0 +1,327 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_4)
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+
+}
+
+extern void maxloc0_4_s4 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, gfc_charlen_type len);
+export_proto(maxloc0_4_s4);
+
+void
+maxloc0_4_s4 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  const GFC_INTEGER_4 *base;
+  GFC_INTEGER_4 * restrict dest;
+  index_type rank;
+  index_type n;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_4));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                               "MAXLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 1;
+  {
+
+  const GFC_INTEGER_4 *maxval;
+   maxval = base;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (compare_fcn (base, maxval, len) > 0)
+    {
+      maxval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void mmaxloc0_4_s4 (gfc_array_i4 * const restrict, 
+       gfc_array_s4 * const restrict, gfc_array_l1 * const restrict, gfc_charlen_type len);
+export_proto(mmaxloc0_4_s4);
+
+void
+mmaxloc0_4_s4 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s4 * const restrict array,
+       gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type mstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  GFC_INTEGER_4 *dest;
+  const GFC_INTEGER_4 *base;
+  GFC_LOGICAL_1 *mbase;
+  int rank;
+  index_type n;
+  int mask_kind;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_4));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       {
+
+         bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                                 "MAXLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                                 "MASK argument", "MAXLOC");
+       }
+    }
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+
+  mbase = mask->base_addr;
+
+  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");
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 0;
+  {
+
+  const GFC_INTEGER_4 *maxval;
+
+  maxval = NULL;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (*mbase && (maxval == NULL || compare_fcn (base, maxval, len) > 0))
+    {
+      maxval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+         mbase += mstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void smaxloc0_4_s4 (gfc_array_i4 * const restrict, 
+       gfc_array_s4 * const restrict, GFC_LOGICAL_4 *, gfc_charlen_type len);
+export_proto(smaxloc0_4_s4);
+
+void
+smaxloc0_4_s4 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s4 * const restrict array,
+       GFC_LOGICAL_4 * mask, gfc_charlen_type len)
+{
+  index_type rank;
+  index_type dstride;
+  index_type n;
+  GFC_INTEGER_4 *dest;
+
+  if (*mask)
+    {
+      maxloc0_4_s4 (retarray, array, len);
+      return;
+    }
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_4));
+    }
+  else if (unlikely (compile_options.bounds_check))
+    {
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                              "MAXLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n<rank; n++)
+    dest[n * dstride] = 0 ;
+}
+#endif
diff --git a/libgfortran/generated/maxloc0_8_s1.c b/libgfortran/generated/maxloc0_8_s1.c
new file mode 100644 (file)
index 0000000..f019736
--- /dev/null
@@ -0,0 +1,327 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_8)
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+
+}
+
+extern void maxloc0_8_s1 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, gfc_charlen_type len);
+export_proto(maxloc0_8_s1);
+
+void
+maxloc0_8_s1 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  const GFC_INTEGER_1 *base;
+  GFC_INTEGER_8 * restrict dest;
+  index_type rank;
+  index_type n;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                               "MAXLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 1;
+  {
+
+  const GFC_INTEGER_1 *maxval;
+   maxval = base;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (compare_fcn (base, maxval, len) > 0)
+    {
+      maxval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void mmaxloc0_8_s1 (gfc_array_i8 * const restrict, 
+       gfc_array_s1 * const restrict, gfc_array_l1 * const restrict, gfc_charlen_type len);
+export_proto(mmaxloc0_8_s1);
+
+void
+mmaxloc0_8_s1 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s1 * const restrict array,
+       gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type mstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  GFC_INTEGER_8 *dest;
+  const GFC_INTEGER_1 *base;
+  GFC_LOGICAL_1 *mbase;
+  int rank;
+  index_type n;
+  int mask_kind;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       {
+
+         bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                                 "MAXLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                                 "MASK argument", "MAXLOC");
+       }
+    }
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+
+  mbase = mask->base_addr;
+
+  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");
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 0;
+  {
+
+  const GFC_INTEGER_1 *maxval;
+
+  maxval = NULL;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (*mbase && (maxval == NULL || compare_fcn (base, maxval, len) > 0))
+    {
+      maxval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+         mbase += mstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void smaxloc0_8_s1 (gfc_array_i8 * const restrict, 
+       gfc_array_s1 * const restrict, GFC_LOGICAL_4 *, gfc_charlen_type len);
+export_proto(smaxloc0_8_s1);
+
+void
+smaxloc0_8_s1 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s1 * const restrict array,
+       GFC_LOGICAL_4 * mask, gfc_charlen_type len)
+{
+  index_type rank;
+  index_type dstride;
+  index_type n;
+  GFC_INTEGER_8 *dest;
+
+  if (*mask)
+    {
+      maxloc0_8_s1 (retarray, array, len);
+      return;
+    }
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
+    }
+  else if (unlikely (compile_options.bounds_check))
+    {
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                              "MAXLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n<rank; n++)
+    dest[n * dstride] = 0 ;
+}
+#endif
diff --git a/libgfortran/generated/maxloc0_8_s4.c b/libgfortran/generated/maxloc0_8_s4.c
new file mode 100644 (file)
index 0000000..524a621
--- /dev/null
@@ -0,0 +1,327 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_8)
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+
+}
+
+extern void maxloc0_8_s4 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, gfc_charlen_type len);
+export_proto(maxloc0_8_s4);
+
+void
+maxloc0_8_s4 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  const GFC_INTEGER_4 *base;
+  GFC_INTEGER_8 * restrict dest;
+  index_type rank;
+  index_type n;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                               "MAXLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 1;
+  {
+
+  const GFC_INTEGER_4 *maxval;
+   maxval = base;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (compare_fcn (base, maxval, len) > 0)
+    {
+      maxval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void mmaxloc0_8_s4 (gfc_array_i8 * const restrict, 
+       gfc_array_s4 * const restrict, gfc_array_l1 * const restrict, gfc_charlen_type len);
+export_proto(mmaxloc0_8_s4);
+
+void
+mmaxloc0_8_s4 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s4 * const restrict array,
+       gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type mstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  GFC_INTEGER_8 *dest;
+  const GFC_INTEGER_4 *base;
+  GFC_LOGICAL_1 *mbase;
+  int rank;
+  index_type n;
+  int mask_kind;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       {
+
+         bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                                 "MAXLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                                 "MASK argument", "MAXLOC");
+       }
+    }
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+
+  mbase = mask->base_addr;
+
+  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");
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 0;
+  {
+
+  const GFC_INTEGER_4 *maxval;
+
+  maxval = NULL;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (*mbase && (maxval == NULL || compare_fcn (base, maxval, len) > 0))
+    {
+      maxval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+         mbase += mstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void smaxloc0_8_s4 (gfc_array_i8 * const restrict, 
+       gfc_array_s4 * const restrict, GFC_LOGICAL_4 *, gfc_charlen_type len);
+export_proto(smaxloc0_8_s4);
+
+void
+smaxloc0_8_s4 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s4 * const restrict array,
+       GFC_LOGICAL_4 * mask, gfc_charlen_type len)
+{
+  index_type rank;
+  index_type dstride;
+  index_type n;
+  GFC_INTEGER_8 *dest;
+
+  if (*mask)
+    {
+      maxloc0_8_s4 (retarray, array, len);
+      return;
+    }
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
+    }
+  else if (unlikely (compile_options.bounds_check))
+    {
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                              "MAXLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n<rank; n++)
+    dest[n * dstride] = 0 ;
+}
+#endif
diff --git a/libgfortran/generated/maxloc1_16_s1.c b/libgfortran/generated/maxloc1_16_s1.c
new file mode 100644 (file)
index 0000000..b8efc0a
--- /dev/null
@@ -0,0 +1,552 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_16)
+
+#include <string.h>
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern void maxloc1_16_s1 (gfc_array_i16 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       gfc_charlen_type);
+export_proto(maxloc1_16_s1);
+
+void
+maxloc1_16_s1 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, gfc_charlen_type string_len)
+{
+  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 GFC_INTEGER_1 * restrict base;
+  GFC_INTEGER_16 * 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.  */
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+  dim = (*pdim) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len < 0)
+    len = 0;
+  delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
+
+      retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
+      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"
+                      " MAXLOC 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", "MAXLOC");
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  base = array->base_addr;
+  dest = retarray->base_addr;
+
+  continue_loop = 1;
+  while (continue_loop)
+    {
+      const GFC_INTEGER_1 * restrict src;
+      GFC_INTEGER_16 result;
+      src = base;
+      {
+
+       const GFC_INTEGER_1 *maxval;
+       maxval = base;
+       result = 1;
+       if (len <= 0)
+         *dest = 0;
+       else
+         {
+           for (n = 0; n < len; n++, src += delta)
+             {
+
+               if (compare_fcn (src, maxval, string_len) > 0)
+                 {
+                   maxval = src;
+                   result = (GFC_INTEGER_16)n + 1;
+                 }
+             }
+           
+           *dest = result;
+         }
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[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.  */
+         base -= sstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             continue_loop = 0;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void mmaxloc1_16_s1 (gfc_array_i16 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       gfc_array_l1 * const restrict, gfc_charlen_type);
+export_proto(mmaxloc1_16_s1);
+
+void
+mmaxloc1_16_s1 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, 
+       gfc_array_l1 * const restrict mask, gfc_charlen_type string_len)
+{
+  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];
+  GFC_INTEGER_16 * restrict dest;
+  const GFC_INTEGER_1 * restrict base;
+  const GFC_LOGICAL_1 * restrict mbase;
+  index_type rank;
+  index_type 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;
+
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len <= 0)
+    return;
+
+  mbase = mask->base_addr;
+
+  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) * string_len;
+  mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      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] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
+      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->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
+
+    }
+  else
+    {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in MAXLOC intrinsic");
+
+      if (unlikely (compile_options.bounds_check))
+       {
+         bounds_ifunction_return ((array_t *) retarray, extent,
+                                  "return value", "MAXLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                               "MASK argument", "MAXLOC");
+       }
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  dest = retarray->base_addr;
+  base = array->base_addr;
+
+  while (base)
+    {
+      const GFC_INTEGER_1 * restrict src;
+      const GFC_LOGICAL_1 * restrict msrc;
+      GFC_INTEGER_16 result;
+      src = base;
+      msrc = mbase;
+      {
+
+       const GFC_INTEGER_1 *maxval;
+       maxval = base;
+       result = 0;
+       for (n = 0; n < len; n++, src += delta, msrc += mdelta)
+         {
+
+               if (*msrc)
+                     {
+                       maxval = src;
+                       result = (GFC_INTEGER_16)n + 1;
+                       break;
+                     }
+           }
+           for (; n < len; n++, src += delta, msrc += mdelta)
+             {
+               if (*msrc && compare_fcn (src, maxval, string_len) > 0)
+                 {
+                   maxval = src;
+                   result = (GFC_INTEGER_16)n + 1;
+                 }
+             
+         }
+       *dest = result;
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[0];
+      mbase += mstride[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.  */
+         base -= sstride[n] * extent[n];
+         mbase -= mstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void smaxloc1_16_s1 (gfc_array_i16 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       GFC_LOGICAL_4 *, gfc_charlen_type);
+export_proto(smaxloc1_16_s1);
+
+void
+smaxloc1_16_s1 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, 
+       GFC_LOGICAL_4 * mask, gfc_charlen_type string_len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
+  index_type rank;
+  index_type n;
+  index_type dim;
+
+
+  if (*mask)
+    {
+      maxloc1_16_s1 (retarray, array, pdim, string_len);
+      return;
+    }
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  for (n = 0; n < dim; n++)
+    {
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      extent[n] =
+       GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
+    }
+  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 (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"
+                              " MAXLOC 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->base_addr;
+
+  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
diff --git a/libgfortran/generated/maxloc1_16_s4.c b/libgfortran/generated/maxloc1_16_s4.c
new file mode 100644 (file)
index 0000000..466d362
--- /dev/null
@@ -0,0 +1,552 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_16)
+
+#include <string.h>
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern void maxloc1_16_s4 (gfc_array_i16 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       gfc_charlen_type);
+export_proto(maxloc1_16_s4);
+
+void
+maxloc1_16_s4 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, gfc_charlen_type string_len)
+{
+  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 GFC_INTEGER_4 * restrict base;
+  GFC_INTEGER_16 * 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.  */
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+  dim = (*pdim) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len < 0)
+    len = 0;
+  delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
+
+      retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
+      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"
+                      " MAXLOC 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", "MAXLOC");
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  base = array->base_addr;
+  dest = retarray->base_addr;
+
+  continue_loop = 1;
+  while (continue_loop)
+    {
+      const GFC_INTEGER_4 * restrict src;
+      GFC_INTEGER_16 result;
+      src = base;
+      {
+
+       const GFC_INTEGER_4 *maxval;
+       maxval = base;
+       result = 1;
+       if (len <= 0)
+         *dest = 0;
+       else
+         {
+           for (n = 0; n < len; n++, src += delta)
+             {
+
+               if (compare_fcn (src, maxval, string_len) > 0)
+                 {
+                   maxval = src;
+                   result = (GFC_INTEGER_16)n + 1;
+                 }
+             }
+           
+           *dest = result;
+         }
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[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.  */
+         base -= sstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             continue_loop = 0;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void mmaxloc1_16_s4 (gfc_array_i16 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       gfc_array_l1 * const restrict, gfc_charlen_type);
+export_proto(mmaxloc1_16_s4);
+
+void
+mmaxloc1_16_s4 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, 
+       gfc_array_l1 * const restrict mask, gfc_charlen_type string_len)
+{
+  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];
+  GFC_INTEGER_16 * restrict dest;
+  const GFC_INTEGER_4 * restrict base;
+  const GFC_LOGICAL_1 * restrict mbase;
+  index_type rank;
+  index_type 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;
+
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len <= 0)
+    return;
+
+  mbase = mask->base_addr;
+
+  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) * string_len;
+  mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      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] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
+      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->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
+
+    }
+  else
+    {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in MAXLOC intrinsic");
+
+      if (unlikely (compile_options.bounds_check))
+       {
+         bounds_ifunction_return ((array_t *) retarray, extent,
+                                  "return value", "MAXLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                               "MASK argument", "MAXLOC");
+       }
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  dest = retarray->base_addr;
+  base = array->base_addr;
+
+  while (base)
+    {
+      const GFC_INTEGER_4 * restrict src;
+      const GFC_LOGICAL_1 * restrict msrc;
+      GFC_INTEGER_16 result;
+      src = base;
+      msrc = mbase;
+      {
+
+       const GFC_INTEGER_4 *maxval;
+       maxval = base;
+       result = 0;
+       for (n = 0; n < len; n++, src += delta, msrc += mdelta)
+         {
+
+               if (*msrc)
+                     {
+                       maxval = src;
+                       result = (GFC_INTEGER_16)n + 1;
+                       break;
+                     }
+           }
+           for (; n < len; n++, src += delta, msrc += mdelta)
+             {
+               if (*msrc && compare_fcn (src, maxval, string_len) > 0)
+                 {
+                   maxval = src;
+                   result = (GFC_INTEGER_16)n + 1;
+                 }
+             
+         }
+       *dest = result;
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[0];
+      mbase += mstride[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.  */
+         base -= sstride[n] * extent[n];
+         mbase -= mstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void smaxloc1_16_s4 (gfc_array_i16 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       GFC_LOGICAL_4 *, gfc_charlen_type);
+export_proto(smaxloc1_16_s4);
+
+void
+smaxloc1_16_s4 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, 
+       GFC_LOGICAL_4 * mask, gfc_charlen_type string_len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
+  index_type rank;
+  index_type n;
+  index_type dim;
+
+
+  if (*mask)
+    {
+      maxloc1_16_s4 (retarray, array, pdim, string_len);
+      return;
+    }
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  for (n = 0; n < dim; n++)
+    {
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      extent[n] =
+       GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
+    }
+  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 (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"
+                              " MAXLOC 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->base_addr;
+
+  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
diff --git a/libgfortran/generated/maxloc1_4_s1.c b/libgfortran/generated/maxloc1_4_s1.c
new file mode 100644 (file)
index 0000000..6116e5b
--- /dev/null
@@ -0,0 +1,552 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_4)
+
+#include <string.h>
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern void maxloc1_4_s1 (gfc_array_i4 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       gfc_charlen_type);
+export_proto(maxloc1_4_s1);
+
+void
+maxloc1_4_s1 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, gfc_charlen_type string_len)
+{
+  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 GFC_INTEGER_1 * restrict base;
+  GFC_INTEGER_4 * 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.  */
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+  dim = (*pdim) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len < 0)
+    len = 0;
+  delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
+
+      retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
+      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"
+                      " MAXLOC 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", "MAXLOC");
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  base = array->base_addr;
+  dest = retarray->base_addr;
+
+  continue_loop = 1;
+  while (continue_loop)
+    {
+      const GFC_INTEGER_1 * restrict src;
+      GFC_INTEGER_4 result;
+      src = base;
+      {
+
+       const GFC_INTEGER_1 *maxval;
+       maxval = base;
+       result = 1;
+       if (len <= 0)
+         *dest = 0;
+       else
+         {
+           for (n = 0; n < len; n++, src += delta)
+             {
+
+               if (compare_fcn (src, maxval, string_len) > 0)
+                 {
+                   maxval = src;
+                   result = (GFC_INTEGER_4)n + 1;
+                 }
+             }
+           
+           *dest = result;
+         }
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[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.  */
+         base -= sstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             continue_loop = 0;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void mmaxloc1_4_s1 (gfc_array_i4 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       gfc_array_l1 * const restrict, gfc_charlen_type);
+export_proto(mmaxloc1_4_s1);
+
+void
+mmaxloc1_4_s1 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, 
+       gfc_array_l1 * const restrict mask, gfc_charlen_type string_len)
+{
+  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];
+  GFC_INTEGER_4 * restrict dest;
+  const GFC_INTEGER_1 * restrict base;
+  const GFC_LOGICAL_1 * restrict mbase;
+  index_type rank;
+  index_type 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;
+
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len <= 0)
+    return;
+
+  mbase = mask->base_addr;
+
+  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) * string_len;
+  mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      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] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
+      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->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
+
+    }
+  else
+    {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in MAXLOC intrinsic");
+
+      if (unlikely (compile_options.bounds_check))
+       {
+         bounds_ifunction_return ((array_t *) retarray, extent,
+                                  "return value", "MAXLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                               "MASK argument", "MAXLOC");
+       }
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  dest = retarray->base_addr;
+  base = array->base_addr;
+
+  while (base)
+    {
+      const GFC_INTEGER_1 * restrict src;
+      const GFC_LOGICAL_1 * restrict msrc;
+      GFC_INTEGER_4 result;
+      src = base;
+      msrc = mbase;
+      {
+
+       const GFC_INTEGER_1 *maxval;
+       maxval = base;
+       result = 0;
+       for (n = 0; n < len; n++, src += delta, msrc += mdelta)
+         {
+
+               if (*msrc)
+                     {
+                       maxval = src;
+                       result = (GFC_INTEGER_4)n + 1;
+                       break;
+                     }
+           }
+           for (; n < len; n++, src += delta, msrc += mdelta)
+             {
+               if (*msrc && compare_fcn (src, maxval, string_len) > 0)
+                 {
+                   maxval = src;
+                   result = (GFC_INTEGER_4)n + 1;
+                 }
+             
+         }
+       *dest = result;
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[0];
+      mbase += mstride[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.  */
+         base -= sstride[n] * extent[n];
+         mbase -= mstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void smaxloc1_4_s1 (gfc_array_i4 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       GFC_LOGICAL_4 *, gfc_charlen_type);
+export_proto(smaxloc1_4_s1);
+
+void
+smaxloc1_4_s1 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, 
+       GFC_LOGICAL_4 * mask, gfc_charlen_type string_len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
+  index_type rank;
+  index_type n;
+  index_type dim;
+
+
+  if (*mask)
+    {
+      maxloc1_4_s1 (retarray, array, pdim, string_len);
+      return;
+    }
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  for (n = 0; n < dim; n++)
+    {
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      extent[n] =
+       GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
+    }
+  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 (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"
+                              " MAXLOC 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->base_addr;
+
+  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
diff --git a/libgfortran/generated/maxloc1_4_s4.c b/libgfortran/generated/maxloc1_4_s4.c
new file mode 100644 (file)
index 0000000..16b1616
--- /dev/null
@@ -0,0 +1,552 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_4)
+
+#include <string.h>
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern void maxloc1_4_s4 (gfc_array_i4 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       gfc_charlen_type);
+export_proto(maxloc1_4_s4);
+
+void
+maxloc1_4_s4 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, gfc_charlen_type string_len)
+{
+  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 GFC_INTEGER_4 * restrict base;
+  GFC_INTEGER_4 * 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.  */
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+  dim = (*pdim) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len < 0)
+    len = 0;
+  delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
+
+      retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
+      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"
+                      " MAXLOC 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", "MAXLOC");
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  base = array->base_addr;
+  dest = retarray->base_addr;
+
+  continue_loop = 1;
+  while (continue_loop)
+    {
+      const GFC_INTEGER_4 * restrict src;
+      GFC_INTEGER_4 result;
+      src = base;
+      {
+
+       const GFC_INTEGER_4 *maxval;
+       maxval = base;
+       result = 1;
+       if (len <= 0)
+         *dest = 0;
+       else
+         {
+           for (n = 0; n < len; n++, src += delta)
+             {
+
+               if (compare_fcn (src, maxval, string_len) > 0)
+                 {
+                   maxval = src;
+                   result = (GFC_INTEGER_4)n + 1;
+                 }
+             }
+           
+           *dest = result;
+         }
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[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.  */
+         base -= sstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             continue_loop = 0;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void mmaxloc1_4_s4 (gfc_array_i4 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       gfc_array_l1 * const restrict, gfc_charlen_type);
+export_proto(mmaxloc1_4_s4);
+
+void
+mmaxloc1_4_s4 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, 
+       gfc_array_l1 * const restrict mask, gfc_charlen_type string_len)
+{
+  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];
+  GFC_INTEGER_4 * restrict dest;
+  const GFC_INTEGER_4 * restrict base;
+  const GFC_LOGICAL_1 * restrict mbase;
+  index_type rank;
+  index_type 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;
+
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len <= 0)
+    return;
+
+  mbase = mask->base_addr;
+
+  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) * string_len;
+  mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      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] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
+      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->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
+
+    }
+  else
+    {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in MAXLOC intrinsic");
+
+      if (unlikely (compile_options.bounds_check))
+       {
+         bounds_ifunction_return ((array_t *) retarray, extent,
+                                  "return value", "MAXLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                               "MASK argument", "MAXLOC");
+       }
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  dest = retarray->base_addr;
+  base = array->base_addr;
+
+  while (base)
+    {
+      const GFC_INTEGER_4 * restrict src;
+      const GFC_LOGICAL_1 * restrict msrc;
+      GFC_INTEGER_4 result;
+      src = base;
+      msrc = mbase;
+      {
+
+       const GFC_INTEGER_4 *maxval;
+       maxval = base;
+       result = 0;
+       for (n = 0; n < len; n++, src += delta, msrc += mdelta)
+         {
+
+               if (*msrc)
+                     {
+                       maxval = src;
+                       result = (GFC_INTEGER_4)n + 1;
+                       break;
+                     }
+           }
+           for (; n < len; n++, src += delta, msrc += mdelta)
+             {
+               if (*msrc && compare_fcn (src, maxval, string_len) > 0)
+                 {
+                   maxval = src;
+                   result = (GFC_INTEGER_4)n + 1;
+                 }
+             
+         }
+       *dest = result;
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[0];
+      mbase += mstride[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.  */
+         base -= sstride[n] * extent[n];
+         mbase -= mstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void smaxloc1_4_s4 (gfc_array_i4 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       GFC_LOGICAL_4 *, gfc_charlen_type);
+export_proto(smaxloc1_4_s4);
+
+void
+smaxloc1_4_s4 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, 
+       GFC_LOGICAL_4 * mask, gfc_charlen_type string_len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
+  index_type rank;
+  index_type n;
+  index_type dim;
+
+
+  if (*mask)
+    {
+      maxloc1_4_s4 (retarray, array, pdim, string_len);
+      return;
+    }
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  for (n = 0; n < dim; n++)
+    {
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      extent[n] =
+       GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
+    }
+  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 (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"
+                              " MAXLOC 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->base_addr;
+
+  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
diff --git a/libgfortran/generated/maxloc1_8_s1.c b/libgfortran/generated/maxloc1_8_s1.c
new file mode 100644 (file)
index 0000000..f3d8697
--- /dev/null
@@ -0,0 +1,552 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_8)
+
+#include <string.h>
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern void maxloc1_8_s1 (gfc_array_i8 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       gfc_charlen_type);
+export_proto(maxloc1_8_s1);
+
+void
+maxloc1_8_s1 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, gfc_charlen_type string_len)
+{
+  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 GFC_INTEGER_1 * restrict base;
+  GFC_INTEGER_8 * 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.  */
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+  dim = (*pdim) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len < 0)
+    len = 0;
+  delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
+
+      retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_8));
+      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"
+                      " MAXLOC 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", "MAXLOC");
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  base = array->base_addr;
+  dest = retarray->base_addr;
+
+  continue_loop = 1;
+  while (continue_loop)
+    {
+      const GFC_INTEGER_1 * restrict src;
+      GFC_INTEGER_8 result;
+      src = base;
+      {
+
+       const GFC_INTEGER_1 *maxval;
+       maxval = base;
+       result = 1;
+       if (len <= 0)
+         *dest = 0;
+       else
+         {
+           for (n = 0; n < len; n++, src += delta)
+             {
+
+               if (compare_fcn (src, maxval, string_len) > 0)
+                 {
+                   maxval = src;
+                   result = (GFC_INTEGER_8)n + 1;
+                 }
+             }
+           
+           *dest = result;
+         }
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[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.  */
+         base -= sstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             continue_loop = 0;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void mmaxloc1_8_s1 (gfc_array_i8 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       gfc_array_l1 * const restrict, gfc_charlen_type);
+export_proto(mmaxloc1_8_s1);
+
+void
+mmaxloc1_8_s1 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, 
+       gfc_array_l1 * const restrict mask, gfc_charlen_type string_len)
+{
+  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];
+  GFC_INTEGER_8 * restrict dest;
+  const GFC_INTEGER_1 * restrict base;
+  const GFC_LOGICAL_1 * restrict mbase;
+  index_type rank;
+  index_type 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;
+
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len <= 0)
+    return;
+
+  mbase = mask->base_addr;
+
+  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) * string_len;
+  mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      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] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
+      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->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_8));
+
+    }
+  else
+    {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in MAXLOC intrinsic");
+
+      if (unlikely (compile_options.bounds_check))
+       {
+         bounds_ifunction_return ((array_t *) retarray, extent,
+                                  "return value", "MAXLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                               "MASK argument", "MAXLOC");
+       }
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  dest = retarray->base_addr;
+  base = array->base_addr;
+
+  while (base)
+    {
+      const GFC_INTEGER_1 * restrict src;
+      const GFC_LOGICAL_1 * restrict msrc;
+      GFC_INTEGER_8 result;
+      src = base;
+      msrc = mbase;
+      {
+
+       const GFC_INTEGER_1 *maxval;
+       maxval = base;
+       result = 0;
+       for (n = 0; n < len; n++, src += delta, msrc += mdelta)
+         {
+
+               if (*msrc)
+                     {
+                       maxval = src;
+                       result = (GFC_INTEGER_8)n + 1;
+                       break;
+                     }
+           }
+           for (; n < len; n++, src += delta, msrc += mdelta)
+             {
+               if (*msrc && compare_fcn (src, maxval, string_len) > 0)
+                 {
+                   maxval = src;
+                   result = (GFC_INTEGER_8)n + 1;
+                 }
+             
+         }
+       *dest = result;
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[0];
+      mbase += mstride[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.  */
+         base -= sstride[n] * extent[n];
+         mbase -= mstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void smaxloc1_8_s1 (gfc_array_i8 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       GFC_LOGICAL_4 *, gfc_charlen_type);
+export_proto(smaxloc1_8_s1);
+
+void
+smaxloc1_8_s1 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, 
+       GFC_LOGICAL_4 * mask, gfc_charlen_type string_len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
+  index_type rank;
+  index_type n;
+  index_type dim;
+
+
+  if (*mask)
+    {
+      maxloc1_8_s1 (retarray, array, pdim, string_len);
+      return;
+    }
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  for (n = 0; n < dim; n++)
+    {
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      extent[n] =
+       GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_8));
+    }
+  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 (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"
+                              " MAXLOC 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->base_addr;
+
+  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
diff --git a/libgfortran/generated/maxloc1_8_s4.c b/libgfortran/generated/maxloc1_8_s4.c
new file mode 100644 (file)
index 0000000..bebc185
--- /dev/null
@@ -0,0 +1,552 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_8)
+
+#include <string.h>
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern void maxloc1_8_s4 (gfc_array_i8 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       gfc_charlen_type);
+export_proto(maxloc1_8_s4);
+
+void
+maxloc1_8_s4 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, gfc_charlen_type string_len)
+{
+  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 GFC_INTEGER_4 * restrict base;
+  GFC_INTEGER_8 * 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.  */
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+  dim = (*pdim) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len < 0)
+    len = 0;
+  delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
+
+      retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_8));
+      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"
+                      " MAXLOC 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", "MAXLOC");
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  base = array->base_addr;
+  dest = retarray->base_addr;
+
+  continue_loop = 1;
+  while (continue_loop)
+    {
+      const GFC_INTEGER_4 * restrict src;
+      GFC_INTEGER_8 result;
+      src = base;
+      {
+
+       const GFC_INTEGER_4 *maxval;
+       maxval = base;
+       result = 1;
+       if (len <= 0)
+         *dest = 0;
+       else
+         {
+           for (n = 0; n < len; n++, src += delta)
+             {
+
+               if (compare_fcn (src, maxval, string_len) > 0)
+                 {
+                   maxval = src;
+                   result = (GFC_INTEGER_8)n + 1;
+                 }
+             }
+           
+           *dest = result;
+         }
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[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.  */
+         base -= sstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             continue_loop = 0;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void mmaxloc1_8_s4 (gfc_array_i8 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       gfc_array_l1 * const restrict, gfc_charlen_type);
+export_proto(mmaxloc1_8_s4);
+
+void
+mmaxloc1_8_s4 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, 
+       gfc_array_l1 * const restrict mask, gfc_charlen_type string_len)
+{
+  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];
+  GFC_INTEGER_8 * restrict dest;
+  const GFC_INTEGER_4 * restrict base;
+  const GFC_LOGICAL_1 * restrict mbase;
+  index_type rank;
+  index_type 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;
+
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len <= 0)
+    return;
+
+  mbase = mask->base_addr;
+
+  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) * string_len;
+  mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      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] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
+      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->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_8));
+
+    }
+  else
+    {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in MAXLOC intrinsic");
+
+      if (unlikely (compile_options.bounds_check))
+       {
+         bounds_ifunction_return ((array_t *) retarray, extent,
+                                  "return value", "MAXLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                               "MASK argument", "MAXLOC");
+       }
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  dest = retarray->base_addr;
+  base = array->base_addr;
+
+  while (base)
+    {
+      const GFC_INTEGER_4 * restrict src;
+      const GFC_LOGICAL_1 * restrict msrc;
+      GFC_INTEGER_8 result;
+      src = base;
+      msrc = mbase;
+      {
+
+       const GFC_INTEGER_4 *maxval;
+       maxval = base;
+       result = 0;
+       for (n = 0; n < len; n++, src += delta, msrc += mdelta)
+         {
+
+               if (*msrc)
+                     {
+                       maxval = src;
+                       result = (GFC_INTEGER_8)n + 1;
+                       break;
+                     }
+           }
+           for (; n < len; n++, src += delta, msrc += mdelta)
+             {
+               if (*msrc && compare_fcn (src, maxval, string_len) > 0)
+                 {
+                   maxval = src;
+                   result = (GFC_INTEGER_8)n + 1;
+                 }
+             
+         }
+       *dest = result;
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[0];
+      mbase += mstride[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.  */
+         base -= sstride[n] * extent[n];
+         mbase -= mstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void smaxloc1_8_s4 (gfc_array_i8 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       GFC_LOGICAL_4 *, gfc_charlen_type);
+export_proto(smaxloc1_8_s4);
+
+void
+smaxloc1_8_s4 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, 
+       GFC_LOGICAL_4 * mask, gfc_charlen_type string_len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
+  index_type rank;
+  index_type n;
+  index_type dim;
+
+
+  if (*mask)
+    {
+      maxloc1_8_s4 (retarray, array, pdim, string_len);
+      return;
+    }
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  for (n = 0; n < dim; n++)
+    {
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      extent[n] =
+       GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_8));
+    }
+  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 (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"
+                              " MAXLOC 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->base_addr;
+
+  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
diff --git a/libgfortran/generated/maxloc2_16_s1.c b/libgfortran/generated/maxloc2_16_s1.c
new file mode 100644 (file)
index 0000000..7770101
--- /dev/null
@@ -0,0 +1,156 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_16)
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, int n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern GFC_INTEGER_16 maxloc2_16_s1 (gfc_array_s1 * const restrict, int);
+export_proto(maxloc2_16_s1);
+
+GFC_INTEGER_16
+maxloc2_16_s1 (gfc_array_s1 * const restrict array, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_1 *src;
+  const GFC_INTEGER_1 *maxval;
+  index_type i;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  ret = 1;
+  src = array->base_addr;
+  maxval = src;
+  for (i=2; i<=extent; i++)
+    {
+      src += sstride;
+      if (compare_fcn (src, maxval, len) > 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_16 mmaxloc2_16_s1 (gfc_array_s1 * const restrict,
+                               gfc_array_l1 *const restrict mask, gfc_charlen_type);
+export_proto(mmaxloc2_16_s1);
+
+GFC_INTEGER_16
+mmaxloc2_16_s1 (gfc_array_s1 * const restrict array,
+                                gfc_array_l1 * const restrict mask,
+                                gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_1 *src;
+  const GFC_INTEGER_1 *maxval;
+  index_type i, j;
+  GFC_LOGICAL_1 *mbase;
+  int mask_kind;
+  index_type mstride;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+  mbase = mask->base_addr;
+
+  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
+    internal_error (NULL, "Funny sized logical array");
+
+  mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
+
+  /* Search for the first occurrence of a true element in mask. */
+  for (j=0; j<extent; j++)
+    {
+      if (*mbase)
+        break;
+      mbase += mstride;
+    }
+
+  if (j == extent)
+    return 0;
+
+  ret = j + 1;
+  src = array->base_addr + j * sstride;
+  maxval = src;
+
+  for (i=j+1; i<=extent; i++)
+    {
+      if (*mbase && compare_fcn (src, maxval, len) > 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+      src += sstride;
+      mbase += mstride;
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_16 smaxloc2_16_s1 (gfc_array_s1 * const restrict,
+                               GFC_LOGICAL_4 *mask, int);
+export_proto(smaxloc2_16_s1);
+
+GFC_INTEGER_16
+smaxloc2_16_s1 (gfc_array_s1 * const restrict array,
+                                GFC_LOGICAL_4 *mask, gfc_charlen_type len)
+{
+  if (mask)
+    return maxloc2_16_s1 (array, len);
+  else
+    return 0;
+}
+
+#endif
diff --git a/libgfortran/generated/maxloc2_16_s4.c b/libgfortran/generated/maxloc2_16_s4.c
new file mode 100644 (file)
index 0000000..3279790
--- /dev/null
@@ -0,0 +1,156 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_16)
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, int n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern GFC_INTEGER_16 maxloc2_16_s4 (gfc_array_s4 * const restrict, int);
+export_proto(maxloc2_16_s4);
+
+GFC_INTEGER_16
+maxloc2_16_s4 (gfc_array_s4 * const restrict array, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_4 *src;
+  const GFC_INTEGER_4 *maxval;
+  index_type i;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  ret = 1;
+  src = array->base_addr;
+  maxval = src;
+  for (i=2; i<=extent; i++)
+    {
+      src += sstride;
+      if (compare_fcn (src, maxval, len) > 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_16 mmaxloc2_16_s4 (gfc_array_s4 * const restrict,
+                               gfc_array_l1 *const restrict mask, gfc_charlen_type);
+export_proto(mmaxloc2_16_s4);
+
+GFC_INTEGER_16
+mmaxloc2_16_s4 (gfc_array_s4 * const restrict array,
+                                gfc_array_l1 * const restrict mask,
+                                gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_4 *src;
+  const GFC_INTEGER_4 *maxval;
+  index_type i, j;
+  GFC_LOGICAL_1 *mbase;
+  int mask_kind;
+  index_type mstride;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+  mbase = mask->base_addr;
+
+  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
+    internal_error (NULL, "Funny sized logical array");
+
+  mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
+
+  /* Search for the first occurrence of a true element in mask. */
+  for (j=0; j<extent; j++)
+    {
+      if (*mbase)
+        break;
+      mbase += mstride;
+    }
+
+  if (j == extent)
+    return 0;
+
+  ret = j + 1;
+  src = array->base_addr + j * sstride;
+  maxval = src;
+
+  for (i=j+1; i<=extent; i++)
+    {
+      if (*mbase && compare_fcn (src, maxval, len) > 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+      src += sstride;
+      mbase += mstride;
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_16 smaxloc2_16_s4 (gfc_array_s4 * const restrict,
+                               GFC_LOGICAL_4 *mask, int);
+export_proto(smaxloc2_16_s4);
+
+GFC_INTEGER_16
+smaxloc2_16_s4 (gfc_array_s4 * const restrict array,
+                                GFC_LOGICAL_4 *mask, gfc_charlen_type len)
+{
+  if (mask)
+    return maxloc2_16_s4 (array, len);
+  else
+    return 0;
+}
+
+#endif
diff --git a/libgfortran/generated/maxloc2_4_s1.c b/libgfortran/generated/maxloc2_4_s1.c
new file mode 100644 (file)
index 0000000..a969fcb
--- /dev/null
@@ -0,0 +1,156 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_4)
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, int n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern GFC_INTEGER_4 maxloc2_4_s1 (gfc_array_s1 * const restrict, int);
+export_proto(maxloc2_4_s1);
+
+GFC_INTEGER_4
+maxloc2_4_s1 (gfc_array_s1 * const restrict array, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_1 *src;
+  const GFC_INTEGER_1 *maxval;
+  index_type i;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  ret = 1;
+  src = array->base_addr;
+  maxval = src;
+  for (i=2; i<=extent; i++)
+    {
+      src += sstride;
+      if (compare_fcn (src, maxval, len) > 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_4 mmaxloc2_4_s1 (gfc_array_s1 * const restrict,
+                               gfc_array_l1 *const restrict mask, gfc_charlen_type);
+export_proto(mmaxloc2_4_s1);
+
+GFC_INTEGER_4
+mmaxloc2_4_s1 (gfc_array_s1 * const restrict array,
+                                gfc_array_l1 * const restrict mask,
+                                gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_1 *src;
+  const GFC_INTEGER_1 *maxval;
+  index_type i, j;
+  GFC_LOGICAL_1 *mbase;
+  int mask_kind;
+  index_type mstride;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+  mbase = mask->base_addr;
+
+  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
+    internal_error (NULL, "Funny sized logical array");
+
+  mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
+
+  /* Search for the first occurrence of a true element in mask. */
+  for (j=0; j<extent; j++)
+    {
+      if (*mbase)
+        break;
+      mbase += mstride;
+    }
+
+  if (j == extent)
+    return 0;
+
+  ret = j + 1;
+  src = array->base_addr + j * sstride;
+  maxval = src;
+
+  for (i=j+1; i<=extent; i++)
+    {
+      if (*mbase && compare_fcn (src, maxval, len) > 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+      src += sstride;
+      mbase += mstride;
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_4 smaxloc2_4_s1 (gfc_array_s1 * const restrict,
+                               GFC_LOGICAL_4 *mask, int);
+export_proto(smaxloc2_4_s1);
+
+GFC_INTEGER_4
+smaxloc2_4_s1 (gfc_array_s1 * const restrict array,
+                                GFC_LOGICAL_4 *mask, gfc_charlen_type len)
+{
+  if (mask)
+    return maxloc2_4_s1 (array, len);
+  else
+    return 0;
+}
+
+#endif
diff --git a/libgfortran/generated/maxloc2_4_s4.c b/libgfortran/generated/maxloc2_4_s4.c
new file mode 100644 (file)
index 0000000..3e9c089
--- /dev/null
@@ -0,0 +1,156 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_4)
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, int n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern GFC_INTEGER_4 maxloc2_4_s4 (gfc_array_s4 * const restrict, int);
+export_proto(maxloc2_4_s4);
+
+GFC_INTEGER_4
+maxloc2_4_s4 (gfc_array_s4 * const restrict array, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_4 *src;
+  const GFC_INTEGER_4 *maxval;
+  index_type i;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  ret = 1;
+  src = array->base_addr;
+  maxval = src;
+  for (i=2; i<=extent; i++)
+    {
+      src += sstride;
+      if (compare_fcn (src, maxval, len) > 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_4 mmaxloc2_4_s4 (gfc_array_s4 * const restrict,
+                               gfc_array_l1 *const restrict mask, gfc_charlen_type);
+export_proto(mmaxloc2_4_s4);
+
+GFC_INTEGER_4
+mmaxloc2_4_s4 (gfc_array_s4 * const restrict array,
+                                gfc_array_l1 * const restrict mask,
+                                gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_4 *src;
+  const GFC_INTEGER_4 *maxval;
+  index_type i, j;
+  GFC_LOGICAL_1 *mbase;
+  int mask_kind;
+  index_type mstride;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+  mbase = mask->base_addr;
+
+  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
+    internal_error (NULL, "Funny sized logical array");
+
+  mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
+
+  /* Search for the first occurrence of a true element in mask. */
+  for (j=0; j<extent; j++)
+    {
+      if (*mbase)
+        break;
+      mbase += mstride;
+    }
+
+  if (j == extent)
+    return 0;
+
+  ret = j + 1;
+  src = array->base_addr + j * sstride;
+  maxval = src;
+
+  for (i=j+1; i<=extent; i++)
+    {
+      if (*mbase && compare_fcn (src, maxval, len) > 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+      src += sstride;
+      mbase += mstride;
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_4 smaxloc2_4_s4 (gfc_array_s4 * const restrict,
+                               GFC_LOGICAL_4 *mask, int);
+export_proto(smaxloc2_4_s4);
+
+GFC_INTEGER_4
+smaxloc2_4_s4 (gfc_array_s4 * const restrict array,
+                                GFC_LOGICAL_4 *mask, gfc_charlen_type len)
+{
+  if (mask)
+    return maxloc2_4_s4 (array, len);
+  else
+    return 0;
+}
+
+#endif
diff --git a/libgfortran/generated/maxloc2_8_s1.c b/libgfortran/generated/maxloc2_8_s1.c
new file mode 100644 (file)
index 0000000..bb84ff4
--- /dev/null
@@ -0,0 +1,156 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_8)
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, int n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern GFC_INTEGER_8 maxloc2_8_s1 (gfc_array_s1 * const restrict, int);
+export_proto(maxloc2_8_s1);
+
+GFC_INTEGER_8
+maxloc2_8_s1 (gfc_array_s1 * const restrict array, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_1 *src;
+  const GFC_INTEGER_1 *maxval;
+  index_type i;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  ret = 1;
+  src = array->base_addr;
+  maxval = src;
+  for (i=2; i<=extent; i++)
+    {
+      src += sstride;
+      if (compare_fcn (src, maxval, len) > 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_8 mmaxloc2_8_s1 (gfc_array_s1 * const restrict,
+                               gfc_array_l1 *const restrict mask, gfc_charlen_type);
+export_proto(mmaxloc2_8_s1);
+
+GFC_INTEGER_8
+mmaxloc2_8_s1 (gfc_array_s1 * const restrict array,
+                                gfc_array_l1 * const restrict mask,
+                                gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_1 *src;
+  const GFC_INTEGER_1 *maxval;
+  index_type i, j;
+  GFC_LOGICAL_1 *mbase;
+  int mask_kind;
+  index_type mstride;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+  mbase = mask->base_addr;
+
+  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
+    internal_error (NULL, "Funny sized logical array");
+
+  mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
+
+  /* Search for the first occurrence of a true element in mask. */
+  for (j=0; j<extent; j++)
+    {
+      if (*mbase)
+        break;
+      mbase += mstride;
+    }
+
+  if (j == extent)
+    return 0;
+
+  ret = j + 1;
+  src = array->base_addr + j * sstride;
+  maxval = src;
+
+  for (i=j+1; i<=extent; i++)
+    {
+      if (*mbase && compare_fcn (src, maxval, len) > 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+      src += sstride;
+      mbase += mstride;
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_8 smaxloc2_8_s1 (gfc_array_s1 * const restrict,
+                               GFC_LOGICAL_4 *mask, int);
+export_proto(smaxloc2_8_s1);
+
+GFC_INTEGER_8
+smaxloc2_8_s1 (gfc_array_s1 * const restrict array,
+                                GFC_LOGICAL_4 *mask, gfc_charlen_type len)
+{
+  if (mask)
+    return maxloc2_8_s1 (array, len);
+  else
+    return 0;
+}
+
+#endif
diff --git a/libgfortran/generated/maxloc2_8_s4.c b/libgfortran/generated/maxloc2_8_s4.c
new file mode 100644 (file)
index 0000000..1aa67ca
--- /dev/null
@@ -0,0 +1,156 @@
+/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_8)
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, int n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern GFC_INTEGER_8 maxloc2_8_s4 (gfc_array_s4 * const restrict, int);
+export_proto(maxloc2_8_s4);
+
+GFC_INTEGER_8
+maxloc2_8_s4 (gfc_array_s4 * const restrict array, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_4 *src;
+  const GFC_INTEGER_4 *maxval;
+  index_type i;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  ret = 1;
+  src = array->base_addr;
+  maxval = src;
+  for (i=2; i<=extent; i++)
+    {
+      src += sstride;
+      if (compare_fcn (src, maxval, len) > 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_8 mmaxloc2_8_s4 (gfc_array_s4 * const restrict,
+                               gfc_array_l1 *const restrict mask, gfc_charlen_type);
+export_proto(mmaxloc2_8_s4);
+
+GFC_INTEGER_8
+mmaxloc2_8_s4 (gfc_array_s4 * const restrict array,
+                                gfc_array_l1 * const restrict mask,
+                                gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_4 *src;
+  const GFC_INTEGER_4 *maxval;
+  index_type i, j;
+  GFC_LOGICAL_1 *mbase;
+  int mask_kind;
+  index_type mstride;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+  mbase = mask->base_addr;
+
+  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
+    internal_error (NULL, "Funny sized logical array");
+
+  mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
+
+  /* Search for the first occurrence of a true element in mask. */
+  for (j=0; j<extent; j++)
+    {
+      if (*mbase)
+        break;
+      mbase += mstride;
+    }
+
+  if (j == extent)
+    return 0;
+
+  ret = j + 1;
+  src = array->base_addr + j * sstride;
+  maxval = src;
+
+  for (i=j+1; i<=extent; i++)
+    {
+      if (*mbase && compare_fcn (src, maxval, len) > 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+      src += sstride;
+      mbase += mstride;
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_8 smaxloc2_8_s4 (gfc_array_s4 * const restrict,
+                               GFC_LOGICAL_4 *mask, int);
+export_proto(smaxloc2_8_s4);
+
+GFC_INTEGER_8
+smaxloc2_8_s4 (gfc_array_s4 * const restrict array,
+                                GFC_LOGICAL_4 *mask, gfc_charlen_type len)
+{
+  if (mask)
+    return maxloc2_8_s4 (array, len);
+  else
+    return 0;
+}
+
+#endif
diff --git a/libgfortran/generated/minloc0_16_s1.c b/libgfortran/generated/minloc0_16_s1.c
new file mode 100644 (file)
index 0000000..e43feaf
--- /dev/null
@@ -0,0 +1,327 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_16)
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+
+}
+
+extern void minloc0_16_s1 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, gfc_charlen_type len);
+export_proto(minloc0_16_s1);
+
+void
+minloc0_16_s1 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  const GFC_INTEGER_1 *base;
+  GFC_INTEGER_16 * restrict dest;
+  index_type rank;
+  index_type n;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_16));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                               "MINLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 1;
+  {
+
+  const GFC_INTEGER_1 *minval;
+   minval = base;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (compare_fcn (base, minval, len) < 0)
+    {
+      minval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void mminloc0_16_s1 (gfc_array_i16 * const restrict, 
+       gfc_array_s1 * const restrict, gfc_array_l1 * const restrict, gfc_charlen_type len);
+export_proto(mminloc0_16_s1);
+
+void
+mminloc0_16_s1 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s1 * const restrict array,
+       gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type mstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  GFC_INTEGER_16 *dest;
+  const GFC_INTEGER_1 *base;
+  GFC_LOGICAL_1 *mbase;
+  int rank;
+  index_type n;
+  int mask_kind;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_16));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       {
+
+         bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                                 "MINLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                                 "MASK argument", "MINLOC");
+       }
+    }
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+
+  mbase = mask->base_addr;
+
+  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");
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 0;
+  {
+
+  const GFC_INTEGER_1 *minval;
+
+  minval = NULL;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (*mbase && (minval == NULL || compare_fcn (base, minval, len) < 0))
+    {
+      minval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+         mbase += mstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void sminloc0_16_s1 (gfc_array_i16 * const restrict, 
+       gfc_array_s1 * const restrict, GFC_LOGICAL_4 *, gfc_charlen_type len);
+export_proto(sminloc0_16_s1);
+
+void
+sminloc0_16_s1 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s1 * const restrict array,
+       GFC_LOGICAL_4 * mask, gfc_charlen_type len)
+{
+  index_type rank;
+  index_type dstride;
+  index_type n;
+  GFC_INTEGER_16 *dest;
+
+  if (*mask)
+    {
+      minloc0_16_s1 (retarray, array, len);
+      return;
+    }
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_16));
+    }
+  else if (unlikely (compile_options.bounds_check))
+    {
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                              "MINLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n<rank; n++)
+    dest[n * dstride] = 0 ;
+}
+#endif
diff --git a/libgfortran/generated/minloc0_16_s4.c b/libgfortran/generated/minloc0_16_s4.c
new file mode 100644 (file)
index 0000000..9e1ba35
--- /dev/null
@@ -0,0 +1,327 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_16)
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+
+}
+
+extern void minloc0_16_s4 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, gfc_charlen_type len);
+export_proto(minloc0_16_s4);
+
+void
+minloc0_16_s4 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  const GFC_INTEGER_4 *base;
+  GFC_INTEGER_16 * restrict dest;
+  index_type rank;
+  index_type n;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_16));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                               "MINLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 1;
+  {
+
+  const GFC_INTEGER_4 *minval;
+   minval = base;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (compare_fcn (base, minval, len) < 0)
+    {
+      minval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void mminloc0_16_s4 (gfc_array_i16 * const restrict, 
+       gfc_array_s4 * const restrict, gfc_array_l1 * const restrict, gfc_charlen_type len);
+export_proto(mminloc0_16_s4);
+
+void
+mminloc0_16_s4 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s4 * const restrict array,
+       gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type mstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  GFC_INTEGER_16 *dest;
+  const GFC_INTEGER_4 *base;
+  GFC_LOGICAL_1 *mbase;
+  int rank;
+  index_type n;
+  int mask_kind;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_16));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       {
+
+         bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                                 "MINLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                                 "MASK argument", "MINLOC");
+       }
+    }
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+
+  mbase = mask->base_addr;
+
+  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");
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 0;
+  {
+
+  const GFC_INTEGER_4 *minval;
+
+  minval = NULL;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (*mbase && (minval == NULL || compare_fcn (base, minval, len) < 0))
+    {
+      minval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+         mbase += mstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void sminloc0_16_s4 (gfc_array_i16 * const restrict, 
+       gfc_array_s4 * const restrict, GFC_LOGICAL_4 *, gfc_charlen_type len);
+export_proto(sminloc0_16_s4);
+
+void
+sminloc0_16_s4 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s4 * const restrict array,
+       GFC_LOGICAL_4 * mask, gfc_charlen_type len)
+{
+  index_type rank;
+  index_type dstride;
+  index_type n;
+  GFC_INTEGER_16 *dest;
+
+  if (*mask)
+    {
+      minloc0_16_s4 (retarray, array, len);
+      return;
+    }
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_16));
+    }
+  else if (unlikely (compile_options.bounds_check))
+    {
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                              "MINLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n<rank; n++)
+    dest[n * dstride] = 0 ;
+}
+#endif
diff --git a/libgfortran/generated/minloc0_4_s1.c b/libgfortran/generated/minloc0_4_s1.c
new file mode 100644 (file)
index 0000000..ab95a83
--- /dev/null
@@ -0,0 +1,327 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_4)
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+
+}
+
+extern void minloc0_4_s1 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, gfc_charlen_type len);
+export_proto(minloc0_4_s1);
+
+void
+minloc0_4_s1 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  const GFC_INTEGER_1 *base;
+  GFC_INTEGER_4 * restrict dest;
+  index_type rank;
+  index_type n;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_4));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                               "MINLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 1;
+  {
+
+  const GFC_INTEGER_1 *minval;
+   minval = base;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (compare_fcn (base, minval, len) < 0)
+    {
+      minval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void mminloc0_4_s1 (gfc_array_i4 * const restrict, 
+       gfc_array_s1 * const restrict, gfc_array_l1 * const restrict, gfc_charlen_type len);
+export_proto(mminloc0_4_s1);
+
+void
+mminloc0_4_s1 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s1 * const restrict array,
+       gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type mstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  GFC_INTEGER_4 *dest;
+  const GFC_INTEGER_1 *base;
+  GFC_LOGICAL_1 *mbase;
+  int rank;
+  index_type n;
+  int mask_kind;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_4));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       {
+
+         bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                                 "MINLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                                 "MASK argument", "MINLOC");
+       }
+    }
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+
+  mbase = mask->base_addr;
+
+  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");
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 0;
+  {
+
+  const GFC_INTEGER_1 *minval;
+
+  minval = NULL;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (*mbase && (minval == NULL || compare_fcn (base, minval, len) < 0))
+    {
+      minval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+         mbase += mstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void sminloc0_4_s1 (gfc_array_i4 * const restrict, 
+       gfc_array_s1 * const restrict, GFC_LOGICAL_4 *, gfc_charlen_type len);
+export_proto(sminloc0_4_s1);
+
+void
+sminloc0_4_s1 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s1 * const restrict array,
+       GFC_LOGICAL_4 * mask, gfc_charlen_type len)
+{
+  index_type rank;
+  index_type dstride;
+  index_type n;
+  GFC_INTEGER_4 *dest;
+
+  if (*mask)
+    {
+      minloc0_4_s1 (retarray, array, len);
+      return;
+    }
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_4));
+    }
+  else if (unlikely (compile_options.bounds_check))
+    {
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                              "MINLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n<rank; n++)
+    dest[n * dstride] = 0 ;
+}
+#endif
diff --git a/libgfortran/generated/minloc0_4_s4.c b/libgfortran/generated/minloc0_4_s4.c
new file mode 100644 (file)
index 0000000..4afe02e
--- /dev/null
@@ -0,0 +1,327 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_4)
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+
+}
+
+extern void minloc0_4_s4 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, gfc_charlen_type len);
+export_proto(minloc0_4_s4);
+
+void
+minloc0_4_s4 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  const GFC_INTEGER_4 *base;
+  GFC_INTEGER_4 * restrict dest;
+  index_type rank;
+  index_type n;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_4));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                               "MINLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 1;
+  {
+
+  const GFC_INTEGER_4 *minval;
+   minval = base;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (compare_fcn (base, minval, len) < 0)
+    {
+      minval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void mminloc0_4_s4 (gfc_array_i4 * const restrict, 
+       gfc_array_s4 * const restrict, gfc_array_l1 * const restrict, gfc_charlen_type len);
+export_proto(mminloc0_4_s4);
+
+void
+mminloc0_4_s4 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s4 * const restrict array,
+       gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type mstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  GFC_INTEGER_4 *dest;
+  const GFC_INTEGER_4 *base;
+  GFC_LOGICAL_1 *mbase;
+  int rank;
+  index_type n;
+  int mask_kind;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_4));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       {
+
+         bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                                 "MINLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                                 "MASK argument", "MINLOC");
+       }
+    }
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+
+  mbase = mask->base_addr;
+
+  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");
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 0;
+  {
+
+  const GFC_INTEGER_4 *minval;
+
+  minval = NULL;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (*mbase && (minval == NULL || compare_fcn (base, minval, len) < 0))
+    {
+      minval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+         mbase += mstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void sminloc0_4_s4 (gfc_array_i4 * const restrict, 
+       gfc_array_s4 * const restrict, GFC_LOGICAL_4 *, gfc_charlen_type len);
+export_proto(sminloc0_4_s4);
+
+void
+sminloc0_4_s4 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s4 * const restrict array,
+       GFC_LOGICAL_4 * mask, gfc_charlen_type len)
+{
+  index_type rank;
+  index_type dstride;
+  index_type n;
+  GFC_INTEGER_4 *dest;
+
+  if (*mask)
+    {
+      minloc0_4_s4 (retarray, array, len);
+      return;
+    }
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_4));
+    }
+  else if (unlikely (compile_options.bounds_check))
+    {
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                              "MINLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n<rank; n++)
+    dest[n * dstride] = 0 ;
+}
+#endif
diff --git a/libgfortran/generated/minloc0_8_s1.c b/libgfortran/generated/minloc0_8_s1.c
new file mode 100644 (file)
index 0000000..0dc18fe
--- /dev/null
@@ -0,0 +1,327 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_8)
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+
+}
+
+extern void minloc0_8_s1 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, gfc_charlen_type len);
+export_proto(minloc0_8_s1);
+
+void
+minloc0_8_s1 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  const GFC_INTEGER_1 *base;
+  GFC_INTEGER_8 * restrict dest;
+  index_type rank;
+  index_type n;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                               "MINLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 1;
+  {
+
+  const GFC_INTEGER_1 *minval;
+   minval = base;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (compare_fcn (base, minval, len) < 0)
+    {
+      minval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void mminloc0_8_s1 (gfc_array_i8 * const restrict, 
+       gfc_array_s1 * const restrict, gfc_array_l1 * const restrict, gfc_charlen_type len);
+export_proto(mminloc0_8_s1);
+
+void
+mminloc0_8_s1 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s1 * const restrict array,
+       gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type mstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  GFC_INTEGER_8 *dest;
+  const GFC_INTEGER_1 *base;
+  GFC_LOGICAL_1 *mbase;
+  int rank;
+  index_type n;
+  int mask_kind;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       {
+
+         bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                                 "MINLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                                 "MASK argument", "MINLOC");
+       }
+    }
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+
+  mbase = mask->base_addr;
+
+  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");
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 0;
+  {
+
+  const GFC_INTEGER_1 *minval;
+
+  minval = NULL;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (*mbase && (minval == NULL || compare_fcn (base, minval, len) < 0))
+    {
+      minval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+         mbase += mstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void sminloc0_8_s1 (gfc_array_i8 * const restrict, 
+       gfc_array_s1 * const restrict, GFC_LOGICAL_4 *, gfc_charlen_type len);
+export_proto(sminloc0_8_s1);
+
+void
+sminloc0_8_s1 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s1 * const restrict array,
+       GFC_LOGICAL_4 * mask, gfc_charlen_type len)
+{
+  index_type rank;
+  index_type dstride;
+  index_type n;
+  GFC_INTEGER_8 *dest;
+
+  if (*mask)
+    {
+      minloc0_8_s1 (retarray, array, len);
+      return;
+    }
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
+    }
+  else if (unlikely (compile_options.bounds_check))
+    {
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                              "MINLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n<rank; n++)
+    dest[n * dstride] = 0 ;
+}
+#endif
diff --git a/libgfortran/generated/minloc0_8_s4.c b/libgfortran/generated/minloc0_8_s4.c
new file mode 100644 (file)
index 0000000..bd84788
--- /dev/null
@@ -0,0 +1,327 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_8)
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+
+}
+
+extern void minloc0_8_s4 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, gfc_charlen_type len);
+export_proto(minloc0_8_s4);
+
+void
+minloc0_8_s4 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  const GFC_INTEGER_4 *base;
+  GFC_INTEGER_8 * restrict dest;
+  index_type rank;
+  index_type n;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                               "MINLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 1;
+  {
+
+  const GFC_INTEGER_4 *minval;
+   minval = base;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (compare_fcn (base, minval, len) < 0)
+    {
+      minval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void mminloc0_8_s4 (gfc_array_i8 * const restrict, 
+       gfc_array_s4 * const restrict, gfc_array_l1 * const restrict, gfc_charlen_type len);
+export_proto(mminloc0_8_s4);
+
+void
+mminloc0_8_s4 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s4 * const restrict array,
+       gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type mstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  GFC_INTEGER_8 *dest;
+  const GFC_INTEGER_4 *base;
+  GFC_LOGICAL_1 *mbase;
+  int rank;
+  index_type n;
+  int mask_kind;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       {
+
+         bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                                 "MINLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                                 "MASK argument", "MINLOC");
+       }
+    }
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+
+  mbase = mask->base_addr;
+
+  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");
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 0;
+  {
+
+  const GFC_INTEGER_4 *minval;
+
+  minval = NULL;
+
+  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+
+  if (*mbase && (minval == NULL || compare_fcn (base, minval, len) < 0))
+    {
+      minval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }
+         /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+         mbase += mstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}
+
+
+extern void sminloc0_8_s4 (gfc_array_i8 * const restrict, 
+       gfc_array_s4 * const restrict, GFC_LOGICAL_4 *, gfc_charlen_type len);
+export_proto(sminloc0_8_s4);
+
+void
+sminloc0_8_s4 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s4 * const restrict array,
+       GFC_LOGICAL_4 * mask, gfc_charlen_type len)
+{
+  index_type rank;
+  index_type dstride;
+  index_type n;
+  GFC_INTEGER_8 *dest;
+
+  if (*mask)
+    {
+      minloc0_8_s4 (retarray, array, len);
+      return;
+    }
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (GFC_INTEGER_8));
+    }
+  else if (unlikely (compile_options.bounds_check))
+    {
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                              "MINLOC");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n<rank; n++)
+    dest[n * dstride] = 0 ;
+}
+#endif
diff --git a/libgfortran/generated/minloc1_16_s1.c b/libgfortran/generated/minloc1_16_s1.c
new file mode 100644 (file)
index 0000000..80269a6
--- /dev/null
@@ -0,0 +1,552 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_16)
+
+#include <string.h>
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern void minloc1_16_s1 (gfc_array_i16 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       gfc_charlen_type);
+export_proto(minloc1_16_s1);
+
+void
+minloc1_16_s1 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, gfc_charlen_type string_len)
+{
+  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 GFC_INTEGER_1 * restrict base;
+  GFC_INTEGER_16 * 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.  */
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+  dim = (*pdim) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len < 0)
+    len = 0;
+  delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
+
+      retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
+      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"
+                      " MINLOC 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", "MINLOC");
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  base = array->base_addr;
+  dest = retarray->base_addr;
+
+  continue_loop = 1;
+  while (continue_loop)
+    {
+      const GFC_INTEGER_1 * restrict src;
+      GFC_INTEGER_16 result;
+      src = base;
+      {
+
+       const GFC_INTEGER_1 *minval;
+       minval = base;
+       result = 1;
+       if (len <= 0)
+         *dest = 0;
+       else
+         {
+           for (n = 0; n < len; n++, src += delta)
+             {
+
+               if (compare_fcn (src, minval, string_len) < 0)
+                 {
+                   minval = src;
+                   result = (GFC_INTEGER_16)n + 1;
+                 }
+             }
+           
+           *dest = result;
+         }
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[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.  */
+         base -= sstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             continue_loop = 0;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void mminloc1_16_s1 (gfc_array_i16 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       gfc_array_l1 * const restrict, gfc_charlen_type);
+export_proto(mminloc1_16_s1);
+
+void
+mminloc1_16_s1 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, 
+       gfc_array_l1 * const restrict mask, gfc_charlen_type string_len)
+{
+  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];
+  GFC_INTEGER_16 * restrict dest;
+  const GFC_INTEGER_1 * restrict base;
+  const GFC_LOGICAL_1 * restrict mbase;
+  index_type rank;
+  index_type 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;
+
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len <= 0)
+    return;
+
+  mbase = mask->base_addr;
+
+  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) * string_len;
+  mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      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] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
+      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->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
+
+    }
+  else
+    {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in MINLOC intrinsic");
+
+      if (unlikely (compile_options.bounds_check))
+       {
+         bounds_ifunction_return ((array_t *) retarray, extent,
+                                  "return value", "MINLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                               "MASK argument", "MINLOC");
+       }
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  dest = retarray->base_addr;
+  base = array->base_addr;
+
+  while (base)
+    {
+      const GFC_INTEGER_1 * restrict src;
+      const GFC_LOGICAL_1 * restrict msrc;
+      GFC_INTEGER_16 result;
+      src = base;
+      msrc = mbase;
+      {
+
+       const GFC_INTEGER_1 *minval;
+       minval = base;
+       result = 0;
+       for (n = 0; n < len; n++, src += delta, msrc += mdelta)
+         {
+
+               if (*msrc)
+                     {
+                       minval = src;
+                       result = (GFC_INTEGER_16)n + 1;
+                       break;
+                     }
+            }
+           for (; n < len; n++, src += delta, msrc += mdelta)
+             {
+               if (*msrc && compare_fcn (src, minval, string_len) < 0)
+                 {
+                   minval = src;
+                   result = (GFC_INTEGER_16)n + 1;
+                 }
+             
+         }
+       *dest = result;
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[0];
+      mbase += mstride[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.  */
+         base -= sstride[n] * extent[n];
+         mbase -= mstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void sminloc1_16_s1 (gfc_array_i16 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       GFC_LOGICAL_4 *, gfc_charlen_type);
+export_proto(sminloc1_16_s1);
+
+void
+sminloc1_16_s1 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, 
+       GFC_LOGICAL_4 * mask, gfc_charlen_type string_len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
+  index_type rank;
+  index_type n;
+  index_type dim;
+
+
+  if (*mask)
+    {
+      minloc1_16_s1 (retarray, array, pdim, string_len);
+      return;
+    }
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  for (n = 0; n < dim; n++)
+    {
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      extent[n] =
+       GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
+    }
+  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 (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"
+                              " MINLOC 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->base_addr;
+
+  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
diff --git a/libgfortran/generated/minloc1_16_s4.c b/libgfortran/generated/minloc1_16_s4.c
new file mode 100644 (file)
index 0000000..1ba1a01
--- /dev/null
@@ -0,0 +1,552 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_16)
+
+#include <string.h>
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern void minloc1_16_s4 (gfc_array_i16 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       gfc_charlen_type);
+export_proto(minloc1_16_s4);
+
+void
+minloc1_16_s4 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, gfc_charlen_type string_len)
+{
+  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 GFC_INTEGER_4 * restrict base;
+  GFC_INTEGER_16 * 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.  */
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+  dim = (*pdim) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len < 0)
+    len = 0;
+  delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
+
+      retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
+      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"
+                      " MINLOC 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", "MINLOC");
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  base = array->base_addr;
+  dest = retarray->base_addr;
+
+  continue_loop = 1;
+  while (continue_loop)
+    {
+      const GFC_INTEGER_4 * restrict src;
+      GFC_INTEGER_16 result;
+      src = base;
+      {
+
+       const GFC_INTEGER_4 *minval;
+       minval = base;
+       result = 1;
+       if (len <= 0)
+         *dest = 0;
+       else
+         {
+           for (n = 0; n < len; n++, src += delta)
+             {
+
+               if (compare_fcn (src, minval, string_len) < 0)
+                 {
+                   minval = src;
+                   result = (GFC_INTEGER_16)n + 1;
+                 }
+             }
+           
+           *dest = result;
+         }
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[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.  */
+         base -= sstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             continue_loop = 0;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void mminloc1_16_s4 (gfc_array_i16 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       gfc_array_l1 * const restrict, gfc_charlen_type);
+export_proto(mminloc1_16_s4);
+
+void
+mminloc1_16_s4 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, 
+       gfc_array_l1 * const restrict mask, gfc_charlen_type string_len)
+{
+  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];
+  GFC_INTEGER_16 * restrict dest;
+  const GFC_INTEGER_4 * restrict base;
+  const GFC_LOGICAL_1 * restrict mbase;
+  index_type rank;
+  index_type 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;
+
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len <= 0)
+    return;
+
+  mbase = mask->base_addr;
+
+  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) * string_len;
+  mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      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] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
+      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->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
+
+    }
+  else
+    {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in MINLOC intrinsic");
+
+      if (unlikely (compile_options.bounds_check))
+       {
+         bounds_ifunction_return ((array_t *) retarray, extent,
+                                  "return value", "MINLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                               "MASK argument", "MINLOC");
+       }
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  dest = retarray->base_addr;
+  base = array->base_addr;
+
+  while (base)
+    {
+      const GFC_INTEGER_4 * restrict src;
+      const GFC_LOGICAL_1 * restrict msrc;
+      GFC_INTEGER_16 result;
+      src = base;
+      msrc = mbase;
+      {
+
+       const GFC_INTEGER_4 *minval;
+       minval = base;
+       result = 0;
+       for (n = 0; n < len; n++, src += delta, msrc += mdelta)
+         {
+
+               if (*msrc)
+                     {
+                       minval = src;
+                       result = (GFC_INTEGER_16)n + 1;
+                       break;
+                     }
+            }
+           for (; n < len; n++, src += delta, msrc += mdelta)
+             {
+               if (*msrc && compare_fcn (src, minval, string_len) < 0)
+                 {
+                   minval = src;
+                   result = (GFC_INTEGER_16)n + 1;
+                 }
+             
+         }
+       *dest = result;
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[0];
+      mbase += mstride[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.  */
+         base -= sstride[n] * extent[n];
+         mbase -= mstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void sminloc1_16_s4 (gfc_array_i16 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       GFC_LOGICAL_4 *, gfc_charlen_type);
+export_proto(sminloc1_16_s4);
+
+void
+sminloc1_16_s4 (gfc_array_i16 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, 
+       GFC_LOGICAL_4 * mask, gfc_charlen_type string_len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_16 * restrict dest;
+  index_type rank;
+  index_type n;
+  index_type dim;
+
+
+  if (*mask)
+    {
+      minloc1_16_s4 (retarray, array, pdim, string_len);
+      return;
+    }
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  for (n = 0; n < dim; n++)
+    {
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      extent[n] =
+       GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
+    }
+  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 (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"
+                              " MINLOC 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->base_addr;
+
+  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
diff --git a/libgfortran/generated/minloc1_4_s1.c b/libgfortran/generated/minloc1_4_s1.c
new file mode 100644 (file)
index 0000000..bbead6b
--- /dev/null
@@ -0,0 +1,552 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_4)
+
+#include <string.h>
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern void minloc1_4_s1 (gfc_array_i4 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       gfc_charlen_type);
+export_proto(minloc1_4_s1);
+
+void
+minloc1_4_s1 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, gfc_charlen_type string_len)
+{
+  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 GFC_INTEGER_1 * restrict base;
+  GFC_INTEGER_4 * 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.  */
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+  dim = (*pdim) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len < 0)
+    len = 0;
+  delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
+
+      retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
+      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"
+                      " MINLOC 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", "MINLOC");
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  base = array->base_addr;
+  dest = retarray->base_addr;
+
+  continue_loop = 1;
+  while (continue_loop)
+    {
+      const GFC_INTEGER_1 * restrict src;
+      GFC_INTEGER_4 result;
+      src = base;
+      {
+
+       const GFC_INTEGER_1 *minval;
+       minval = base;
+       result = 1;
+       if (len <= 0)
+         *dest = 0;
+       else
+         {
+           for (n = 0; n < len; n++, src += delta)
+             {
+
+               if (compare_fcn (src, minval, string_len) < 0)
+                 {
+                   minval = src;
+                   result = (GFC_INTEGER_4)n + 1;
+                 }
+             }
+           
+           *dest = result;
+         }
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[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.  */
+         base -= sstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             continue_loop = 0;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void mminloc1_4_s1 (gfc_array_i4 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       gfc_array_l1 * const restrict, gfc_charlen_type);
+export_proto(mminloc1_4_s1);
+
+void
+mminloc1_4_s1 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, 
+       gfc_array_l1 * const restrict mask, gfc_charlen_type string_len)
+{
+  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];
+  GFC_INTEGER_4 * restrict dest;
+  const GFC_INTEGER_1 * restrict base;
+  const GFC_LOGICAL_1 * restrict mbase;
+  index_type rank;
+  index_type 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;
+
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len <= 0)
+    return;
+
+  mbase = mask->base_addr;
+
+  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) * string_len;
+  mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      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] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
+      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->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
+
+    }
+  else
+    {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in MINLOC intrinsic");
+
+      if (unlikely (compile_options.bounds_check))
+       {
+         bounds_ifunction_return ((array_t *) retarray, extent,
+                                  "return value", "MINLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                               "MASK argument", "MINLOC");
+       }
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  dest = retarray->base_addr;
+  base = array->base_addr;
+
+  while (base)
+    {
+      const GFC_INTEGER_1 * restrict src;
+      const GFC_LOGICAL_1 * restrict msrc;
+      GFC_INTEGER_4 result;
+      src = base;
+      msrc = mbase;
+      {
+
+       const GFC_INTEGER_1 *minval;
+       minval = base;
+       result = 0;
+       for (n = 0; n < len; n++, src += delta, msrc += mdelta)
+         {
+
+               if (*msrc)
+                     {
+                       minval = src;
+                       result = (GFC_INTEGER_4)n + 1;
+                       break;
+                     }
+            }
+           for (; n < len; n++, src += delta, msrc += mdelta)
+             {
+               if (*msrc && compare_fcn (src, minval, string_len) < 0)
+                 {
+                   minval = src;
+                   result = (GFC_INTEGER_4)n + 1;
+                 }
+             
+         }
+       *dest = result;
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[0];
+      mbase += mstride[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.  */
+         base -= sstride[n] * extent[n];
+         mbase -= mstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void sminloc1_4_s1 (gfc_array_i4 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       GFC_LOGICAL_4 *, gfc_charlen_type);
+export_proto(sminloc1_4_s1);
+
+void
+sminloc1_4_s1 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, 
+       GFC_LOGICAL_4 * mask, gfc_charlen_type string_len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
+  index_type rank;
+  index_type n;
+  index_type dim;
+
+
+  if (*mask)
+    {
+      minloc1_4_s1 (retarray, array, pdim, string_len);
+      return;
+    }
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  for (n = 0; n < dim; n++)
+    {
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      extent[n] =
+       GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
+    }
+  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 (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"
+                              " MINLOC 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->base_addr;
+
+  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
diff --git a/libgfortran/generated/minloc1_4_s4.c b/libgfortran/generated/minloc1_4_s4.c
new file mode 100644 (file)
index 0000000..673702b
--- /dev/null
@@ -0,0 +1,552 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_4)
+
+#include <string.h>
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern void minloc1_4_s4 (gfc_array_i4 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       gfc_charlen_type);
+export_proto(minloc1_4_s4);
+
+void
+minloc1_4_s4 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, gfc_charlen_type string_len)
+{
+  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 GFC_INTEGER_4 * restrict base;
+  GFC_INTEGER_4 * 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.  */
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+  dim = (*pdim) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len < 0)
+    len = 0;
+  delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
+
+      retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
+      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"
+                      " MINLOC 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", "MINLOC");
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  base = array->base_addr;
+  dest = retarray->base_addr;
+
+  continue_loop = 1;
+  while (continue_loop)
+    {
+      const GFC_INTEGER_4 * restrict src;
+      GFC_INTEGER_4 result;
+      src = base;
+      {
+
+       const GFC_INTEGER_4 *minval;
+       minval = base;
+       result = 1;
+       if (len <= 0)
+         *dest = 0;
+       else
+         {
+           for (n = 0; n < len; n++, src += delta)
+             {
+
+               if (compare_fcn (src, minval, string_len) < 0)
+                 {
+                   minval = src;
+                   result = (GFC_INTEGER_4)n + 1;
+                 }
+             }
+           
+           *dest = result;
+         }
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[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.  */
+         base -= sstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             continue_loop = 0;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void mminloc1_4_s4 (gfc_array_i4 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       gfc_array_l1 * const restrict, gfc_charlen_type);
+export_proto(mminloc1_4_s4);
+
+void
+mminloc1_4_s4 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, 
+       gfc_array_l1 * const restrict mask, gfc_charlen_type string_len)
+{
+  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];
+  GFC_INTEGER_4 * restrict dest;
+  const GFC_INTEGER_4 * restrict base;
+  const GFC_LOGICAL_1 * restrict mbase;
+  index_type rank;
+  index_type 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;
+
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len <= 0)
+    return;
+
+  mbase = mask->base_addr;
+
+  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) * string_len;
+  mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      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] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
+      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->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
+
+    }
+  else
+    {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in MINLOC intrinsic");
+
+      if (unlikely (compile_options.bounds_check))
+       {
+         bounds_ifunction_return ((array_t *) retarray, extent,
+                                  "return value", "MINLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                               "MASK argument", "MINLOC");
+       }
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  dest = retarray->base_addr;
+  base = array->base_addr;
+
+  while (base)
+    {
+      const GFC_INTEGER_4 * restrict src;
+      const GFC_LOGICAL_1 * restrict msrc;
+      GFC_INTEGER_4 result;
+      src = base;
+      msrc = mbase;
+      {
+
+       const GFC_INTEGER_4 *minval;
+       minval = base;
+       result = 0;
+       for (n = 0; n < len; n++, src += delta, msrc += mdelta)
+         {
+
+               if (*msrc)
+                     {
+                       minval = src;
+                       result = (GFC_INTEGER_4)n + 1;
+                       break;
+                     }
+            }
+           for (; n < len; n++, src += delta, msrc += mdelta)
+             {
+               if (*msrc && compare_fcn (src, minval, string_len) < 0)
+                 {
+                   minval = src;
+                   result = (GFC_INTEGER_4)n + 1;
+                 }
+             
+         }
+       *dest = result;
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[0];
+      mbase += mstride[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.  */
+         base -= sstride[n] * extent[n];
+         mbase -= mstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void sminloc1_4_s4 (gfc_array_i4 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       GFC_LOGICAL_4 *, gfc_charlen_type);
+export_proto(sminloc1_4_s4);
+
+void
+sminloc1_4_s4 (gfc_array_i4 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, 
+       GFC_LOGICAL_4 * mask, gfc_charlen_type string_len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_4 * restrict dest;
+  index_type rank;
+  index_type n;
+  index_type dim;
+
+
+  if (*mask)
+    {
+      minloc1_4_s4 (retarray, array, pdim, string_len);
+      return;
+    }
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  for (n = 0; n < dim; n++)
+    {
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      extent[n] =
+       GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_4));
+    }
+  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 (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"
+                              " MINLOC 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->base_addr;
+
+  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
diff --git a/libgfortran/generated/minloc1_8_s1.c b/libgfortran/generated/minloc1_8_s1.c
new file mode 100644 (file)
index 0000000..90ab353
--- /dev/null
@@ -0,0 +1,552 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_8)
+
+#include <string.h>
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern void minloc1_8_s1 (gfc_array_i8 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       gfc_charlen_type);
+export_proto(minloc1_8_s1);
+
+void
+minloc1_8_s1 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, gfc_charlen_type string_len)
+{
+  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 GFC_INTEGER_1 * restrict base;
+  GFC_INTEGER_8 * 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.  */
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+  dim = (*pdim) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len < 0)
+    len = 0;
+  delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
+
+      retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_8));
+      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"
+                      " MINLOC 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", "MINLOC");
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  base = array->base_addr;
+  dest = retarray->base_addr;
+
+  continue_loop = 1;
+  while (continue_loop)
+    {
+      const GFC_INTEGER_1 * restrict src;
+      GFC_INTEGER_8 result;
+      src = base;
+      {
+
+       const GFC_INTEGER_1 *minval;
+       minval = base;
+       result = 1;
+       if (len <= 0)
+         *dest = 0;
+       else
+         {
+           for (n = 0; n < len; n++, src += delta)
+             {
+
+               if (compare_fcn (src, minval, string_len) < 0)
+                 {
+                   minval = src;
+                   result = (GFC_INTEGER_8)n + 1;
+                 }
+             }
+           
+           *dest = result;
+         }
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[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.  */
+         base -= sstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             continue_loop = 0;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void mminloc1_8_s1 (gfc_array_i8 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       gfc_array_l1 * const restrict, gfc_charlen_type);
+export_proto(mminloc1_8_s1);
+
+void
+mminloc1_8_s1 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, 
+       gfc_array_l1 * const restrict mask, gfc_charlen_type string_len)
+{
+  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];
+  GFC_INTEGER_8 * restrict dest;
+  const GFC_INTEGER_1 * restrict base;
+  const GFC_LOGICAL_1 * restrict mbase;
+  index_type rank;
+  index_type 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;
+
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len <= 0)
+    return;
+
+  mbase = mask->base_addr;
+
+  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) * string_len;
+  mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      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] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
+      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->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_8));
+
+    }
+  else
+    {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in MINLOC intrinsic");
+
+      if (unlikely (compile_options.bounds_check))
+       {
+         bounds_ifunction_return ((array_t *) retarray, extent,
+                                  "return value", "MINLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                               "MASK argument", "MINLOC");
+       }
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  dest = retarray->base_addr;
+  base = array->base_addr;
+
+  while (base)
+    {
+      const GFC_INTEGER_1 * restrict src;
+      const GFC_LOGICAL_1 * restrict msrc;
+      GFC_INTEGER_8 result;
+      src = base;
+      msrc = mbase;
+      {
+
+       const GFC_INTEGER_1 *minval;
+       minval = base;
+       result = 0;
+       for (n = 0; n < len; n++, src += delta, msrc += mdelta)
+         {
+
+               if (*msrc)
+                     {
+                       minval = src;
+                       result = (GFC_INTEGER_8)n + 1;
+                       break;
+                     }
+            }
+           for (; n < len; n++, src += delta, msrc += mdelta)
+             {
+               if (*msrc && compare_fcn (src, minval, string_len) < 0)
+                 {
+                   minval = src;
+                   result = (GFC_INTEGER_8)n + 1;
+                 }
+             
+         }
+       *dest = result;
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[0];
+      mbase += mstride[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.  */
+         base -= sstride[n] * extent[n];
+         mbase -= mstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void sminloc1_8_s1 (gfc_array_i8 * const restrict, 
+       gfc_array_s1 * const restrict, const index_type * const restrict,
+       GFC_LOGICAL_4 *, gfc_charlen_type);
+export_proto(sminloc1_8_s1);
+
+void
+sminloc1_8_s1 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s1 * const restrict array, 
+       const index_type * const restrict pdim, 
+       GFC_LOGICAL_4 * mask, gfc_charlen_type string_len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
+  index_type rank;
+  index_type n;
+  index_type dim;
+
+
+  if (*mask)
+    {
+      minloc1_8_s1 (retarray, array, pdim, string_len);
+      return;
+    }
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  for (n = 0; n < dim; n++)
+    {
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      extent[n] =
+       GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_8));
+    }
+  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 (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"
+                              " MINLOC 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->base_addr;
+
+  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
diff --git a/libgfortran/generated/minloc1_8_s4.c b/libgfortran/generated/minloc1_8_s4.c
new file mode 100644 (file)
index 0000000..10c0208
--- /dev/null
@@ -0,0 +1,552 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_8)
+
+#include <string.h>
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, gfc_charlen_type n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern void minloc1_8_s4 (gfc_array_i8 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       gfc_charlen_type);
+export_proto(minloc1_8_s4);
+
+void
+minloc1_8_s4 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, gfc_charlen_type string_len)
+{
+  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 GFC_INTEGER_4 * restrict base;
+  GFC_INTEGER_8 * 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.  */
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+  dim = (*pdim) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len < 0)
+    len = 0;
+  delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
+
+      retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_8));
+      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"
+                      " MINLOC 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", "MINLOC");
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  base = array->base_addr;
+  dest = retarray->base_addr;
+
+  continue_loop = 1;
+  while (continue_loop)
+    {
+      const GFC_INTEGER_4 * restrict src;
+      GFC_INTEGER_8 result;
+      src = base;
+      {
+
+       const GFC_INTEGER_4 *minval;
+       minval = base;
+       result = 1;
+       if (len <= 0)
+         *dest = 0;
+       else
+         {
+           for (n = 0; n < len; n++, src += delta)
+             {
+
+               if (compare_fcn (src, minval, string_len) < 0)
+                 {
+                   minval = src;
+                   result = (GFC_INTEGER_8)n + 1;
+                 }
+             }
+           
+           *dest = result;
+         }
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[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.  */
+         base -= sstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             continue_loop = 0;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void mminloc1_8_s4 (gfc_array_i8 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       gfc_array_l1 * const restrict, gfc_charlen_type);
+export_proto(mminloc1_8_s4);
+
+void
+mminloc1_8_s4 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, 
+       gfc_array_l1 * const restrict mask, gfc_charlen_type string_len)
+{
+  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];
+  GFC_INTEGER_8 * restrict dest;
+  const GFC_INTEGER_4 * restrict base;
+  const GFC_LOGICAL_1 * restrict mbase;
+  index_type rank;
+  index_type 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;
+
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len <= 0)
+    return;
+
+  mbase = mask->base_addr;
+
+  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) * string_len;
+  mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      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] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
+      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->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_8));
+
+    }
+  else
+    {
+      if (rank != GFC_DESCRIPTOR_RANK (retarray))
+       runtime_error ("rank of return array incorrect in MINLOC intrinsic");
+
+      if (unlikely (compile_options.bounds_check))
+       {
+         bounds_ifunction_return ((array_t *) retarray, extent,
+                                  "return value", "MINLOC");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                               "MASK argument", "MINLOC");
+       }
+    }
+
+  for (n = 0; n < rank; n++)
+    {
+      count[n] = 0;
+      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  dest = retarray->base_addr;
+  base = array->base_addr;
+
+  while (base)
+    {
+      const GFC_INTEGER_4 * restrict src;
+      const GFC_LOGICAL_1 * restrict msrc;
+      GFC_INTEGER_8 result;
+      src = base;
+      msrc = mbase;
+      {
+
+       const GFC_INTEGER_4 *minval;
+       minval = base;
+       result = 0;
+       for (n = 0; n < len; n++, src += delta, msrc += mdelta)
+         {
+
+               if (*msrc)
+                     {
+                       minval = src;
+                       result = (GFC_INTEGER_8)n + 1;
+                       break;
+                     }
+            }
+           for (; n < len; n++, src += delta, msrc += mdelta)
+             {
+               if (*msrc && compare_fcn (src, minval, string_len) < 0)
+                 {
+                   minval = src;
+                   result = (GFC_INTEGER_8)n + 1;
+                 }
+             
+         }
+       *dest = result;
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[0];
+      mbase += mstride[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.  */
+         base -= sstride[n] * extent[n];
+         mbase -= mstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}
+
+
+extern void sminloc1_8_s4 (gfc_array_i8 * const restrict, 
+       gfc_array_s4 * const restrict, const index_type * const restrict,
+       GFC_LOGICAL_4 *, gfc_charlen_type);
+export_proto(sminloc1_8_s4);
+
+void
+sminloc1_8_s4 (gfc_array_i8 * const restrict retarray, 
+       gfc_array_s4 * const restrict array, 
+       const index_type * const restrict pdim, 
+       GFC_LOGICAL_4 * mask, gfc_charlen_type string_len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type dstride[GFC_MAX_DIMENSIONS];
+  GFC_INTEGER_8 * restrict dest;
+  index_type rank;
+  index_type n;
+  index_type dim;
+
+
+  if (*mask)
+    {
+      minloc1_8_s4 (retarray, array, pdim, string_len);
+      return;
+    }
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in MINLOC intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  for (n = 0; n < dim; n++)
+    {
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      extent[n] =
+       GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_8));
+    }
+  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 (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"
+                              " MINLOC 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->base_addr;
+
+  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
diff --git a/libgfortran/generated/minloc2_16_s1.c b/libgfortran/generated/minloc2_16_s1.c
new file mode 100644 (file)
index 0000000..3f9e907
--- /dev/null
@@ -0,0 +1,155 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_16)
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, int n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern GFC_INTEGER_16 minloc2_16_s1 (gfc_array_s1 * const restrict, int);
+export_proto(minloc2_16_s1);
+
+GFC_INTEGER_16
+minloc2_16_s1 (gfc_array_s1 * const restrict array, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_1 *src;
+  const GFC_INTEGER_1 *maxval;
+  index_type i;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  ret = 1;
+  src = array->base_addr;
+  maxval = src;
+  for (i=2; i<=extent; i++)
+    {
+      src += sstride;
+      if (compare_fcn (src, maxval, len) < 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_16 mminloc2_16_s1 (gfc_array_s1 * const restrict,
+                               gfc_array_l1 *const restrict mask, int);
+export_proto(mminloc2_16_s1);
+
+GFC_INTEGER_16
+mminloc2_16_s1 (gfc_array_s1 * const restrict array,
+                                gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_1 *src;
+  const GFC_INTEGER_1 *maxval;
+  index_type i, j;
+  GFC_LOGICAL_1 *mbase;
+  int mask_kind;
+  index_type mstride;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+  mbase = mask->base_addr;
+
+  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
+    internal_error (NULL, "Funny sized logical array");
+
+  mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
+
+  /* Search for the first occurrence of a true element in mask. */
+  for (j=0; j<extent; j++)
+    {
+      if (*mbase)
+        break;
+      mbase += mstride;
+    }
+
+  if (j == extent)
+    return 0;
+
+  ret = j + 1;
+  src = array->base_addr + j * sstride;
+  maxval = src;
+
+  for (i=j+1; i<=extent; i++)
+    {
+      if (*mbase && compare_fcn (src, maxval, len) < 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+      src += sstride;
+      mbase += mstride;
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_16 sminloc2_16_s1 (gfc_array_s1 * const restrict,
+                               GFC_LOGICAL_4 *mask, gfc_charlen_type);
+export_proto(sminloc2_16_s1);
+
+GFC_INTEGER_16
+sminloc2_16_s1 (gfc_array_s1 * const restrict array,
+                                GFC_LOGICAL_4 *mask, gfc_charlen_type len)
+{
+  if (mask)
+    return minloc2_16_s1 (array, len);
+  else
+    return 0;
+}
+
+#endif
diff --git a/libgfortran/generated/minloc2_16_s4.c b/libgfortran/generated/minloc2_16_s4.c
new file mode 100644 (file)
index 0000000..4857b08
--- /dev/null
@@ -0,0 +1,155 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_16)
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, int n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern GFC_INTEGER_16 minloc2_16_s4 (gfc_array_s4 * const restrict, int);
+export_proto(minloc2_16_s4);
+
+GFC_INTEGER_16
+minloc2_16_s4 (gfc_array_s4 * const restrict array, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_4 *src;
+  const GFC_INTEGER_4 *maxval;
+  index_type i;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  ret = 1;
+  src = array->base_addr;
+  maxval = src;
+  for (i=2; i<=extent; i++)
+    {
+      src += sstride;
+      if (compare_fcn (src, maxval, len) < 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_16 mminloc2_16_s4 (gfc_array_s4 * const restrict,
+                               gfc_array_l1 *const restrict mask, int);
+export_proto(mminloc2_16_s4);
+
+GFC_INTEGER_16
+mminloc2_16_s4 (gfc_array_s4 * const restrict array,
+                                gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_4 *src;
+  const GFC_INTEGER_4 *maxval;
+  index_type i, j;
+  GFC_LOGICAL_1 *mbase;
+  int mask_kind;
+  index_type mstride;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+  mbase = mask->base_addr;
+
+  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
+    internal_error (NULL, "Funny sized logical array");
+
+  mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
+
+  /* Search for the first occurrence of a true element in mask. */
+  for (j=0; j<extent; j++)
+    {
+      if (*mbase)
+        break;
+      mbase += mstride;
+    }
+
+  if (j == extent)
+    return 0;
+
+  ret = j + 1;
+  src = array->base_addr + j * sstride;
+  maxval = src;
+
+  for (i=j+1; i<=extent; i++)
+    {
+      if (*mbase && compare_fcn (src, maxval, len) < 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+      src += sstride;
+      mbase += mstride;
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_16 sminloc2_16_s4 (gfc_array_s4 * const restrict,
+                               GFC_LOGICAL_4 *mask, gfc_charlen_type);
+export_proto(sminloc2_16_s4);
+
+GFC_INTEGER_16
+sminloc2_16_s4 (gfc_array_s4 * const restrict array,
+                                GFC_LOGICAL_4 *mask, gfc_charlen_type len)
+{
+  if (mask)
+    return minloc2_16_s4 (array, len);
+  else
+    return 0;
+}
+
+#endif
diff --git a/libgfortran/generated/minloc2_4_s1.c b/libgfortran/generated/minloc2_4_s1.c
new file mode 100644 (file)
index 0000000..2fd526d
--- /dev/null
@@ -0,0 +1,155 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_4)
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, int n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern GFC_INTEGER_4 minloc2_4_s1 (gfc_array_s1 * const restrict, int);
+export_proto(minloc2_4_s1);
+
+GFC_INTEGER_4
+minloc2_4_s1 (gfc_array_s1 * const restrict array, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_1 *src;
+  const GFC_INTEGER_1 *maxval;
+  index_type i;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  ret = 1;
+  src = array->base_addr;
+  maxval = src;
+  for (i=2; i<=extent; i++)
+    {
+      src += sstride;
+      if (compare_fcn (src, maxval, len) < 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_4 mminloc2_4_s1 (gfc_array_s1 * const restrict,
+                               gfc_array_l1 *const restrict mask, int);
+export_proto(mminloc2_4_s1);
+
+GFC_INTEGER_4
+mminloc2_4_s1 (gfc_array_s1 * const restrict array,
+                                gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_1 *src;
+  const GFC_INTEGER_1 *maxval;
+  index_type i, j;
+  GFC_LOGICAL_1 *mbase;
+  int mask_kind;
+  index_type mstride;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+  mbase = mask->base_addr;
+
+  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
+    internal_error (NULL, "Funny sized logical array");
+
+  mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
+
+  /* Search for the first occurrence of a true element in mask. */
+  for (j=0; j<extent; j++)
+    {
+      if (*mbase)
+        break;
+      mbase += mstride;
+    }
+
+  if (j == extent)
+    return 0;
+
+  ret = j + 1;
+  src = array->base_addr + j * sstride;
+  maxval = src;
+
+  for (i=j+1; i<=extent; i++)
+    {
+      if (*mbase && compare_fcn (src, maxval, len) < 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+      src += sstride;
+      mbase += mstride;
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_4 sminloc2_4_s1 (gfc_array_s1 * const restrict,
+                               GFC_LOGICAL_4 *mask, gfc_charlen_type);
+export_proto(sminloc2_4_s1);
+
+GFC_INTEGER_4
+sminloc2_4_s1 (gfc_array_s1 * const restrict array,
+                                GFC_LOGICAL_4 *mask, gfc_charlen_type len)
+{
+  if (mask)
+    return minloc2_4_s1 (array, len);
+  else
+    return 0;
+}
+
+#endif
diff --git a/libgfortran/generated/minloc2_4_s4.c b/libgfortran/generated/minloc2_4_s4.c
new file mode 100644 (file)
index 0000000..ad85d26
--- /dev/null
@@ -0,0 +1,155 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_4)
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, int n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern GFC_INTEGER_4 minloc2_4_s4 (gfc_array_s4 * const restrict, int);
+export_proto(minloc2_4_s4);
+
+GFC_INTEGER_4
+minloc2_4_s4 (gfc_array_s4 * const restrict array, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_4 *src;
+  const GFC_INTEGER_4 *maxval;
+  index_type i;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  ret = 1;
+  src = array->base_addr;
+  maxval = src;
+  for (i=2; i<=extent; i++)
+    {
+      src += sstride;
+      if (compare_fcn (src, maxval, len) < 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_4 mminloc2_4_s4 (gfc_array_s4 * const restrict,
+                               gfc_array_l1 *const restrict mask, int);
+export_proto(mminloc2_4_s4);
+
+GFC_INTEGER_4
+mminloc2_4_s4 (gfc_array_s4 * const restrict array,
+                                gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_4 *src;
+  const GFC_INTEGER_4 *maxval;
+  index_type i, j;
+  GFC_LOGICAL_1 *mbase;
+  int mask_kind;
+  index_type mstride;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+  mbase = mask->base_addr;
+
+  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
+    internal_error (NULL, "Funny sized logical array");
+
+  mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
+
+  /* Search for the first occurrence of a true element in mask. */
+  for (j=0; j<extent; j++)
+    {
+      if (*mbase)
+        break;
+      mbase += mstride;
+    }
+
+  if (j == extent)
+    return 0;
+
+  ret = j + 1;
+  src = array->base_addr + j * sstride;
+  maxval = src;
+
+  for (i=j+1; i<=extent; i++)
+    {
+      if (*mbase && compare_fcn (src, maxval, len) < 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+      src += sstride;
+      mbase += mstride;
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_4 sminloc2_4_s4 (gfc_array_s4 * const restrict,
+                               GFC_LOGICAL_4 *mask, gfc_charlen_type);
+export_proto(sminloc2_4_s4);
+
+GFC_INTEGER_4
+sminloc2_4_s4 (gfc_array_s4 * const restrict array,
+                                GFC_LOGICAL_4 *mask, gfc_charlen_type len)
+{
+  if (mask)
+    return minloc2_4_s4 (array, len);
+  else
+    return 0;
+}
+
+#endif
diff --git a/libgfortran/generated/minloc2_8_s1.c b/libgfortran/generated/minloc2_8_s1.c
new file mode 100644 (file)
index 0000000..0b594d6
--- /dev/null
@@ -0,0 +1,155 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+
+#if defined (HAVE_GFC_INTEGER_1) && defined (HAVE_GFC_INTEGER_8)
+
+static inline int
+compare_fcn (const GFC_INTEGER_1 *a, const GFC_INTEGER_1 *b, int n)
+{
+  if (sizeof (GFC_INTEGER_1) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern GFC_INTEGER_8 minloc2_8_s1 (gfc_array_s1 * const restrict, int);
+export_proto(minloc2_8_s1);
+
+GFC_INTEGER_8
+minloc2_8_s1 (gfc_array_s1 * const restrict array, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_1 *src;
+  const GFC_INTEGER_1 *maxval;
+  index_type i;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  ret = 1;
+  src = array->base_addr;
+  maxval = src;
+  for (i=2; i<=extent; i++)
+    {
+      src += sstride;
+      if (compare_fcn (src, maxval, len) < 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_8 mminloc2_8_s1 (gfc_array_s1 * const restrict,
+                               gfc_array_l1 *const restrict mask, int);
+export_proto(mminloc2_8_s1);
+
+GFC_INTEGER_8
+mminloc2_8_s1 (gfc_array_s1 * const restrict array,
+                                gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_1 *src;
+  const GFC_INTEGER_1 *maxval;
+  index_type i, j;
+  GFC_LOGICAL_1 *mbase;
+  int mask_kind;
+  index_type mstride;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+  mbase = mask->base_addr;
+
+  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
+    internal_error (NULL, "Funny sized logical array");
+
+  mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
+
+  /* Search for the first occurrence of a true element in mask. */
+  for (j=0; j<extent; j++)
+    {
+      if (*mbase)
+        break;
+      mbase += mstride;
+    }
+
+  if (j == extent)
+    return 0;
+
+  ret = j + 1;
+  src = array->base_addr + j * sstride;
+  maxval = src;
+
+  for (i=j+1; i<=extent; i++)
+    {
+      if (*mbase && compare_fcn (src, maxval, len) < 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+      src += sstride;
+      mbase += mstride;
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_8 sminloc2_8_s1 (gfc_array_s1 * const restrict,
+                               GFC_LOGICAL_4 *mask, gfc_charlen_type);
+export_proto(sminloc2_8_s1);
+
+GFC_INTEGER_8
+sminloc2_8_s1 (gfc_array_s1 * const restrict array,
+                                GFC_LOGICAL_4 *mask, gfc_charlen_type len)
+{
+  if (mask)
+    return minloc2_8_s1 (array, len);
+  else
+    return 0;
+}
+
+#endif
diff --git a/libgfortran/generated/minloc2_8_s4.c b/libgfortran/generated/minloc2_8_s4.c
new file mode 100644 (file)
index 0000000..71a55fc
--- /dev/null
@@ -0,0 +1,155 @@
+/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+
+#if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_8)
+
+static inline int
+compare_fcn (const GFC_INTEGER_4 *a, const GFC_INTEGER_4 *b, int n)
+{
+  if (sizeof (GFC_INTEGER_4) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern GFC_INTEGER_8 minloc2_8_s4 (gfc_array_s4 * const restrict, int);
+export_proto(minloc2_8_s4);
+
+GFC_INTEGER_8
+minloc2_8_s4 (gfc_array_s4 * const restrict array, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_4 *src;
+  const GFC_INTEGER_4 *maxval;
+  index_type i;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  ret = 1;
+  src = array->base_addr;
+  maxval = src;
+  for (i=2; i<=extent; i++)
+    {
+      src += sstride;
+      if (compare_fcn (src, maxval, len) < 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_8 mminloc2_8_s4 (gfc_array_s4 * const restrict,
+                               gfc_array_l1 *const restrict mask, int);
+export_proto(mminloc2_8_s4);
+
+GFC_INTEGER_8
+mminloc2_8_s4 (gfc_array_s4 * const restrict array,
+                                gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const GFC_INTEGER_4 *src;
+  const GFC_INTEGER_4 *maxval;
+  index_type i, j;
+  GFC_LOGICAL_1 *mbase;
+  int mask_kind;
+  index_type mstride;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+  mbase = mask->base_addr;
+
+  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
+    internal_error (NULL, "Funny sized logical array");
+
+  mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
+
+  /* Search for the first occurrence of a true element in mask. */
+  for (j=0; j<extent; j++)
+    {
+      if (*mbase)
+        break;
+      mbase += mstride;
+    }
+
+  if (j == extent)
+    return 0;
+
+  ret = j + 1;
+  src = array->base_addr + j * sstride;
+  maxval = src;
+
+  for (i=j+1; i<=extent; i++)
+    {
+      if (*mbase && compare_fcn (src, maxval, len) < 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+      src += sstride;
+      mbase += mstride;
+    }
+  return ret;
+}
+
+extern GFC_INTEGER_8 sminloc2_8_s4 (gfc_array_s4 * const restrict,
+                               GFC_LOGICAL_4 *mask, gfc_charlen_type);
+export_proto(sminloc2_8_s4);
+
+GFC_INTEGER_8
+sminloc2_8_s4 (gfc_array_s4 * const restrict array,
+                                GFC_LOGICAL_4 *mask, gfc_charlen_type len)
+{
+  if (mask)
+    return minloc2_8_s4 (array, len);
+  else
+    return 0;
+}
+
+#endif
index 460bfe4965dbfd1248ea0ddfb381d9956cabbeda..4f8b4f3e298069d97401faf9621834889a32a298 100644 (file)
@@ -1,4 +1,4 @@
-GFORTRAN_7 {
+GFORTRAN_8 {
   global:
     __ieee_arithmetic_MOD_ieee_class_10;
     __ieee_arithmetic_MOD_ieee_class_16;
@@ -357,6 +357,8 @@ GFORTRAN_7 {
     _gfortran_maxloc0_16_r16;
     _gfortran_maxloc0_16_r4;
     _gfortran_maxloc0_16_r8;
+    _gfortran_maxloc0_16_s1;
+    _gfortran_maxloc0_16_s4;
     _gfortran_maxloc0_4_i16;
     _gfortran_maxloc0_4_i1;
     _gfortran_maxloc0_4_i2;
@@ -366,6 +368,8 @@ GFORTRAN_7 {
     _gfortran_maxloc0_4_r16;
     _gfortran_maxloc0_4_r4;
     _gfortran_maxloc0_4_r8;
+    _gfortran_maxloc0_4_s1;
+    _gfortran_maxloc0_4_s4;
     _gfortran_maxloc0_8_i16;
     _gfortran_maxloc0_8_i1;
     _gfortran_maxloc0_8_i2;
@@ -375,6 +379,8 @@ GFORTRAN_7 {
     _gfortran_maxloc0_8_r16;
     _gfortran_maxloc0_8_r4;
     _gfortran_maxloc0_8_r8;
+    _gfortran_maxloc0_8_s1;
+    _gfortran_maxloc0_8_s4;
     _gfortran_maxloc1_16_i16;
     _gfortran_maxloc1_16_i1;
     _gfortran_maxloc1_16_i2;
@@ -384,6 +390,8 @@ GFORTRAN_7 {
     _gfortran_maxloc1_16_r16;
     _gfortran_maxloc1_16_r4;
     _gfortran_maxloc1_16_r8;
+    _gfortran_maxloc1_16_s1;
+    _gfortran_maxloc1_16_s4;
     _gfortran_maxloc1_4_i16;
     _gfortran_maxloc1_4_i1;
     _gfortran_maxloc1_4_i2;
@@ -393,6 +401,8 @@ GFORTRAN_7 {
     _gfortran_maxloc1_4_r16;
     _gfortran_maxloc1_4_r4;
     _gfortran_maxloc1_4_r8;
+    _gfortran_maxloc1_4_s1;
+    _gfortran_maxloc1_4_s4;
     _gfortran_maxloc1_8_i16;
     _gfortran_maxloc1_8_i1;
     _gfortran_maxloc1_8_i2;
@@ -402,6 +412,14 @@ GFORTRAN_7 {
     _gfortran_maxloc1_8_r16;
     _gfortran_maxloc1_8_r4;
     _gfortran_maxloc1_8_r8;
+    _gfortran_maxloc1_8_s1;
+    _gfortran_maxloc1_8_s4;
+    _gfortran_maxloc2_16_s1;
+    _gfortran_maxloc2_16_s4;
+    _gfortran_maxloc2_4_s1;
+    _gfortran_maxloc2_4_s4;
+    _gfortran_maxloc2_8_s1;
+    _gfortran_maxloc2_8_s4;
     _gfortran_maxval_i16;
     _gfortran_maxval_i1;
     _gfortran_maxval_i2;
@@ -432,6 +450,8 @@ GFORTRAN_7 {
     _gfortran_minloc0_16_r16;
     _gfortran_minloc0_16_r4;
     _gfortran_minloc0_16_r8;
+    _gfortran_minloc0_16_s1;
+    _gfortran_minloc0_16_s4;
     _gfortran_minloc0_4_i16;
     _gfortran_minloc0_4_i1;
     _gfortran_minloc0_4_i2;
@@ -441,6 +461,8 @@ GFORTRAN_7 {
     _gfortran_minloc0_4_r16;
     _gfortran_minloc0_4_r4;
     _gfortran_minloc0_4_r8;
+    _gfortran_minloc0_4_s1;
+    _gfortran_minloc0_4_s4;
     _gfortran_minloc0_8_i16;
     _gfortran_minloc0_8_i1;
     _gfortran_minloc0_8_i2;
@@ -450,6 +472,8 @@ GFORTRAN_7 {
     _gfortran_minloc0_8_r16;
     _gfortran_minloc0_8_r4;
     _gfortran_minloc0_8_r8;
+    _gfortran_minloc0_8_s1;
+    _gfortran_minloc0_8_s4;
     _gfortran_minloc1_16_i16;
     _gfortran_minloc1_16_i1;
     _gfortran_minloc1_16_i2;
@@ -459,6 +483,8 @@ GFORTRAN_7 {
     _gfortran_minloc1_16_r16;
     _gfortran_minloc1_16_r4;
     _gfortran_minloc1_16_r8;
+    _gfortran_minloc1_16_s1;
+    _gfortran_minloc1_16_s4;
     _gfortran_minloc1_4_i16;
     _gfortran_minloc1_4_i1;
     _gfortran_minloc1_4_i2;
@@ -468,6 +494,8 @@ GFORTRAN_7 {
     _gfortran_minloc1_4_r16;
     _gfortran_minloc1_4_r4;
     _gfortran_minloc1_4_r8;
+    _gfortran_minloc1_4_s1;
+    _gfortran_minloc1_4_s4;
     _gfortran_minloc1_8_i16;
     _gfortran_minloc1_8_i1;
     _gfortran_minloc1_8_i2;
@@ -477,6 +505,14 @@ GFORTRAN_7 {
     _gfortran_minloc1_8_r16;
     _gfortran_minloc1_8_r4;
     _gfortran_minloc1_8_r8;
+    _gfortran_minloc1_8_s1;
+    _gfortran_minloc1_8_s4;
+    _gfortran_minloc2_16_s1;
+    _gfortran_minloc2_16_s4;
+    _gfortran_minloc2_4_s1;
+    _gfortran_minloc2_4_s4;
+    _gfortran_minloc2_8_s1;
+    _gfortran_minloc2_8_s4;
     _gfortran_minval_i16;
     _gfortran_minval_i1;
     _gfortran_minval_i2;
@@ -500,6 +536,8 @@ GFORTRAN_7 {
     _gfortran_mmaxloc0_16_r16;
     _gfortran_mmaxloc0_16_r4;
     _gfortran_mmaxloc0_16_r8;
+    _gfortran_mmaxloc0_16_s1;
+    _gfortran_mmaxloc0_16_s4;
     _gfortran_mmaxloc0_4_i16;
     _gfortran_mmaxloc0_4_i1;
     _gfortran_mmaxloc0_4_i2;
@@ -509,6 +547,8 @@ GFORTRAN_7 {
     _gfortran_mmaxloc0_4_r16;
     _gfortran_mmaxloc0_4_r4;
     _gfortran_mmaxloc0_4_r8;
+    _gfortran_mmaxloc0_4_s1;
+    _gfortran_mmaxloc0_4_s4;
     _gfortran_mmaxloc0_8_i16;
     _gfortran_mmaxloc0_8_i1;
     _gfortran_mmaxloc0_8_i2;
@@ -518,6 +558,8 @@ GFORTRAN_7 {
     _gfortran_mmaxloc0_8_r16;
     _gfortran_mmaxloc0_8_r4;
     _gfortran_mmaxloc0_8_r8;
+    _gfortran_mmaxloc0_8_s1;
+    _gfortran_mmaxloc0_8_s4;
     _gfortran_mmaxloc1_16_i16;
     _gfortran_mmaxloc1_16_i1;
     _gfortran_mmaxloc1_16_i2;
@@ -527,6 +569,8 @@ GFORTRAN_7 {
     _gfortran_mmaxloc1_16_r16;
     _gfortran_mmaxloc1_16_r4;
     _gfortran_mmaxloc1_16_r8;
+    _gfortran_mmaxloc1_16_s1;
+    _gfortran_mmaxloc1_16_s4;
     _gfortran_mmaxloc1_4_i16;
     _gfortran_mmaxloc1_4_i1;
     _gfortran_mmaxloc1_4_i2;
@@ -536,6 +580,8 @@ GFORTRAN_7 {
     _gfortran_mmaxloc1_4_r16;
     _gfortran_mmaxloc1_4_r4;
     _gfortran_mmaxloc1_4_r8;
+    _gfortran_mmaxloc1_4_s1;
+    _gfortran_mmaxloc1_4_s4;
     _gfortran_mmaxloc1_8_i16;
     _gfortran_mmaxloc1_8_i1;
     _gfortran_mmaxloc1_8_i2;
@@ -545,6 +591,14 @@ GFORTRAN_7 {
     _gfortran_mmaxloc1_8_r16;
     _gfortran_mmaxloc1_8_r4;
     _gfortran_mmaxloc1_8_r8;
+    _gfortran_mmaxloc1_8_s1;
+    _gfortran_mmaxloc1_8_s4;
+    _gfortran_mmaxloc2_16_s1;
+    _gfortran_mmaxloc2_16_s4;
+    _gfortran_mmaxloc2_4_s1;
+    _gfortran_mmaxloc2_4_s4;
+    _gfortran_mmaxloc2_8_s1;
+    _gfortran_mmaxloc2_8_s4;
     _gfortran_mmaxval_i16;
     _gfortran_mmaxval_i1;
     _gfortran_mmaxval_i2;
@@ -563,6 +617,8 @@ GFORTRAN_7 {
     _gfortran_mminloc0_16_r16;
     _gfortran_mminloc0_16_r4;
     _gfortran_mminloc0_16_r8;
+    _gfortran_mminloc0_16_s1;
+    _gfortran_mminloc0_16_s4;
     _gfortran_mminloc0_4_i16;
     _gfortran_mminloc0_4_i1;
     _gfortran_mminloc0_4_i2;
@@ -572,6 +628,8 @@ GFORTRAN_7 {
     _gfortran_mminloc0_4_r16;
     _gfortran_mminloc0_4_r4;
     _gfortran_mminloc0_4_r8;
+    _gfortran_mminloc0_4_s1;
+    _gfortran_mminloc0_4_s4;
     _gfortran_mminloc0_8_i16;
     _gfortran_mminloc0_8_i1;
     _gfortran_mminloc0_8_i2;
@@ -581,6 +639,8 @@ GFORTRAN_7 {
     _gfortran_mminloc0_8_r16;
     _gfortran_mminloc0_8_r4;
     _gfortran_mminloc0_8_r8;
+    _gfortran_mminloc0_8_s1;
+    _gfortran_mminloc0_8_s4;
     _gfortran_mminloc1_16_i16;
     _gfortran_mminloc1_16_i1;
     _gfortran_mminloc1_16_i2;
@@ -590,6 +650,8 @@ GFORTRAN_7 {
     _gfortran_mminloc1_16_r16;
     _gfortran_mminloc1_16_r4;
     _gfortran_mminloc1_16_r8;
+    _gfortran_mminloc1_16_s1;
+    _gfortran_mminloc1_16_s4;
     _gfortran_mminloc1_4_i16;
     _gfortran_mminloc1_4_i1;
     _gfortran_mminloc1_4_i2;
@@ -599,6 +661,8 @@ GFORTRAN_7 {
     _gfortran_mminloc1_4_r16;
     _gfortran_mminloc1_4_r4;
     _gfortran_mminloc1_4_r8;
+    _gfortran_mminloc1_4_s1;
+    _gfortran_mminloc1_4_s4;
     _gfortran_mminloc1_8_i16;
     _gfortran_mminloc1_8_i1;
     _gfortran_mminloc1_8_i2;
@@ -608,6 +672,14 @@ GFORTRAN_7 {
     _gfortran_mminloc1_8_r16;
     _gfortran_mminloc1_8_r4;
     _gfortran_mminloc1_8_r8;
+    _gfortran_mminloc1_8_s1;
+    _gfortran_mminloc1_8_s4;
+    _gfortran_mminloc2_16_s1;
+    _gfortran_mminloc2_16_s4;
+    _gfortran_mminloc2_4_s1;
+    _gfortran_mminloc2_4_s4;
+    _gfortran_mminloc2_8_s1;
+    _gfortran_mminloc2_8_s4;
     _gfortran_mminval_i16;
     _gfortran_mminval_i1;
     _gfortran_mminval_i2;
@@ -792,6 +864,8 @@ GFORTRAN_7 {
     _gfortran_smaxloc0_16_r16;
     _gfortran_smaxloc0_16_r4;
     _gfortran_smaxloc0_16_r8;
+    _gfortran_smaxloc0_16_s1;
+    _gfortran_smaxloc0_16_s4;
     _gfortran_smaxloc0_4_i16;
     _gfortran_smaxloc0_4_i1;
     _gfortran_smaxloc0_4_i2;
@@ -801,6 +875,8 @@ GFORTRAN_7 {
     _gfortran_smaxloc0_4_r16;
     _gfortran_smaxloc0_4_r4;
     _gfortran_smaxloc0_4_r8;
+    _gfortran_smaxloc0_4_s1;
+    _gfortran_smaxloc0_4_s4;
     _gfortran_smaxloc0_8_i16;
     _gfortran_smaxloc0_8_i1;
     _gfortran_smaxloc0_8_i2;
@@ -810,6 +886,8 @@ GFORTRAN_7 {
     _gfortran_smaxloc0_8_r16;
     _gfortran_smaxloc0_8_r4;
     _gfortran_smaxloc0_8_r8;
+    _gfortran_smaxloc0_8_s1;
+    _gfortran_smaxloc0_8_s4;
     _gfortran_smaxloc1_16_i16;
     _gfortran_smaxloc1_16_i1;
     _gfortran_smaxloc1_16_i2;
@@ -819,6 +897,8 @@ GFORTRAN_7 {
     _gfortran_smaxloc1_16_r16;
     _gfortran_smaxloc1_16_r4;
     _gfortran_smaxloc1_16_r8;
+    _gfortran_smaxloc1_16_s1;
+    _gfortran_smaxloc1_16_s4;
     _gfortran_smaxloc1_4_i16;
     _gfortran_smaxloc1_4_i1;
     _gfortran_smaxloc1_4_i2;
@@ -828,6 +908,8 @@ GFORTRAN_7 {
     _gfortran_smaxloc1_4_r16;
     _gfortran_smaxloc1_4_r4;
     _gfortran_smaxloc1_4_r8;
+    _gfortran_smaxloc1_4_s1;
+    _gfortran_smaxloc1_4_s4;
     _gfortran_smaxloc1_8_i16;
     _gfortran_smaxloc1_8_i1;
     _gfortran_smaxloc1_8_i2;
@@ -837,6 +919,14 @@ GFORTRAN_7 {
     _gfortran_smaxloc1_8_r16;
     _gfortran_smaxloc1_8_r4;
     _gfortran_smaxloc1_8_r8;
+    _gfortran_smaxloc1_8_s1;
+    _gfortran_smaxloc1_8_s4;
+    _gfortran_smaxloc2_16_s1;
+    _gfortran_smaxloc2_16_s4;
+    _gfortran_smaxloc2_4_s1;
+    _gfortran_smaxloc2_4_s4;
+    _gfortran_smaxloc2_8_s1;
+    _gfortran_smaxloc2_8_s4;
     _gfortran_smaxval_i16;
     _gfortran_smaxval_i1;
     _gfortran_smaxval_i2;
@@ -855,6 +945,8 @@ GFORTRAN_7 {
     _gfortran_sminloc0_16_r16;
     _gfortran_sminloc0_16_r4;
     _gfortran_sminloc0_16_r8;
+    _gfortran_sminloc0_16_s1;
+    _gfortran_sminloc0_16_s4;
     _gfortran_sminloc0_4_i16;
     _gfortran_sminloc0_4_i1;
     _gfortran_sminloc0_4_i2;
@@ -864,6 +956,8 @@ GFORTRAN_7 {
     _gfortran_sminloc0_4_r16;
     _gfortran_sminloc0_4_r4;
     _gfortran_sminloc0_4_r8;
+    _gfortran_sminloc0_4_s1;
+    _gfortran_sminloc0_4_s4;
     _gfortran_sminloc0_8_i16;
     _gfortran_sminloc0_8_i1;
     _gfortran_sminloc0_8_i2;
@@ -873,6 +967,8 @@ GFORTRAN_7 {
     _gfortran_sminloc0_8_r16;
     _gfortran_sminloc0_8_r4;
     _gfortran_sminloc0_8_r8;
+    _gfortran_sminloc0_8_s1;
+    _gfortran_sminloc0_8_s4;
     _gfortran_sminloc1_16_i16;
     _gfortran_sminloc1_16_i1;
     _gfortran_sminloc1_16_i2;
@@ -882,6 +978,8 @@ GFORTRAN_7 {
     _gfortran_sminloc1_16_r16;
     _gfortran_sminloc1_16_r4;
     _gfortran_sminloc1_16_r8;
+    _gfortran_sminloc1_16_s1;
+    _gfortran_sminloc1_16_s4;
     _gfortran_sminloc1_4_i16;
     _gfortran_sminloc1_4_i1;
     _gfortran_sminloc1_4_i2;
@@ -891,6 +989,8 @@ GFORTRAN_7 {
     _gfortran_sminloc1_4_r16;
     _gfortran_sminloc1_4_r4;
     _gfortran_sminloc1_4_r8;
+    _gfortran_sminloc1_4_s1;
+    _gfortran_sminloc1_4_s4;
     _gfortran_sminloc1_8_i16;
     _gfortran_sminloc1_8_i1;
     _gfortran_sminloc1_8_i2;
@@ -900,6 +1000,14 @@ GFORTRAN_7 {
     _gfortran_sminloc1_8_r16;
     _gfortran_sminloc1_8_r4;
     _gfortran_sminloc1_8_r8;
+    _gfortran_sminloc1_8_s1;
+    _gfortran_sminloc1_8_s4;
+    _gfortran_sminloc2_16_s1;
+    _gfortran_sminloc2_16_s4;
+    _gfortran_sminloc2_4_s1;
+    _gfortran_sminloc2_4_s4;
+    _gfortran_sminloc2_8_s1;
+    _gfortran_sminloc2_8_s4;
     _gfortran_sminval_i16;
     _gfortran_sminval_i1;
     _gfortran_sminval_i2;
@@ -1196,7 +1304,7 @@ GFORTRAN_7 {
     *;
 };
 
-GFORTRAN_F2C_7 {
+GFORTRAN_F2C_8 {
   global:
     _gfortran_f2c_specific__abs_c4;
     _gfortran_f2c_specific__abs_r4;
@@ -1238,7 +1346,7 @@ GFORTRAN_F2C_7 {
     _gfortran_f2c_specific__tan_r4;
 };
 
-GFORTRAN_C99_7 {
+GFORTRAN_C99_8 {
   global:
     acosf;
     acoshf;
index cdbdd9516875ca39853e17b1080ad436efd5580a..52f4764a30711d89c283d63ec34a32713cd2cf03 100644 (file)
@@ -376,7 +376,8 @@ typedef GFC_ARRAY_DESCRIPTOR (GFC_MAX_DIMENSIONS, GFC_LOGICAL_8) gfc_array_l8;
 #ifdef HAVE_GFC_LOGICAL_16
 typedef GFC_ARRAY_DESCRIPTOR (GFC_MAX_DIMENSIONS, GFC_LOGICAL_16) gfc_array_l16;
 #endif
-
+typedef gfc_array_i1 gfc_array_s1;
+typedef gfc_array_i4 gfc_array_s4;
 
 #define GFC_DESCRIPTOR_RANK(desc) ((desc)->dtype & GFC_DTYPE_RANK_MASK)
 #define GFC_DESCRIPTOR_TYPE(desc) (((desc)->dtype & GFC_DTYPE_TYPE_MASK) \
diff --git a/libgfortran/m4/iforeach-s.m4 b/libgfortran/m4/iforeach-s.m4
new file mode 100644 (file)
index 0000000..39868dd
--- /dev/null
@@ -0,0 +1,288 @@
+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 Runtime Library (libgfortran)
+dnl Distributed under the GNU GPL with exception.  See COPYING for details.
+define(START_FOREACH_FUNCTION,
+`static inline int
+compare_fcn (const atype_name *a, const atype_name *b, gfc_charlen_type n)
+{
+  if (sizeof ('atype_name`) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+
+}
+
+extern void name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
+       atype * const restrict array, gfc_charlen_type len);
+export_proto(name`'rtype_qual`_'atype_code);
+
+void
+name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
+       atype * const restrict array, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  const atype_name *base;
+  rtype_name * restrict dest;
+  index_type rank;
+  index_type n;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (rtype_name));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                               "u_name");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 1;
+  {
+')dnl
+define(START_FOREACH_BLOCK,
+`  while (base)
+    {
+      do
+       {
+         /* Implementation start.  */
+')dnl
+define(FINISH_FOREACH_FUNCTION,
+`        /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}')dnl
+define(START_MASKED_FOREACH_FUNCTION,
+`
+extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict, 
+       atype * const restrict, gfc_array_l1 * const restrict, gfc_charlen_type len);
+export_proto(`m'name`'rtype_qual`_'atype_code);
+
+void
+`m'name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
+       atype * const restrict array,
+       gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type count[GFC_MAX_DIMENSIONS];
+  index_type extent[GFC_MAX_DIMENSIONS];
+  index_type sstride[GFC_MAX_DIMENSIONS];
+  index_type mstride[GFC_MAX_DIMENSIONS];
+  index_type dstride;
+  rtype_name *dest;
+  const atype_name *base;
+  GFC_LOGICAL_1 *mbase;
+  int rank;
+  index_type n;
+  int mask_kind;
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank - 1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (rtype_name));
+    }
+  else
+    {
+      if (unlikely (compile_options.bounds_check))
+       {
+
+         bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                                 "u_name");
+         bounds_equal_extents ((array_t *) mask, (array_t *) array,
+                                 "MASK argument", "u_name");
+       }
+    }
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+
+  mbase = mask->base_addr;
+
+  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");
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * len;
+      mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+      count[n] = 0;
+      if (extent[n] <= 0)
+       {
+         /* Set the return value.  */
+         for (n = 0; n < rank; n++)
+           dest[n * dstride] = 0;
+         return;
+       }
+    }
+
+  base = array->base_addr;
+
+  /* Initialize the return value.  */
+  for (n = 0; n < rank; n++)
+    dest[n * dstride] = 0;
+  {
+')dnl
+define(START_MASKED_FOREACH_BLOCK, `START_FOREACH_BLOCK')dnl
+define(FINISH_MASKED_FOREACH_FUNCTION,
+`        /* Implementation end.  */
+         /* Advance to the next element.  */
+         base += sstride[0];
+         mbase += mstride[0];
+       }
+      while (++count[0] != extent[0]);
+      n = 0;
+      do
+       {
+         /* 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];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             base = NULL;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             mbase += mstride[n];
+           }
+       }
+      while (count[n] == extent[n]);
+    }
+  }
+}')dnl
+define(FOREACH_FUNCTION,
+`START_FOREACH_FUNCTION
+$1
+START_FOREACH_BLOCK
+$2
+FINISH_FOREACH_FUNCTION')dnl
+define(MASKED_FOREACH_FUNCTION,
+`START_MASKED_FOREACH_FUNCTION
+$1
+START_MASKED_FOREACH_BLOCK
+$2
+FINISH_MASKED_FOREACH_FUNCTION')dnl
+define(SCALAR_FOREACH_FUNCTION,
+`
+extern void `s'name`'rtype_qual`_'atype_code (rtype * const restrict, 
+       atype * const restrict, GFC_LOGICAL_4 *, gfc_charlen_type len);
+export_proto(`s'name`'rtype_qual`_'atype_code);
+
+void
+`s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray, 
+       atype * const restrict array,
+       GFC_LOGICAL_4 * mask, gfc_charlen_type len)
+{
+  index_type rank;
+  index_type dstride;
+  index_type n;
+  rtype_name *dest;
+
+  if (*mask)
+    {
+      name`'rtype_qual`_'atype_code (retarray, array, len);
+      return;
+    }
+
+  rank = GFC_DESCRIPTOR_RANK (array);
+
+  if (rank <= 0)
+    runtime_error ("Rank of array needs to be > 0");
+
+  if (retarray->base_addr == NULL)
+    {
+      GFC_DIMENSION_SET(retarray->dim[0], 0, rank-1, 1);
+      retarray->dtype = (retarray->dtype & ~GFC_DTYPE_RANK_MASK) | 1;
+      retarray->offset = 0;
+      retarray->base_addr = xmallocarray (rank, sizeof (rtype_name));
+    }
+  else if (unlikely (compile_options.bounds_check))
+    {
+       bounds_iforeach_return ((array_t *) retarray, (array_t *) array,
+                              "u_name");
+    }
+
+  dstride = GFC_DESCRIPTOR_STRIDE(retarray,0);
+  dest = retarray->base_addr;
+  for (n = 0; n<rank; n++)
+    dest[n * dstride] = $1 ;
+}')dnl
diff --git a/libgfortran/m4/ifunction-s.m4 b/libgfortran/m4/ifunction-s.m4
new file mode 100644 (file)
index 0000000..93ca694
--- /dev/null
@@ -0,0 +1,530 @@
+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 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.
+dnl The variables base, delta, and len describe the input section.
+dnl For masked section the mask is described by mbase and mdelta.
+dnl These should not be modified. The result should be stored in *dest.
+dnl The names count, extent, sstride, dstride, base, dest, rank, dim
+dnl retarray, array, pdim and mstride should not be used.
+dnl The variable n is declared as index_type and may be used.
+dnl Other variable declarations may be placed at the start of the code,
+dnl The types of the array parameter and the return value are
+dnl atype_name and rtype_name respectively.
+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,
+`#include <string.h>
+
+static inline int
+compare_fcn (const atype_name *a, const atype_name *b, gfc_charlen_type n)
+{
+  if (sizeof ('atype_name`) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern void name`'rtype_qual`_'atype_code (rtype * const restrict, 
+       atype * const restrict, const index_type * const restrict,
+       gfc_charlen_type);
+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, gfc_charlen_type string_len)
+{
+  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.  */
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+  dim = (*pdim) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in u_name intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len < 0)
+    len = 0;
+  delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+  for (n = dim; n < rank; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
+
+      if (extent[n] < 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
+
+      retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
+      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] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  base = array->base_addr;
+  dest = retarray->base_addr;
+
+  continue_loop = 1;
+  while (continue_loop)
+    {
+      const atype_name * restrict src;
+      rtype_name result;
+      src = base;
+      {
+')dnl
+define(START_ARRAY_BLOCK,
+`      if (len <= 0)
+         *dest = '$1`;
+       else
+         {
+           for (n = 0; n < len; n++, src += delta)
+             {
+')dnl
+define(FINISH_ARRAY_FUNCTION,
+`            }
+           '$1`
+           *dest = result;
+         }
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[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.  */
+         base -= sstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             continue_loop = 0;
+             break;
+           }
+         else
+           {
+             count[n]++;
+             base += sstride[n];
+             dest += dstride[n];
+           }
+       }
+    }
+}')dnl
+define(START_MASKED_ARRAY_FUNCTION,
+`
+extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict, 
+       atype * const restrict, const index_type * const restrict,
+       gfc_array_l1 * const restrict, gfc_charlen_type);
+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, gfc_charlen_type string_len)
+{
+  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;
+  index_type rank;
+  index_type 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;
+
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in u_name intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  len = GFC_DESCRIPTOR_EXTENT(array,dim);
+  if (len <= 0)
+    return;
+
+  mbase = mask->base_addr;
+
+  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) * string_len;
+  mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
+
+  for (n = 0; n < dim; n++)
+    {
+      sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
+      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] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
+      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->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
+
+    }
+  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] = GFC_DESCRIPTOR_STRIDE(retarray,n);
+      if (extent[n] <= 0)
+       return;
+    }
+
+  dest = retarray->base_addr;
+  base = array->base_addr;
+
+  while (base)
+    {
+      const atype_name * restrict src;
+      const GFC_LOGICAL_1 * restrict msrc;
+      rtype_name result;
+      src = base;
+      msrc = mbase;
+      {
+')dnl
+define(START_MASKED_ARRAY_BLOCK,
+`      for (n = 0; n < len; n++, src += delta, msrc += mdelta)
+         {
+')dnl
+define(FINISH_MASKED_ARRAY_FUNCTION,
+`        }
+       *dest = result;
+      }
+      /* Advance to the next element.  */
+      count[0]++;
+      base += sstride[0];
+      mbase += mstride[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.  */
+         base -= sstride[n] * extent[n];
+         mbase -= mstride[n] * extent[n];
+         dest -= dstride[n] * extent[n];
+         n++;
+         if (n >= rank)
+           {
+             /* Break out of the loop.  */
+             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 *, gfc_charlen_type);
+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, gfc_charlen_type string_len)
+{
+  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, string_len);
+      return;
+    }
+  /* Make dim zero based to avoid confusion.  */
+  dim = (*pdim) - 1;
+  rank = GFC_DESCRIPTOR_RANK (array) - 1;
+
+  if (unlikely (dim < 0 || dim > rank))
+    {
+      runtime_error ("Dim argument incorrect in u_name intrinsic: "
+                    "is %ld, should be between 1 and %ld",
+                    (long int) dim + 1, (long int) rank + 1);
+    }
+
+  for (n = 0; n < dim; n++)
+    {
+      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  for (n = dim; n < rank; n++)
+    {
+      extent[n] =
+       GFC_DESCRIPTOR_EXTENT(array,n + 1) * string_len;
+
+      if (extent[n] <= 0)
+       extent[n] = 0;
+    }
+
+  if (retarray->base_addr == 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 = 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->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
+    }
+  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->base_addr;
+
+  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
+$2
+START_ARRAY_BLOCK($1)
+$3
+FINISH_ARRAY_FUNCTION($4)')dnl
+define(MASKED_ARRAY_FUNCTION,
+`START_MASKED_ARRAY_FUNCTION
+$2
+START_MASKED_ARRAY_BLOCK
+$3
+FINISH_MASKED_ARRAY_FUNCTION')dnl
index 91cfd28d5d13da696f2564609839e0846489b01e..7777a0c8c078e525e8ba6fdeefc7351c079f9a4c 100644 (file)
@@ -42,8 +42,8 @@ name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
   int continue_loop;
 
   /* Make dim zero based to avoid confusion.  */
-  dim = (*pdim) - 1;
   rank = GFC_DESCRIPTOR_RANK (array) - 1;
+  dim = (*pdim) - 1;
 
   if (unlikely (dim < 0 || dim > rank))
     {
index 4ff62474107444b56fdc8bf646c0cc63a009205a..4bf2a3010cf627ff7cb77c79d584776a4deb997a 100644 (file)
@@ -4,7 +4,7 @@ dnl This file is part of the GNU Fortran 95 Runtime Library (libgfortran)
 dnl Distributed under the GNU GPL with exception.  See COPYING for details.
 dnl M4 macro file to get type names from filenames
 define(get_typename2, `GFC_$1_$2')dnl
-define(get_typename, `get_typename2(ifelse($1,i,INTEGER,ifelse($1,r,REAL,ifelse($1,l,LOGICAL,ifelse($1,c,COMPLEX,unknown)))),`$2')')dnl
+define(get_typename, `get_typename2(ifelse($1,i,INTEGER,ifelse($1,r,REAL,ifelse($1,l,LOGICAL,ifelse($1,c,COMPLEX,ifelse($1,s,INTEGER,unknown))))),`$2')')dnl
 define(get_arraytype, `gfc_array_$1$2')dnl
 define(define_type, `dnl
 ifelse(regexp($2,`^[0-9]'),-1,`dnl
diff --git a/libgfortran/m4/maxloc0s.m4 b/libgfortran/m4/maxloc0s.m4
new file mode 100644 (file)
index 0000000..96935dc
--- /dev/null
@@ -0,0 +1,61 @@
+`/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>'
+
+include(iparm.m4)dnl
+include(iforeach-s.m4)dnl
+
+`#if defined (HAVE_'atype_name`) && defined (HAVE_'rtype_name`)'
+
+FOREACH_FUNCTION(
+`  const atype_name *maxval;
+   maxval = base;'
+,
+`  if (compare_fcn (base, maxval, len) > 0)
+    {
+      maxval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }')
+
+MASKED_FOREACH_FUNCTION(
+`  const atype_name *maxval;
+
+  maxval = NULL;'
+,
+`  if (*mbase && (maxval == NULL || compare_fcn (base, maxval, len) > 0))
+    {
+      maxval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }')
+
+SCALAR_FOREACH_FUNCTION(`0')
+#endif
diff --git a/libgfortran/m4/maxloc1s.m4 b/libgfortran/m4/maxloc1s.m4
new file mode 100644 (file)
index 0000000..dbb69b4
--- /dev/null
@@ -0,0 +1,65 @@
+`/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"'
+
+include(iparm.m4)dnl
+include(ifunction-s.m4)dnl
+
+`#if defined (HAVE_'atype_name`) && defined (HAVE_'rtype_name`)'
+
+ARRAY_FUNCTION(0,
+`      const atype_name *maxval;
+       maxval = base;
+       result = 1;',
+`              if (compare_fcn (src, maxval, string_len) > 0)
+                 {
+                   maxval = src;
+                   result = (rtype_name)n + 1;
+                 }', `')
+
+MASKED_ARRAY_FUNCTION(0,
+`      const atype_name *maxval;
+       maxval = base;
+       result = 0;',
+`              if (*msrc)
+                     {
+                       maxval = src;
+                       result = (rtype_name)n + 1;
+                       break;
+                     }
+           }
+           for (; n < len; n++, src += delta, msrc += mdelta)
+             {
+               if (*msrc && compare_fcn (src, maxval, string_len) > 0)
+                 {
+                   maxval = src;
+                   result = (rtype_name)n + 1;
+                 }
+             ')
+
+SCALAR_ARRAY_FUNCTION(0)
+
+#endif
diff --git a/libgfortran/m4/maxloc2s.m4 b/libgfortran/m4/maxloc2s.m4
new file mode 100644 (file)
index 0000000..9b2ed74
--- /dev/null
@@ -0,0 +1,157 @@
+`/* Implementation of the MAXLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>'
+include(iparm.m4)dnl
+
+`#if defined (HAVE_'atype_name`) && defined (HAVE_'rtype_name`)
+
+static inline int
+compare_fcn (const 'atype_name` *a, const 'atype_name` *b, int n)
+{
+  if (sizeof ('atype_name`) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern 'rtype_name` 'name`'rtype_qual`_'atype_code` ('atype` * const restrict, int);
+export_proto('name`'rtype_qual`_'atype_code`);
+
+'rtype_name`
+'name`'rtype_qual`_'atype_code` ('atype` * const restrict array, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const 'atype_name` *src;
+  const 'atype_name` *maxval;
+  index_type i;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  ret = 1;
+  src = array->base_addr;
+  maxval = src;
+  for (i=2; i<=extent; i++)
+    {
+      src += sstride;
+      if (compare_fcn (src, maxval, len) > 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+    }
+  return ret;
+}
+
+extern 'rtype_name` m'name`'rtype_qual`_'atype_code` ('atype` * const restrict,
+                               gfc_array_l1 *const restrict mask, gfc_charlen_type);
+export_proto(m'name`'rtype_qual`_'atype_code`);
+
+'rtype_name`
+m'name`'rtype_qual`_'atype_code` ('atype` * const restrict array,
+                                gfc_array_l1 * const restrict mask,
+                                gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const 'atype_name` *src;
+  const 'atype_name` *maxval;
+  index_type i, j;
+  GFC_LOGICAL_1 *mbase;
+  int mask_kind;
+  index_type mstride;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+  mbase = mask->base_addr;
+
+  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
+    internal_error (NULL, "Funny sized logical array");
+
+  mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
+
+  /* Search for the first occurrence of a true element in mask. */
+  for (j=0; j<extent; j++)
+    {
+      if (*mbase)
+        break;
+      mbase += mstride;
+    }
+
+  if (j == extent)
+    return 0;
+
+  ret = j + 1;
+  src = array->base_addr + j * sstride;
+  maxval = src;
+
+  for (i=j+1; i<=extent; i++)
+    {
+      if (*mbase && compare_fcn (src, maxval, len) > 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+      src += sstride;
+      mbase += mstride;
+    }
+  return ret;
+}
+
+extern 'rtype_name` s'name`'rtype_qual`_'atype_code` ('atype` * const restrict,
+                               GFC_LOGICAL_4 *mask, int);
+export_proto(s'name`'rtype_qual`_'atype_code`);
+
+'rtype_name`
+s'name`'rtype_qual`_'atype_code` ('atype` * const restrict array,
+                                GFC_LOGICAL_4 *mask, gfc_charlen_type len)
+{
+  if (mask)
+    return 'name`'rtype_qual`_'atype_code` (array, len);
+  else
+    return 0;
+}
+
+#endif'
diff --git a/libgfortran/m4/minloc0s.m4 b/libgfortran/m4/minloc0s.m4
new file mode 100644 (file)
index 0000000..b907be3
--- /dev/null
@@ -0,0 +1,61 @@
+`/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>'
+
+include(iparm.m4)dnl
+include(iforeach-s.m4)dnl
+
+`#if defined (HAVE_'atype_name`) && defined (HAVE_'rtype_name`)'
+
+FOREACH_FUNCTION(
+`  const atype_name *minval;
+   minval = base;'
+,
+`  if (compare_fcn (base, minval, len) < 0)
+    {
+      minval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }')
+
+MASKED_FOREACH_FUNCTION(
+`  const atype_name *minval;
+
+  minval = NULL;'
+,
+`  if (*mbase && (minval == NULL || compare_fcn (base, minval, len) < 0))
+    {
+      minval = base;
+      for (n = 0; n < rank; n++)
+        dest[n * dstride] = count[n] + 1;
+    }')
+
+SCALAR_FOREACH_FUNCTION(`0')
+#endif
diff --git a/libgfortran/m4/minloc1s.m4 b/libgfortran/m4/minloc1s.m4
new file mode 100644 (file)
index 0000000..d64935a
--- /dev/null
@@ -0,0 +1,65 @@
+`/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"'
+
+include(iparm.m4)dnl
+include(ifunction-s.m4)dnl
+
+`#if defined (HAVE_'atype_name`) && defined (HAVE_'rtype_name`)'
+
+ARRAY_FUNCTION(0,
+`      const atype_name *minval;
+       minval = base;
+       result = 1;',
+`              if (compare_fcn (src, minval, string_len) < 0)
+                 {
+                   minval = src;
+                   result = (rtype_name)n + 1;
+                 }', `')
+
+MASKED_ARRAY_FUNCTION(0,
+`      const atype_name *minval;
+       minval = base;
+       result = 0;',
+`              if (*msrc)
+                     {
+                       minval = src;
+                       result = (rtype_name)n + 1;
+                       break;
+                     }
+            }
+           for (; n < len; n++, src += delta, msrc += mdelta)
+             {
+               if (*msrc && compare_fcn (src, minval, string_len) < 0)
+                 {
+                   minval = src;
+                   result = (rtype_name)n + 1;
+                 }
+             ')
+
+SCALAR_ARRAY_FUNCTION(0)
+
+#endif
diff --git a/libgfortran/m4/minloc2s.m4 b/libgfortran/m4/minloc2s.m4
new file mode 100644 (file)
index 0000000..38073ce
--- /dev/null
@@ -0,0 +1,156 @@
+`/* Implementation of the MINLOC intrinsic
+   Copyright 2017 Free Software Foundation, Inc.
+   Contributed by Thomas Koenig
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 3 of the License, or (at your option) any later version.
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "libgfortran.h"
+#include <stdlib.h>
+#include <string.h>'
+include(iparm.m4)dnl
+
+`#if defined (HAVE_'atype_name`) && defined (HAVE_'rtype_name`)
+
+static inline int
+compare_fcn (const 'atype_name` *a, const 'atype_name` *b, int n)
+{
+  if (sizeof ('atype_name`) == 1)
+    return memcmp (a, b, n);
+  else
+    return memcmp_char4 (a, b, n);
+}
+
+extern 'rtype_name` 'name`'rtype_qual`_'atype_code` ('atype` * const restrict, int);
+export_proto('name`'rtype_qual`_'atype_code`);
+
+'rtype_name`
+'name`'rtype_qual`_'atype_code` ('atype` * const restrict array, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const 'atype_name` *src;
+  const 'atype_name` *maxval;
+  index_type i;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  ret = 1;
+  src = array->base_addr;
+  maxval = src;
+  for (i=2; i<=extent; i++)
+    {
+      src += sstride;
+      if (compare_fcn (src, maxval, len) < 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+    }
+  return ret;
+}
+
+extern 'rtype_name` m'name`'rtype_qual`_'atype_code` ('atype` * const restrict,
+                               gfc_array_l1 *const restrict mask, int);
+export_proto(m'name`'rtype_qual`_'atype_code`);
+
+'rtype_name`
+m'name`'rtype_qual`_'atype_code` ('atype` * const restrict array,
+                                gfc_array_l1 * const restrict mask, gfc_charlen_type len)
+{
+  index_type ret;
+  index_type sstride;
+  index_type extent;
+  const 'atype_name` *src;
+  const 'atype_name` *maxval;
+  index_type i, j;
+  GFC_LOGICAL_1 *mbase;
+  int mask_kind;
+  index_type mstride;
+
+  extent = GFC_DESCRIPTOR_EXTENT(array,0);
+  if (extent <= 0)
+    return 0;
+
+  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
+
+  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
+  mbase = mask->base_addr;
+
+  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
+    internal_error (NULL, "Funny sized logical array");
+
+  mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
+
+  /* Search for the first occurrence of a true element in mask. */
+  for (j=0; j<extent; j++)
+    {
+      if (*mbase)
+        break;
+      mbase += mstride;
+    }
+
+  if (j == extent)
+    return 0;
+
+  ret = j + 1;
+  src = array->base_addr + j * sstride;
+  maxval = src;
+
+  for (i=j+1; i<=extent; i++)
+    {
+      if (*mbase && compare_fcn (src, maxval, len) < 0)
+      {
+        ret = i;
+        maxval = src;
+      }
+      src += sstride;
+      mbase += mstride;
+    }
+  return ret;
+}
+
+extern 'rtype_name` s'name`'rtype_qual`_'atype_code` ('atype` * const restrict,
+                               GFC_LOGICAL_4 *mask, gfc_charlen_type);
+export_proto(s'name`'rtype_qual`_'atype_code`);
+
+'rtype_name`
+s'name`'rtype_qual`_'atype_code` ('atype` * const restrict array,
+                                GFC_LOGICAL_4 *mask, gfc_charlen_type len)
+{
+  if (mask)
+    return 'name`'rtype_qual`_'atype_code` (array, len);
+  else
+    return 0;
+}
+
+#endif'