xref: /netbsd-src/external/gpl3/gcc.old/dist/libgfortran/m4/maxloc2s.m4 (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1627f7eb2Smrg`/* Implementation of the MAXLOC intrinsic
2*4c3eb207Smrg   Copyright (C) 2017-2020 Free Software Foundation, Inc.
3627f7eb2Smrg   Contributed by Thomas Koenig
4627f7eb2Smrg
5627f7eb2SmrgThis file is part of the GNU Fortran runtime library (libgfortran).
6627f7eb2Smrg
7627f7eb2SmrgLibgfortran is free software; you can redistribute it and/or
8627f7eb2Smrgmodify it under the terms of the GNU General Public
9627f7eb2SmrgLicense as published by the Free Software Foundation; either
10627f7eb2Smrgversion 3 of the License, or (at your option) any later version.
11627f7eb2Smrg
12627f7eb2SmrgLibgfortran is distributed in the hope that it will be useful,
13627f7eb2Smrgbut WITHOUT ANY WARRANTY; without even the implied warranty of
14627f7eb2SmrgMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15627f7eb2SmrgGNU General Public License for more details.
16627f7eb2Smrg
17627f7eb2SmrgUnder Section 7 of GPL version 3, you are granted additional
18627f7eb2Smrgpermissions described in the GCC Runtime Library Exception, version
19627f7eb2Smrg3.1, as published by the Free Software Foundation.
20627f7eb2Smrg
21627f7eb2SmrgYou should have received a copy of the GNU General Public License and
22627f7eb2Smrga copy of the GCC Runtime Library Exception along with this program;
23627f7eb2Smrgsee the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24627f7eb2Smrg<http://www.gnu.org/licenses/>.  */
25627f7eb2Smrg
26627f7eb2Smrg#include "libgfortran.h"
27627f7eb2Smrg#include <stdlib.h>
28627f7eb2Smrg#include <string.h>
29627f7eb2Smrg#include <assert.h>'
30627f7eb2Smrginclude(iparm.m4)dnl
31627f7eb2Smrg
32627f7eb2Smrg`#if defined (HAVE_'atype_name`) && defined (HAVE_'rtype_name`)
33627f7eb2Smrg
34627f7eb2Smrgstatic inline int
35627f7eb2Smrgcompare_fcn (const 'atype_name` *a, const 'atype_name` *b, gfc_charlen_type n)
36627f7eb2Smrg{
37627f7eb2Smrg  if (sizeof ('atype_name`) == 1)
38627f7eb2Smrg    return memcmp (a, b, n);
39627f7eb2Smrg  else
40627f7eb2Smrg    return memcmp_char4 (a, b, n);
41627f7eb2Smrg}
42627f7eb2Smrg
43627f7eb2Smrgextern 'rtype_name` 'name`'rtype_qual`_'atype_code` ('atype` * const restrict'back_arg`,
44627f7eb2Smrg       gfc_charlen_type);
45627f7eb2Smrgexport_proto('name`'rtype_qual`_'atype_code`);
46627f7eb2Smrg
47627f7eb2Smrg'rtype_name`
48627f7eb2Smrg'name`'rtype_qual`_'atype_code` ('atype` * const restrict array'back_arg`, gfc_charlen_type len)
49627f7eb2Smrg{
50627f7eb2Smrg  index_type ret;
51627f7eb2Smrg  index_type sstride;
52627f7eb2Smrg  index_type extent;
53627f7eb2Smrg  const 'atype_name` *src;
54627f7eb2Smrg  const 'atype_name` *maxval;
55627f7eb2Smrg  index_type i;
56627f7eb2Smrg
57627f7eb2Smrg  extent = GFC_DESCRIPTOR_EXTENT(array,0);
58627f7eb2Smrg  if (extent <= 0)
59627f7eb2Smrg    return 0;
60627f7eb2Smrg
61627f7eb2Smrg  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
62627f7eb2Smrg
63627f7eb2Smrg  ret = 1;
64627f7eb2Smrg  src = array->base_addr;
65627f7eb2Smrg  maxval = NULL;
66627f7eb2Smrg  for (i=1; i<=extent; i++)
67627f7eb2Smrg    {
68627f7eb2Smrg      if (maxval == NULL || (back ? compare_fcn (src, maxval, len) >= 0 :
69627f7eb2Smrg      	 	    	    	    compare_fcn (src, maxval, len) > 0))
70627f7eb2Smrg      {
71627f7eb2Smrg	 ret = i;
72627f7eb2Smrg	 maxval = src;
73627f7eb2Smrg      }
74627f7eb2Smrg      src += sstride;
75627f7eb2Smrg    }
76627f7eb2Smrg  return ret;
77627f7eb2Smrg}
78627f7eb2Smrg
79627f7eb2Smrgextern 'rtype_name` m'name`'rtype_qual`_'atype_code` ('atype` * const restrict,
80627f7eb2Smrg       		    	gfc_array_l1 *const restrict mask'back_arg`,
81627f7eb2Smrg			gfc_charlen_type);
82627f7eb2Smrgexport_proto(m'name`'rtype_qual`_'atype_code`);
83627f7eb2Smrg
84627f7eb2Smrg'rtype_name`
85627f7eb2Smrgm'name`'rtype_qual`_'atype_code` ('atype` * const restrict array,
86627f7eb2Smrg				 gfc_array_l1 * const restrict mask'back_arg`,
87627f7eb2Smrg				 gfc_charlen_type len)
88627f7eb2Smrg{
89627f7eb2Smrg  index_type ret;
90627f7eb2Smrg  index_type sstride;
91627f7eb2Smrg  index_type extent;
92627f7eb2Smrg  const 'atype_name` *src;
93627f7eb2Smrg  const 'atype_name` *maxval;
94627f7eb2Smrg  index_type i, j;
95627f7eb2Smrg  GFC_LOGICAL_1 *mbase;
96627f7eb2Smrg  int mask_kind;
97627f7eb2Smrg  index_type mstride;
98627f7eb2Smrg
99627f7eb2Smrg  extent = GFC_DESCRIPTOR_EXTENT(array,0);
100627f7eb2Smrg  if (extent <= 0)
101627f7eb2Smrg    return 0;
102627f7eb2Smrg
103627f7eb2Smrg  sstride = GFC_DESCRIPTOR_STRIDE(array,0) * len;
104627f7eb2Smrg
105627f7eb2Smrg  mask_kind = GFC_DESCRIPTOR_SIZE (mask);
106627f7eb2Smrg  mbase = mask->base_addr;
107627f7eb2Smrg
108627f7eb2Smrg  if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
109627f7eb2Smrg#ifdef HAVE_GFC_LOGICAL_16
110627f7eb2Smrg      || mask_kind == 16
111627f7eb2Smrg#endif
112627f7eb2Smrg      )
113627f7eb2Smrg    mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
114627f7eb2Smrg  else
115627f7eb2Smrg    internal_error (NULL, "Funny sized logical array");
116627f7eb2Smrg
117627f7eb2Smrg  mstride = GFC_DESCRIPTOR_STRIDE_BYTES(mask,0);
118627f7eb2Smrg
119627f7eb2Smrg  /* Search for the first occurrence of a true element in mask. */
120627f7eb2Smrg  for (j=0; j<extent; j++)
121627f7eb2Smrg    {
122627f7eb2Smrg      if (*mbase)
123627f7eb2Smrg        break;
124627f7eb2Smrg      mbase += mstride;
125627f7eb2Smrg    }
126627f7eb2Smrg
127627f7eb2Smrg  if (j == extent)
128627f7eb2Smrg    return 0;
129627f7eb2Smrg
130627f7eb2Smrg  ret = j + 1;
131627f7eb2Smrg  src = array->base_addr + j * sstride;
132627f7eb2Smrg  maxval = src;
133627f7eb2Smrg
134627f7eb2Smrg  for (i=j+1; i<=extent; i++)
135627f7eb2Smrg    {
136627f7eb2Smrg      if (*mbase && (back ? compare_fcn (src, maxval, len) >= 0 :
137627f7eb2Smrg      	 	    	   compare_fcn (src, maxval, len) > 0))
138627f7eb2Smrg      {
139627f7eb2Smrg	 ret = i;
140627f7eb2Smrg	 maxval = src;
141627f7eb2Smrg      }
142627f7eb2Smrg      src += sstride;
143627f7eb2Smrg      mbase += mstride;
144627f7eb2Smrg    }
145627f7eb2Smrg  return ret;
146627f7eb2Smrg}
147627f7eb2Smrg
148627f7eb2Smrgextern 'rtype_name` s'name`'rtype_qual`_'atype_code` ('atype` * const restrict,
149627f7eb2Smrg                               GFC_LOGICAL_4 *mask'back_arg`, gfc_charlen_type);
150627f7eb2Smrgexport_proto(s'name`'rtype_qual`_'atype_code`);
151627f7eb2Smrg
152627f7eb2Smrg'rtype_name`
153627f7eb2Smrgs'name`'rtype_qual`_'atype_code` ('atype` * const restrict array,
154627f7eb2Smrg				 GFC_LOGICAL_4 *mask'back_arg`, gfc_charlen_type len)
155627f7eb2Smrg{
156627f7eb2Smrg  if (mask)
157627f7eb2Smrg    return 'name`'rtype_qual`_'atype_code` (array, len, back);
158627f7eb2Smrg  else
159627f7eb2Smrg    return 0;
160627f7eb2Smrg}
161627f7eb2Smrg
162627f7eb2Smrg#endif'
163