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