1181254a7Smrg /* Implementation of the MAXVAL intrinsic
2*b1e83836Smrg Copyright (C) 2017-2022 Free Software Foundation, Inc.
3181254a7Smrg Contributed by Thomas Koenig
4181254a7Smrg
5181254a7Smrg This file is part of the GNU Fortran runtime library (libgfortran).
6181254a7Smrg
7181254a7Smrg Libgfortran is free software; you can redistribute it and/or
8181254a7Smrg modify it under the terms of the GNU General Public
9181254a7Smrg License as published by the Free Software Foundation; either
10181254a7Smrg version 3 of the License, or (at your option) any later version.
11181254a7Smrg
12181254a7Smrg Libgfortran is distributed in the hope that it will be useful,
13181254a7Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
14181254a7Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15181254a7Smrg GNU General Public License for more details.
16181254a7Smrg
17181254a7Smrg Under Section 7 of GPL version 3, you are granted additional
18181254a7Smrg permissions described in the GCC Runtime Library Exception, version
19181254a7Smrg 3.1, as published by the Free Software Foundation.
20181254a7Smrg
21181254a7Smrg You should have received a copy of the GNU General Public License and
22181254a7Smrg a copy of the GCC Runtime Library Exception along with this program;
23181254a7Smrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24181254a7Smrg <http://www.gnu.org/licenses/>. */
25181254a7Smrg
26181254a7Smrg #include "libgfortran.h"
27181254a7Smrg
28181254a7Smrg
29181254a7Smrg #if defined (HAVE_GFC_UINTEGER_1) && defined (HAVE_GFC_UINTEGER_1)
30181254a7Smrg
31181254a7Smrg #include <string.h>
32181254a7Smrg #include <assert.h>
33181254a7Smrg
34181254a7Smrg static inline int
compare_fcn(const GFC_UINTEGER_1 * a,const GFC_UINTEGER_1 * b,gfc_charlen_type n)35181254a7Smrg compare_fcn (const GFC_UINTEGER_1 *a, const GFC_UINTEGER_1 *b, gfc_charlen_type n)
36181254a7Smrg {
37181254a7Smrg if (sizeof (GFC_UINTEGER_1) == 1)
38181254a7Smrg return memcmp (a, b, n);
39181254a7Smrg else
40181254a7Smrg return memcmp_char4 (a, b, n);
41181254a7Smrg }
42181254a7Smrg
43181254a7Smrg extern void maxval1_s1 (gfc_array_s1 * const restrict,
44181254a7Smrg gfc_charlen_type, gfc_array_s1 * const restrict,
45181254a7Smrg const index_type * const restrict, gfc_charlen_type);
46181254a7Smrg export_proto(maxval1_s1);
47181254a7Smrg
48181254a7Smrg void
maxval1_s1(gfc_array_s1 * const restrict retarray,gfc_charlen_type xlen,gfc_array_s1 * const restrict array,const index_type * const restrict pdim,gfc_charlen_type string_len)49181254a7Smrg maxval1_s1 (gfc_array_s1 * const restrict retarray,
50181254a7Smrg gfc_charlen_type xlen, gfc_array_s1 * const restrict array,
51181254a7Smrg const index_type * const restrict pdim, gfc_charlen_type string_len)
52181254a7Smrg {
53181254a7Smrg index_type count[GFC_MAX_DIMENSIONS];
54181254a7Smrg index_type extent[GFC_MAX_DIMENSIONS];
55181254a7Smrg index_type sstride[GFC_MAX_DIMENSIONS];
56181254a7Smrg index_type dstride[GFC_MAX_DIMENSIONS];
57181254a7Smrg const GFC_UINTEGER_1 * restrict base;
58181254a7Smrg GFC_UINTEGER_1 * restrict dest;
59181254a7Smrg index_type rank;
60181254a7Smrg index_type n;
61181254a7Smrg index_type len;
62181254a7Smrg index_type delta;
63181254a7Smrg index_type dim;
64181254a7Smrg int continue_loop;
65181254a7Smrg
66181254a7Smrg assert (xlen == string_len);
67181254a7Smrg /* Make dim zero based to avoid confusion. */
68181254a7Smrg rank = GFC_DESCRIPTOR_RANK (array) - 1;
69181254a7Smrg dim = (*pdim) - 1;
70181254a7Smrg
71181254a7Smrg if (unlikely (dim < 0 || dim > rank))
72181254a7Smrg {
73181254a7Smrg runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
74181254a7Smrg "is %ld, should be between 1 and %ld",
75181254a7Smrg (long int) dim + 1, (long int) rank + 1);
76181254a7Smrg }
77181254a7Smrg
78181254a7Smrg len = GFC_DESCRIPTOR_EXTENT(array,dim);
79181254a7Smrg if (len < 0)
80181254a7Smrg len = 0;
81181254a7Smrg
82181254a7Smrg delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
83181254a7Smrg
84181254a7Smrg for (n = 0; n < dim; n++)
85181254a7Smrg {
86181254a7Smrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
87181254a7Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
88181254a7Smrg
89181254a7Smrg if (extent[n] < 0)
90181254a7Smrg extent[n] = 0;
91181254a7Smrg }
92181254a7Smrg for (n = dim; n < rank; n++)
93181254a7Smrg {
94181254a7Smrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1) * string_len;
95181254a7Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
96181254a7Smrg
97181254a7Smrg if (extent[n] < 0)
98181254a7Smrg extent[n] = 0;
99181254a7Smrg }
100181254a7Smrg
101181254a7Smrg if (retarray->base_addr == NULL)
102181254a7Smrg {
103181254a7Smrg size_t alloc_size, str;
104181254a7Smrg
105181254a7Smrg for (n = 0; n < rank; n++)
106181254a7Smrg {
107181254a7Smrg if (n == 0)
108181254a7Smrg str = 1;
109181254a7Smrg else
110181254a7Smrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
111181254a7Smrg
112181254a7Smrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
113181254a7Smrg
114181254a7Smrg }
115181254a7Smrg
116181254a7Smrg retarray->offset = 0;
117181254a7Smrg retarray->dtype.rank = rank;
118181254a7Smrg
119181254a7Smrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
120181254a7Smrg * string_len;
121181254a7Smrg
122181254a7Smrg retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_UINTEGER_1));
123181254a7Smrg if (alloc_size == 0)
124181254a7Smrg {
125181254a7Smrg /* Make sure we have a zero-sized array. */
126181254a7Smrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
127181254a7Smrg return;
128181254a7Smrg
129181254a7Smrg }
130181254a7Smrg }
131181254a7Smrg else
132181254a7Smrg {
133181254a7Smrg if (rank != GFC_DESCRIPTOR_RANK (retarray))
134181254a7Smrg runtime_error ("rank of return array incorrect in"
135181254a7Smrg " MAXVAL intrinsic: is %ld, should be %ld",
136181254a7Smrg (long int) (GFC_DESCRIPTOR_RANK (retarray)),
137181254a7Smrg (long int) rank);
138181254a7Smrg
139181254a7Smrg if (unlikely (compile_options.bounds_check))
140181254a7Smrg bounds_ifunction_return ((array_t *) retarray, extent,
141181254a7Smrg "return value", "MAXVAL");
142181254a7Smrg }
143181254a7Smrg
144181254a7Smrg for (n = 0; n < rank; n++)
145181254a7Smrg {
146181254a7Smrg count[n] = 0;
147181254a7Smrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
148181254a7Smrg if (extent[n] <= 0)
149181254a7Smrg return;
150181254a7Smrg }
151181254a7Smrg
152181254a7Smrg base = array->base_addr;
153181254a7Smrg dest = retarray->base_addr;
154181254a7Smrg
155181254a7Smrg continue_loop = 1;
156181254a7Smrg while (continue_loop)
157181254a7Smrg {
158181254a7Smrg const GFC_UINTEGER_1 * restrict src;
159181254a7Smrg src = base;
160181254a7Smrg {
161181254a7Smrg
162181254a7Smrg const GFC_UINTEGER_1 *retval;
163181254a7Smrg retval = base;
164181254a7Smrg if (len <= 0)
165181254a7Smrg memset (dest, 0, sizeof (*dest) * string_len);
166181254a7Smrg else
167181254a7Smrg {
168181254a7Smrg for (n = 0; n < len; n++, src += delta)
169181254a7Smrg {
170181254a7Smrg
171181254a7Smrg if (compare_fcn (src, retval, string_len) > 0)
172181254a7Smrg {
173181254a7Smrg retval = src;
174181254a7Smrg }
175181254a7Smrg }
176181254a7Smrg
177181254a7Smrg memcpy (dest, retval, sizeof (*dest) * string_len);
178181254a7Smrg }
179181254a7Smrg }
180181254a7Smrg /* Advance to the next element. */
181181254a7Smrg count[0]++;
182181254a7Smrg base += sstride[0];
183181254a7Smrg dest += dstride[0];
184181254a7Smrg n = 0;
185181254a7Smrg while (count[n] == extent[n])
186181254a7Smrg {
187181254a7Smrg /* When we get to the end of a dimension, reset it and increment
188181254a7Smrg the next dimension. */
189181254a7Smrg count[n] = 0;
190181254a7Smrg /* We could precalculate these products, but this is a less
191181254a7Smrg frequently used path so probably not worth it. */
192181254a7Smrg base -= sstride[n] * extent[n];
193181254a7Smrg dest -= dstride[n] * extent[n];
194181254a7Smrg n++;
195181254a7Smrg if (n >= rank)
196181254a7Smrg {
197181254a7Smrg /* Break out of the loop. */
198181254a7Smrg continue_loop = 0;
199181254a7Smrg break;
200181254a7Smrg }
201181254a7Smrg else
202181254a7Smrg {
203181254a7Smrg count[n]++;
204181254a7Smrg base += sstride[n];
205181254a7Smrg dest += dstride[n];
206181254a7Smrg }
207181254a7Smrg }
208181254a7Smrg }
209181254a7Smrg }
210181254a7Smrg
211181254a7Smrg
212181254a7Smrg extern void mmaxval1_s1 (gfc_array_s1 * const restrict,
213181254a7Smrg gfc_charlen_type, gfc_array_s1 * const restrict,
214181254a7Smrg const index_type * const restrict,
215181254a7Smrg gfc_array_l1 * const restrict, gfc_charlen_type);
216181254a7Smrg export_proto(mmaxval1_s1);
217181254a7Smrg
218181254a7Smrg void
mmaxval1_s1(gfc_array_s1 * const restrict retarray,gfc_charlen_type xlen,gfc_array_s1 * const restrict array,const index_type * const restrict pdim,gfc_array_l1 * const restrict mask,gfc_charlen_type string_len)219181254a7Smrg mmaxval1_s1 (gfc_array_s1 * const restrict retarray,
220181254a7Smrg gfc_charlen_type xlen, gfc_array_s1 * const restrict array,
221181254a7Smrg const index_type * const restrict pdim,
222181254a7Smrg gfc_array_l1 * const restrict mask,
223181254a7Smrg gfc_charlen_type string_len)
224181254a7Smrg
225181254a7Smrg {
226181254a7Smrg index_type count[GFC_MAX_DIMENSIONS];
227181254a7Smrg index_type extent[GFC_MAX_DIMENSIONS];
228181254a7Smrg index_type sstride[GFC_MAX_DIMENSIONS];
229181254a7Smrg index_type dstride[GFC_MAX_DIMENSIONS];
230181254a7Smrg index_type mstride[GFC_MAX_DIMENSIONS];
231181254a7Smrg GFC_UINTEGER_1 * restrict dest;
232181254a7Smrg const GFC_UINTEGER_1 * restrict base;
233181254a7Smrg const GFC_LOGICAL_1 * restrict mbase;
234181254a7Smrg index_type rank;
235181254a7Smrg index_type dim;
236181254a7Smrg index_type n;
237181254a7Smrg index_type len;
238181254a7Smrg index_type delta;
239181254a7Smrg index_type mdelta;
240181254a7Smrg int mask_kind;
241181254a7Smrg
242181254a7Smrg if (mask == NULL)
243181254a7Smrg {
244181254a7Smrg maxval1_s1 (retarray, xlen, array, pdim, string_len);
245181254a7Smrg return;
246181254a7Smrg }
247181254a7Smrg
248181254a7Smrg assert (xlen == string_len);
249181254a7Smrg
250181254a7Smrg dim = (*pdim) - 1;
251181254a7Smrg rank = GFC_DESCRIPTOR_RANK (array) - 1;
252181254a7Smrg
253181254a7Smrg if (unlikely (dim < 0 || dim > rank))
254181254a7Smrg {
255181254a7Smrg runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
256181254a7Smrg "is %ld, should be between 1 and %ld",
257181254a7Smrg (long int) dim + 1, (long int) rank + 1);
258181254a7Smrg }
259181254a7Smrg
260181254a7Smrg len = GFC_DESCRIPTOR_EXTENT(array,dim);
261181254a7Smrg if (len <= 0)
262181254a7Smrg return;
263181254a7Smrg
264181254a7Smrg mbase = mask->base_addr;
265181254a7Smrg
266181254a7Smrg mask_kind = GFC_DESCRIPTOR_SIZE (mask);
267181254a7Smrg
268181254a7Smrg if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
269181254a7Smrg #ifdef HAVE_GFC_LOGICAL_16
270181254a7Smrg || mask_kind == 16
271181254a7Smrg #endif
272181254a7Smrg )
273181254a7Smrg mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
274181254a7Smrg else
275181254a7Smrg runtime_error ("Funny sized logical array");
276181254a7Smrg
277181254a7Smrg delta = GFC_DESCRIPTOR_STRIDE(array,dim) * string_len;
278181254a7Smrg mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
279181254a7Smrg
280181254a7Smrg for (n = 0; n < dim; n++)
281181254a7Smrg {
282181254a7Smrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n) * string_len;
283181254a7Smrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
284181254a7Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
285181254a7Smrg
286181254a7Smrg if (extent[n] < 0)
287181254a7Smrg extent[n] = 0;
288181254a7Smrg
289181254a7Smrg }
290181254a7Smrg for (n = dim; n < rank; n++)
291181254a7Smrg {
292181254a7Smrg sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1) * string_len;
293181254a7Smrg mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
294181254a7Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
295181254a7Smrg
296181254a7Smrg if (extent[n] < 0)
297181254a7Smrg extent[n] = 0;
298181254a7Smrg }
299181254a7Smrg
300181254a7Smrg if (retarray->base_addr == NULL)
301181254a7Smrg {
302181254a7Smrg size_t alloc_size, str;
303181254a7Smrg
304181254a7Smrg for (n = 0; n < rank; n++)
305181254a7Smrg {
306181254a7Smrg if (n == 0)
307181254a7Smrg str = 1;
308181254a7Smrg else
309181254a7Smrg str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
310181254a7Smrg
311181254a7Smrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
312181254a7Smrg
313181254a7Smrg }
314181254a7Smrg
315181254a7Smrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
316181254a7Smrg * string_len;
317181254a7Smrg
318181254a7Smrg retarray->offset = 0;
319181254a7Smrg retarray->dtype.rank = rank;
320181254a7Smrg
321181254a7Smrg if (alloc_size == 0)
322181254a7Smrg {
323181254a7Smrg /* Make sure we have a zero-sized array. */
324181254a7Smrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
325181254a7Smrg return;
326181254a7Smrg }
327181254a7Smrg else
328181254a7Smrg retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_UINTEGER_1));
329181254a7Smrg
330181254a7Smrg }
331181254a7Smrg else
332181254a7Smrg {
333181254a7Smrg if (rank != GFC_DESCRIPTOR_RANK (retarray))
334181254a7Smrg runtime_error ("rank of return array incorrect in MAXVAL intrinsic");
335181254a7Smrg
336181254a7Smrg if (unlikely (compile_options.bounds_check))
337181254a7Smrg {
338181254a7Smrg bounds_ifunction_return ((array_t *) retarray, extent,
339181254a7Smrg "return value", "MAXVAL");
340181254a7Smrg bounds_equal_extents ((array_t *) mask, (array_t *) array,
341181254a7Smrg "MASK argument", "MAXVAL");
342181254a7Smrg }
343181254a7Smrg }
344181254a7Smrg
345181254a7Smrg for (n = 0; n < rank; n++)
346181254a7Smrg {
347181254a7Smrg count[n] = 0;
348181254a7Smrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
349181254a7Smrg if (extent[n] <= 0)
350181254a7Smrg return;
351181254a7Smrg }
352181254a7Smrg
353181254a7Smrg dest = retarray->base_addr;
354181254a7Smrg base = array->base_addr;
355181254a7Smrg
356181254a7Smrg while (base)
357181254a7Smrg {
358181254a7Smrg const GFC_UINTEGER_1 * restrict src;
359181254a7Smrg const GFC_LOGICAL_1 * restrict msrc;
360181254a7Smrg
361181254a7Smrg src = base;
362181254a7Smrg msrc = mbase;
363181254a7Smrg {
364181254a7Smrg
365181254a7Smrg const GFC_UINTEGER_1 *retval;
366181254a7Smrg memset (dest, 0, sizeof (*dest) * string_len);
367181254a7Smrg retval = dest;
368181254a7Smrg for (n = 0; n < len; n++, src += delta, msrc += mdelta)
369181254a7Smrg {
370181254a7Smrg
371181254a7Smrg if (*msrc)
372181254a7Smrg {
373181254a7Smrg retval = src;
374181254a7Smrg break;
375181254a7Smrg }
376181254a7Smrg }
377181254a7Smrg for (; n < len; n++, src += delta, msrc += mdelta)
378181254a7Smrg {
379181254a7Smrg if (*msrc && compare_fcn (src, retval, string_len) > 0)
380181254a7Smrg {
381181254a7Smrg retval = src;
382181254a7Smrg }
383181254a7Smrg
384181254a7Smrg }
385181254a7Smrg memcpy (dest, retval, sizeof (*dest) * string_len);
386181254a7Smrg }
387181254a7Smrg /* Advance to the next element. */
388181254a7Smrg count[0]++;
389181254a7Smrg base += sstride[0];
390181254a7Smrg mbase += mstride[0];
391181254a7Smrg dest += dstride[0];
392181254a7Smrg n = 0;
393181254a7Smrg while (count[n] == extent[n])
394181254a7Smrg {
395181254a7Smrg /* When we get to the end of a dimension, reset it and increment
396181254a7Smrg the next dimension. */
397181254a7Smrg count[n] = 0;
398181254a7Smrg /* We could precalculate these products, but this is a less
399181254a7Smrg frequently used path so probably not worth it. */
400181254a7Smrg base -= sstride[n] * extent[n];
401181254a7Smrg mbase -= mstride[n] * extent[n];
402181254a7Smrg dest -= dstride[n] * extent[n];
403181254a7Smrg n++;
404181254a7Smrg if (n >= rank)
405181254a7Smrg {
406181254a7Smrg /* Break out of the loop. */
407181254a7Smrg base = NULL;
408181254a7Smrg break;
409181254a7Smrg }
410181254a7Smrg else
411181254a7Smrg {
412181254a7Smrg count[n]++;
413181254a7Smrg base += sstride[n];
414181254a7Smrg mbase += mstride[n];
415181254a7Smrg dest += dstride[n];
416181254a7Smrg }
417181254a7Smrg }
418181254a7Smrg }
419181254a7Smrg }
420181254a7Smrg
421181254a7Smrg
422181254a7Smrg void smaxval1_s1 (gfc_array_s1 * const restrict,
423181254a7Smrg gfc_charlen_type, gfc_array_s1 * const restrict,
424181254a7Smrg const index_type * const restrict,
425181254a7Smrg GFC_LOGICAL_4 *, gfc_charlen_type);
426181254a7Smrg
427181254a7Smrg export_proto(smaxval1_s1);
428181254a7Smrg
429181254a7Smrg void
smaxval1_s1(gfc_array_s1 * const restrict retarray,gfc_charlen_type xlen,gfc_array_s1 * const restrict array,const index_type * const restrict pdim,GFC_LOGICAL_4 * mask,gfc_charlen_type string_len)430181254a7Smrg smaxval1_s1 (gfc_array_s1 * const restrict retarray,
431181254a7Smrg gfc_charlen_type xlen, gfc_array_s1 * const restrict array,
432181254a7Smrg const index_type * const restrict pdim,
433181254a7Smrg GFC_LOGICAL_4 *mask, gfc_charlen_type string_len)
434181254a7Smrg
435181254a7Smrg {
436181254a7Smrg index_type count[GFC_MAX_DIMENSIONS];
437181254a7Smrg index_type extent[GFC_MAX_DIMENSIONS];
438181254a7Smrg index_type dstride[GFC_MAX_DIMENSIONS];
439181254a7Smrg GFC_UINTEGER_1 * restrict dest;
440181254a7Smrg index_type rank;
441181254a7Smrg index_type n;
442181254a7Smrg index_type dim;
443181254a7Smrg
444181254a7Smrg
445181254a7Smrg if (mask == NULL || *mask)
446181254a7Smrg {
447181254a7Smrg maxval1_s1 (retarray, xlen, array, pdim, string_len);
448181254a7Smrg return;
449181254a7Smrg }
450181254a7Smrg /* Make dim zero based to avoid confusion. */
451181254a7Smrg dim = (*pdim) - 1;
452181254a7Smrg rank = GFC_DESCRIPTOR_RANK (array) - 1;
453181254a7Smrg
454181254a7Smrg if (unlikely (dim < 0 || dim > rank))
455181254a7Smrg {
456181254a7Smrg runtime_error ("Dim argument incorrect in MAXVAL intrinsic: "
457181254a7Smrg "is %ld, should be between 1 and %ld",
458181254a7Smrg (long int) dim + 1, (long int) rank + 1);
459181254a7Smrg }
460181254a7Smrg
461181254a7Smrg for (n = 0; n < dim; n++)
462181254a7Smrg {
463181254a7Smrg extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
464181254a7Smrg
465181254a7Smrg if (extent[n] <= 0)
466181254a7Smrg extent[n] = 0;
467181254a7Smrg }
468181254a7Smrg
469181254a7Smrg for (n = dim; n < rank; n++)
470181254a7Smrg {
471181254a7Smrg extent[n] =
472181254a7Smrg GFC_DESCRIPTOR_EXTENT(array,n + 1);
473181254a7Smrg
474181254a7Smrg if (extent[n] <= 0)
475181254a7Smrg extent[n] = 0;
476181254a7Smrg }
477181254a7Smrg
478181254a7Smrg if (retarray->base_addr == NULL)
479181254a7Smrg {
480181254a7Smrg size_t alloc_size, str;
481181254a7Smrg
482181254a7Smrg for (n = 0; n < rank; n++)
483181254a7Smrg {
484181254a7Smrg if (n == 0)
485181254a7Smrg str = 1;
486181254a7Smrg else
487181254a7Smrg str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
488181254a7Smrg
489181254a7Smrg GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
490181254a7Smrg
491181254a7Smrg }
492181254a7Smrg
493181254a7Smrg retarray->offset = 0;
494181254a7Smrg retarray->dtype.rank = rank;
495181254a7Smrg
496181254a7Smrg alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1]
497181254a7Smrg * string_len;
498181254a7Smrg
499181254a7Smrg if (alloc_size == 0)
500181254a7Smrg {
501181254a7Smrg /* Make sure we have a zero-sized array. */
502181254a7Smrg GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
503181254a7Smrg return;
504181254a7Smrg }
505181254a7Smrg else
506181254a7Smrg retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_UINTEGER_1));
507181254a7Smrg }
508181254a7Smrg else
509181254a7Smrg {
510181254a7Smrg if (rank != GFC_DESCRIPTOR_RANK (retarray))
511181254a7Smrg runtime_error ("rank of return array incorrect in"
512181254a7Smrg " MAXVAL intrinsic: is %ld, should be %ld",
513181254a7Smrg (long int) (GFC_DESCRIPTOR_RANK (retarray)),
514181254a7Smrg (long int) rank);
515181254a7Smrg
516181254a7Smrg if (unlikely (compile_options.bounds_check))
517181254a7Smrg {
518181254a7Smrg for (n=0; n < rank; n++)
519181254a7Smrg {
520181254a7Smrg index_type ret_extent;
521181254a7Smrg
522181254a7Smrg ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
523181254a7Smrg if (extent[n] != ret_extent)
524181254a7Smrg runtime_error ("Incorrect extent in return value of"
525181254a7Smrg " MAXVAL intrinsic in dimension %ld:"
526181254a7Smrg " is %ld, should be %ld", (long int) n + 1,
527181254a7Smrg (long int) ret_extent, (long int) extent[n]);
528181254a7Smrg }
529181254a7Smrg }
530181254a7Smrg }
531181254a7Smrg
532181254a7Smrg for (n = 0; n < rank; n++)
533181254a7Smrg {
534181254a7Smrg count[n] = 0;
535181254a7Smrg dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n) * string_len;
536181254a7Smrg }
537181254a7Smrg
538181254a7Smrg dest = retarray->base_addr;
539181254a7Smrg
540181254a7Smrg while(1)
541181254a7Smrg {
542181254a7Smrg memset (dest, 0, sizeof (*dest) * string_len);
543181254a7Smrg count[0]++;
544181254a7Smrg dest += dstride[0];
545181254a7Smrg n = 0;
546181254a7Smrg while (count[n] == extent[n])
547181254a7Smrg {
548181254a7Smrg /* When we get to the end of a dimension, reset it and increment
549181254a7Smrg the next dimension. */
550181254a7Smrg count[n] = 0;
551181254a7Smrg /* We could precalculate these products, but this is a less
552181254a7Smrg frequently used path so probably not worth it. */
553181254a7Smrg dest -= dstride[n] * extent[n];
554181254a7Smrg n++;
555181254a7Smrg if (n >= rank)
556181254a7Smrg return;
557181254a7Smrg else
558181254a7Smrg {
559181254a7Smrg count[n]++;
560181254a7Smrg dest += dstride[n];
561181254a7Smrg }
562181254a7Smrg }
563181254a7Smrg }
564181254a7Smrg }
565181254a7Smrg
566181254a7Smrg #endif
567