1 /* Implementation of the MAXLOC intrinsic
2 Copyright (C) 2002-2024 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
5 This file is part of the GNU Fortran runtime library (libgfortran).
7 Libgfortran is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either
10 version 3 of the License, or (at your option) any later version.
12 Libgfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #include "libgfortran.h"
30 #if defined (HAVE_GFC_REAL_10) && defined (HAVE_GFC_INTEGER_4)
32 #define HAVE_BACK_ARG 1
35 extern void maxloc1_4_r10 (gfc_array_i4
* const restrict
,
36 gfc_array_r10
* const restrict
, const index_type
* const restrict
, GFC_LOGICAL_4 back
);
37 export_proto(maxloc1_4_r10
);
40 maxloc1_4_r10 (gfc_array_i4
* const restrict retarray
,
41 gfc_array_r10
* const restrict array
,
42 const index_type
* const restrict pdim
, GFC_LOGICAL_4 back
)
44 index_type count
[GFC_MAX_DIMENSIONS
];
45 index_type extent
[GFC_MAX_DIMENSIONS
];
46 index_type sstride
[GFC_MAX_DIMENSIONS
];
47 index_type dstride
[GFC_MAX_DIMENSIONS
];
48 const GFC_REAL_10
* restrict base
;
49 GFC_INTEGER_4
* restrict dest
;
57 /* Make dim zero based to avoid confusion. */
58 rank
= GFC_DESCRIPTOR_RANK (array
) - 1;
61 if (unlikely (dim
< 0 || dim
> rank
))
63 runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
64 "is %ld, should be between 1 and %ld",
65 (long int) dim
+ 1, (long int) rank
+ 1);
68 len
= GFC_DESCRIPTOR_EXTENT(array
,dim
);
71 delta
= GFC_DESCRIPTOR_STRIDE(array
,dim
);
73 for (n
= 0; n
< dim
; n
++)
75 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(array
,n
);
76 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
,n
);
81 for (n
= dim
; n
< rank
; n
++)
83 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(array
, n
+ 1);
84 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
, n
+ 1);
90 if (retarray
->base_addr
== NULL
)
92 size_t alloc_size
, str
;
94 for (n
= 0; n
< rank
; n
++)
99 str
= GFC_DESCRIPTOR_STRIDE(retarray
,n
-1) * extent
[n
-1];
101 GFC_DIMENSION_SET(retarray
->dim
[n
], 0, extent
[n
] - 1, str
);
105 retarray
->offset
= 0;
106 retarray
->dtype
.rank
= rank
;
108 alloc_size
= GFC_DESCRIPTOR_STRIDE(retarray
,rank
-1) * extent
[rank
-1];
110 retarray
->base_addr
= xmallocarray (alloc_size
, sizeof (GFC_INTEGER_4
));
116 if (rank
!= GFC_DESCRIPTOR_RANK (retarray
))
117 runtime_error ("rank of return array incorrect in"
118 " MAXLOC intrinsic: is %ld, should be %ld",
119 (long int) (GFC_DESCRIPTOR_RANK (retarray
)),
122 if (unlikely (compile_options
.bounds_check
))
123 bounds_ifunction_return ((array_t
*) retarray
, extent
,
124 "return value", "MAXLOC");
127 for (n
= 0; n
< rank
; n
++)
130 dstride
[n
] = GFC_DESCRIPTOR_STRIDE(retarray
,n
);
135 base
= array
->base_addr
;
136 dest
= retarray
->base_addr
;
139 while (continue_loop
)
141 const GFC_REAL_10
* restrict src
;
142 GFC_INTEGER_4 result
;
147 #if defined (GFC_REAL_10_INFINITY)
148 maxval
= -GFC_REAL_10_INFINITY
;
150 maxval
= -GFC_REAL_10_HUGE
;
157 #if ! defined HAVE_BACK_ARG
158 for (n
= 0; n
< len
; n
++, src
+= delta
)
162 #if defined (GFC_REAL_10_QUIET_NAN)
163 for (n
= 0; n
< len
; n
++, src
+= delta
)
168 result
= (GFC_INTEGER_4
)n
+ 1;
175 for (; n
< len
; n
++, src
+= delta
)
177 if (back
? *src
>= maxval
: *src
> maxval
)
180 result
= (GFC_INTEGER_4
)n
+ 1;
187 /* Advance to the next element. */
192 while (count
[n
] == extent
[n
])
194 /* When we get to the end of a dimension, reset it and increment
195 the next dimension. */
197 /* We could precalculate these products, but this is a less
198 frequently used path so probably not worth it. */
199 base
-= sstride
[n
] * extent
[n
];
200 dest
-= dstride
[n
] * extent
[n
];
204 /* Break out of the loop. */
219 extern void mmaxloc1_4_r10 (gfc_array_i4
* const restrict
,
220 gfc_array_r10
* const restrict
, const index_type
* const restrict
,
221 gfc_array_l1
* const restrict
, GFC_LOGICAL_4 back
);
222 export_proto(mmaxloc1_4_r10
);
225 mmaxloc1_4_r10 (gfc_array_i4
* const restrict retarray
,
226 gfc_array_r10
* const restrict array
,
227 const index_type
* const restrict pdim
,
228 gfc_array_l1
* const restrict mask
, GFC_LOGICAL_4 back
)
230 index_type count
[GFC_MAX_DIMENSIONS
];
231 index_type extent
[GFC_MAX_DIMENSIONS
];
232 index_type sstride
[GFC_MAX_DIMENSIONS
];
233 index_type dstride
[GFC_MAX_DIMENSIONS
];
234 index_type mstride
[GFC_MAX_DIMENSIONS
];
235 GFC_INTEGER_4
* restrict dest
;
236 const GFC_REAL_10
* restrict base
;
237 const GFC_LOGICAL_1
* restrict mbase
;
249 maxloc1_4_r10 (retarray
, array
, pdim
, back
);
251 maxloc1_4_r10 (retarray
, array
, pdim
);
257 rank
= GFC_DESCRIPTOR_RANK (array
) - 1;
260 if (unlikely (dim
< 0 || dim
> rank
))
262 runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
263 "is %ld, should be between 1 and %ld",
264 (long int) dim
+ 1, (long int) rank
+ 1);
267 len
= GFC_DESCRIPTOR_EXTENT(array
,dim
);
271 mbase
= mask
->base_addr
;
273 mask_kind
= GFC_DESCRIPTOR_SIZE (mask
);
275 if (mask_kind
== 1 || mask_kind
== 2 || mask_kind
== 4 || mask_kind
== 8
276 #ifdef HAVE_GFC_LOGICAL_16
280 mbase
= GFOR_POINTER_TO_L1 (mbase
, mask_kind
);
282 runtime_error ("Funny sized logical array");
284 delta
= GFC_DESCRIPTOR_STRIDE(array
,dim
);
285 mdelta
= GFC_DESCRIPTOR_STRIDE_BYTES(mask
,dim
);
287 for (n
= 0; n
< dim
; n
++)
289 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(array
,n
);
290 mstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(mask
,n
);
291 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
,n
);
297 for (n
= dim
; n
< rank
; n
++)
299 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(array
,n
+ 1);
300 mstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(mask
, n
+ 1);
301 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
, n
+ 1);
307 if (retarray
->base_addr
== NULL
)
309 size_t alloc_size
, str
;
311 for (n
= 0; n
< rank
; n
++)
316 str
= GFC_DESCRIPTOR_STRIDE(retarray
,n
-1) * extent
[n
-1];
318 GFC_DIMENSION_SET(retarray
->dim
[n
], 0, extent
[n
] - 1, str
);
322 alloc_size
= GFC_DESCRIPTOR_STRIDE(retarray
,rank
-1) * extent
[rank
-1];
324 retarray
->offset
= 0;
325 retarray
->dtype
.rank
= rank
;
327 retarray
->base_addr
= xmallocarray (alloc_size
, sizeof (GFC_INTEGER_4
));
333 if (rank
!= GFC_DESCRIPTOR_RANK (retarray
))
334 runtime_error ("rank of return array incorrect in MAXLOC intrinsic");
336 if (unlikely (compile_options
.bounds_check
))
338 bounds_ifunction_return ((array_t
*) retarray
, extent
,
339 "return value", "MAXLOC");
340 bounds_equal_extents ((array_t
*) mask
, (array_t
*) array
,
341 "MASK argument", "MAXLOC");
345 for (n
= 0; n
< rank
; n
++)
348 dstride
[n
] = GFC_DESCRIPTOR_STRIDE(retarray
,n
);
353 dest
= retarray
->base_addr
;
354 base
= array
->base_addr
;
358 const GFC_REAL_10
* restrict src
;
359 const GFC_LOGICAL_1
* restrict msrc
;
360 GFC_INTEGER_4 result
;
366 #if defined (GFC_REAL_10_INFINITY)
367 maxval
= -GFC_REAL_10_INFINITY
;
369 maxval
= -GFC_REAL_10_HUGE
;
371 #if defined (GFC_REAL_10_QUIET_NAN)
372 GFC_INTEGER_4 result2
= 0;
375 for (n
= 0; n
< len
; n
++, src
+= delta
, msrc
+= mdelta
)
380 #if defined (GFC_REAL_10_QUIET_NAN)
382 result2
= (GFC_INTEGER_4
)n
+ 1;
387 result
= (GFC_INTEGER_4
)n
+ 1;
392 #if defined (GFC_REAL_10_QUIET_NAN)
393 if (unlikely (n
>= len
))
398 for (; n
< len
; n
++, src
+= delta
, msrc
+= mdelta
)
400 if (*msrc
&& unlikely (*src
>= maxval
))
403 result
= (GFC_INTEGER_4
)n
+ 1;
407 for (; n
< len
; n
++, src
+= delta
, msrc
+= mdelta
)
409 if (*msrc
&& unlikely (*src
> maxval
))
412 result
= (GFC_INTEGER_4
)n
+ 1;
417 /* Advance to the next element. */
423 while (count
[n
] == extent
[n
])
425 /* When we get to the end of a dimension, reset it and increment
426 the next dimension. */
428 /* We could precalculate these products, but this is a less
429 frequently used path so probably not worth it. */
430 base
-= sstride
[n
] * extent
[n
];
431 mbase
-= mstride
[n
] * extent
[n
];
432 dest
-= dstride
[n
] * extent
[n
];
436 /* Break out of the loop. */
452 extern void smaxloc1_4_r10 (gfc_array_i4
* const restrict
,
453 gfc_array_r10
* const restrict
, const index_type
* const restrict
,
454 GFC_LOGICAL_4
*, GFC_LOGICAL_4 back
);
455 export_proto(smaxloc1_4_r10
);
458 smaxloc1_4_r10 (gfc_array_i4
* const restrict retarray
,
459 gfc_array_r10
* const restrict array
,
460 const index_type
* const restrict pdim
,
461 GFC_LOGICAL_4
* mask
, GFC_LOGICAL_4 back
)
463 index_type count
[GFC_MAX_DIMENSIONS
];
464 index_type extent
[GFC_MAX_DIMENSIONS
];
465 index_type dstride
[GFC_MAX_DIMENSIONS
];
466 GFC_INTEGER_4
* restrict dest
;
472 if (mask
== NULL
|| *mask
)
475 maxloc1_4_r10 (retarray
, array
, pdim
, back
);
477 maxloc1_4_r10 (retarray
, array
, pdim
);
481 /* Make dim zero based to avoid confusion. */
483 rank
= GFC_DESCRIPTOR_RANK (array
) - 1;
485 if (unlikely (dim
< 0 || dim
> rank
))
487 runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
488 "is %ld, should be between 1 and %ld",
489 (long int) dim
+ 1, (long int) rank
+ 1);
492 for (n
= 0; n
< dim
; n
++)
494 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
,n
);
500 for (n
= dim
; n
< rank
; n
++)
503 GFC_DESCRIPTOR_EXTENT(array
,n
+ 1);
509 if (retarray
->base_addr
== NULL
)
511 size_t alloc_size
, str
;
513 for (n
= 0; n
< rank
; n
++)
518 str
= GFC_DESCRIPTOR_STRIDE(retarray
,n
-1) * extent
[n
-1];
520 GFC_DIMENSION_SET(retarray
->dim
[n
], 0, extent
[n
] - 1, str
);
524 retarray
->offset
= 0;
525 retarray
->dtype
.rank
= rank
;
527 alloc_size
= GFC_DESCRIPTOR_STRIDE(retarray
,rank
-1) * extent
[rank
-1];
529 retarray
->base_addr
= xmallocarray (alloc_size
, sizeof (GFC_INTEGER_4
));
535 if (rank
!= GFC_DESCRIPTOR_RANK (retarray
))
536 runtime_error ("rank of return array incorrect in"
537 " MAXLOC intrinsic: is %ld, should be %ld",
538 (long int) (GFC_DESCRIPTOR_RANK (retarray
)),
541 if (unlikely (compile_options
.bounds_check
))
543 for (n
=0; n
< rank
; n
++)
545 index_type ret_extent
;
547 ret_extent
= GFC_DESCRIPTOR_EXTENT(retarray
,n
);
548 if (extent
[n
] != ret_extent
)
549 runtime_error ("Incorrect extent in return value of"
550 " MAXLOC intrinsic in dimension %ld:"
551 " is %ld, should be %ld", (long int) n
+ 1,
552 (long int) ret_extent
, (long int) extent
[n
]);
557 for (n
= 0; n
< rank
; n
++)
560 dstride
[n
] = GFC_DESCRIPTOR_STRIDE(retarray
,n
);
563 dest
= retarray
->base_addr
;
571 while (count
[n
] == extent
[n
])
573 /* When we get to the end of a dimension, reset it and increment
574 the next dimension. */
576 /* We could precalculate these products, but this is a less
577 frequently used path so probably not worth it. */
578 dest
-= dstride
[n
] * extent
[n
];