1 /* Implementation of the MINVAL intrinsic
2 Copyright (C) 2002-2017 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"
29 #if defined (HAVE_GFC_REAL_16) && defined (HAVE_GFC_REAL_16)
32 extern void minval_r16 (gfc_array_r16
* const restrict
,
33 gfc_array_r16
* const restrict
, const index_type
* const restrict
);
34 export_proto(minval_r16
);
37 minval_r16 (gfc_array_r16
* const restrict retarray
,
38 gfc_array_r16
* const restrict array
,
39 const index_type
* const restrict pdim
)
41 index_type count
[GFC_MAX_DIMENSIONS
];
42 index_type extent
[GFC_MAX_DIMENSIONS
];
43 index_type sstride
[GFC_MAX_DIMENSIONS
];
44 index_type dstride
[GFC_MAX_DIMENSIONS
];
45 const GFC_REAL_16
* restrict base
;
46 GFC_REAL_16
* restrict dest
;
54 /* Make dim zero based to avoid confusion. */
56 rank
= GFC_DESCRIPTOR_RANK (array
) - 1;
58 len
= GFC_DESCRIPTOR_EXTENT(array
,dim
);
61 delta
= GFC_DESCRIPTOR_STRIDE(array
,dim
);
63 for (n
= 0; n
< dim
; n
++)
65 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(array
,n
);
66 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
,n
);
71 for (n
= dim
; n
< rank
; n
++)
73 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(array
, n
+ 1);
74 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
, n
+ 1);
80 if (retarray
->base_addr
== NULL
)
82 size_t alloc_size
, str
;
84 for (n
= 0; n
< rank
; n
++)
89 str
= GFC_DESCRIPTOR_STRIDE(retarray
,n
-1) * extent
[n
-1];
91 GFC_DIMENSION_SET(retarray
->dim
[n
], 0, extent
[n
] - 1, str
);
96 retarray
->dtype
= (array
->dtype
& ~GFC_DTYPE_RANK_MASK
) | rank
;
98 alloc_size
= GFC_DESCRIPTOR_STRIDE(retarray
,rank
-1) * extent
[rank
-1];
100 retarray
->base_addr
= xmallocarray (alloc_size
, sizeof (GFC_REAL_16
));
103 /* Make sure we have a zero-sized array. */
104 GFC_DIMENSION_SET(retarray
->dim
[0], 0, -1, 1);
111 if (rank
!= GFC_DESCRIPTOR_RANK (retarray
))
112 runtime_error ("rank of return array incorrect in"
113 " MINVAL intrinsic: is %ld, should be %ld",
114 (long int) (GFC_DESCRIPTOR_RANK (retarray
)),
117 if (unlikely (compile_options
.bounds_check
))
118 bounds_ifunction_return ((array_t
*) retarray
, extent
,
119 "return value", "MINVAL");
122 for (n
= 0; n
< rank
; n
++)
125 dstride
[n
] = GFC_DESCRIPTOR_STRIDE(retarray
,n
);
130 base
= array
->base_addr
;
131 dest
= retarray
->base_addr
;
134 while (continue_loop
)
136 const GFC_REAL_16
* restrict src
;
141 #if defined (GFC_REAL_16_INFINITY)
142 result
= GFC_REAL_16_INFINITY
;
144 result
= GFC_REAL_16_HUGE
;
147 *dest
= GFC_REAL_16_HUGE
;
150 for (n
= 0; n
< len
; n
++, src
+= delta
)
153 #if defined (GFC_REAL_16_QUIET_NAN)
157 if (unlikely (n
>= len
))
158 result
= GFC_REAL_16_QUIET_NAN
;
159 else for (; n
< len
; n
++, src
+= delta
)
169 /* Advance to the next element. */
174 while (count
[n
] == extent
[n
])
176 /* When we get to the end of a dimension, reset it and increment
177 the next dimension. */
179 /* We could precalculate these products, but this is a less
180 frequently used path so probably not worth it. */
181 base
-= sstride
[n
] * extent
[n
];
182 dest
-= dstride
[n
] * extent
[n
];
186 /* Break out of the loop. */
201 extern void mminval_r16 (gfc_array_r16
* const restrict
,
202 gfc_array_r16
* const restrict
, const index_type
* const restrict
,
203 gfc_array_l1
* const restrict
);
204 export_proto(mminval_r16
);
207 mminval_r16 (gfc_array_r16
* const restrict retarray
,
208 gfc_array_r16
* const restrict array
,
209 const index_type
* const restrict pdim
,
210 gfc_array_l1
* const restrict mask
)
212 index_type count
[GFC_MAX_DIMENSIONS
];
213 index_type extent
[GFC_MAX_DIMENSIONS
];
214 index_type sstride
[GFC_MAX_DIMENSIONS
];
215 index_type dstride
[GFC_MAX_DIMENSIONS
];
216 index_type mstride
[GFC_MAX_DIMENSIONS
];
217 GFC_REAL_16
* restrict dest
;
218 const GFC_REAL_16
* restrict base
;
219 const GFC_LOGICAL_1
* restrict mbase
;
229 rank
= GFC_DESCRIPTOR_RANK (array
) - 1;
231 len
= GFC_DESCRIPTOR_EXTENT(array
,dim
);
235 mbase
= mask
->base_addr
;
237 mask_kind
= GFC_DESCRIPTOR_SIZE (mask
);
239 if (mask_kind
== 1 || mask_kind
== 2 || mask_kind
== 4 || mask_kind
== 8
240 #ifdef HAVE_GFC_LOGICAL_16
244 mbase
= GFOR_POINTER_TO_L1 (mbase
, mask_kind
);
246 runtime_error ("Funny sized logical array");
248 delta
= GFC_DESCRIPTOR_STRIDE(array
,dim
);
249 mdelta
= GFC_DESCRIPTOR_STRIDE_BYTES(mask
,dim
);
251 for (n
= 0; n
< dim
; n
++)
253 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(array
,n
);
254 mstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(mask
,n
);
255 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
,n
);
261 for (n
= dim
; n
< rank
; n
++)
263 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(array
,n
+ 1);
264 mstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(mask
, n
+ 1);
265 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
, n
+ 1);
271 if (retarray
->base_addr
== NULL
)
273 size_t alloc_size
, str
;
275 for (n
= 0; n
< rank
; n
++)
280 str
= GFC_DESCRIPTOR_STRIDE(retarray
,n
-1) * extent
[n
-1];
282 GFC_DIMENSION_SET(retarray
->dim
[n
], 0, extent
[n
] - 1, str
);
286 alloc_size
= GFC_DESCRIPTOR_STRIDE(retarray
,rank
-1) * extent
[rank
-1];
288 retarray
->offset
= 0;
289 retarray
->dtype
= (array
->dtype
& ~GFC_DTYPE_RANK_MASK
) | rank
;
293 /* Make sure we have a zero-sized array. */
294 GFC_DIMENSION_SET(retarray
->dim
[0], 0, -1, 1);
298 retarray
->base_addr
= xmallocarray (alloc_size
, sizeof (GFC_REAL_16
));
303 if (rank
!= GFC_DESCRIPTOR_RANK (retarray
))
304 runtime_error ("rank of return array incorrect in MINVAL intrinsic");
306 if (unlikely (compile_options
.bounds_check
))
308 bounds_ifunction_return ((array_t
*) retarray
, extent
,
309 "return value", "MINVAL");
310 bounds_equal_extents ((array_t
*) mask
, (array_t
*) array
,
311 "MASK argument", "MINVAL");
315 for (n
= 0; n
< rank
; n
++)
318 dstride
[n
] = GFC_DESCRIPTOR_STRIDE(retarray
,n
);
323 dest
= retarray
->base_addr
;
324 base
= array
->base_addr
;
328 const GFC_REAL_16
* restrict src
;
329 const GFC_LOGICAL_1
* restrict msrc
;
335 #if defined (GFC_REAL_16_INFINITY)
336 result
= GFC_REAL_16_INFINITY
;
338 result
= GFC_REAL_16_HUGE
;
340 #if defined (GFC_REAL_16_QUIET_NAN)
343 for (n
= 0; n
< len
; n
++, src
+= delta
, msrc
+= mdelta
)
346 #if defined (GFC_REAL_16_INFINITY) || defined (GFC_REAL_16_QUIET_NAN)
349 #if defined (GFC_REAL_16_QUIET_NAN)
356 if (unlikely (n
>= len
))
358 #if defined (GFC_REAL_16_QUIET_NAN)
359 result
= non_empty_p
? GFC_REAL_16_QUIET_NAN
: GFC_REAL_16_HUGE
;
361 result
= GFC_REAL_16_HUGE
;
364 else for (; n
< len
; n
++, src
+= delta
, msrc
+= mdelta
)
367 if (*msrc
&& *src
< result
)
372 /* Advance to the next element. */
378 while (count
[n
] == extent
[n
])
380 /* When we get to the end of a dimension, reset it and increment
381 the next dimension. */
383 /* We could precalculate these products, but this is a less
384 frequently used path so probably not worth it. */
385 base
-= sstride
[n
] * extent
[n
];
386 mbase
-= mstride
[n
] * extent
[n
];
387 dest
-= dstride
[n
] * extent
[n
];
391 /* Break out of the loop. */
407 extern void sminval_r16 (gfc_array_r16
* const restrict
,
408 gfc_array_r16
* const restrict
, const index_type
* const restrict
,
410 export_proto(sminval_r16
);
413 sminval_r16 (gfc_array_r16
* const restrict retarray
,
414 gfc_array_r16
* const restrict array
,
415 const index_type
* const restrict pdim
,
416 GFC_LOGICAL_4
* mask
)
418 index_type count
[GFC_MAX_DIMENSIONS
];
419 index_type extent
[GFC_MAX_DIMENSIONS
];
420 index_type dstride
[GFC_MAX_DIMENSIONS
];
421 GFC_REAL_16
* restrict dest
;
429 minval_r16 (retarray
, array
, pdim
);
432 /* Make dim zero based to avoid confusion. */
434 rank
= GFC_DESCRIPTOR_RANK (array
) - 1;
436 for (n
= 0; n
< dim
; n
++)
438 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
,n
);
444 for (n
= dim
; n
< rank
; n
++)
447 GFC_DESCRIPTOR_EXTENT(array
,n
+ 1);
453 if (retarray
->base_addr
== NULL
)
455 size_t alloc_size
, str
;
457 for (n
= 0; n
< rank
; n
++)
462 str
= GFC_DESCRIPTOR_STRIDE(retarray
,n
-1) * extent
[n
-1];
464 GFC_DIMENSION_SET(retarray
->dim
[n
], 0, extent
[n
] - 1, str
);
468 retarray
->offset
= 0;
469 retarray
->dtype
= (array
->dtype
& ~GFC_DTYPE_RANK_MASK
) | rank
;
471 alloc_size
= GFC_DESCRIPTOR_STRIDE(retarray
,rank
-1) * extent
[rank
-1];
475 /* Make sure we have a zero-sized array. */
476 GFC_DIMENSION_SET(retarray
->dim
[0], 0, -1, 1);
480 retarray
->base_addr
= xmallocarray (alloc_size
, sizeof (GFC_REAL_16
));
484 if (rank
!= GFC_DESCRIPTOR_RANK (retarray
))
485 runtime_error ("rank of return array incorrect in"
486 " MINVAL intrinsic: is %ld, should be %ld",
487 (long int) (GFC_DESCRIPTOR_RANK (retarray
)),
490 if (unlikely (compile_options
.bounds_check
))
492 for (n
=0; n
< rank
; n
++)
494 index_type ret_extent
;
496 ret_extent
= GFC_DESCRIPTOR_EXTENT(retarray
,n
);
497 if (extent
[n
] != ret_extent
)
498 runtime_error ("Incorrect extent in return value of"
499 " MINVAL intrinsic in dimension %ld:"
500 " is %ld, should be %ld", (long int) n
+ 1,
501 (long int) ret_extent
, (long int) extent
[n
]);
506 for (n
= 0; n
< rank
; n
++)
509 dstride
[n
] = GFC_DESCRIPTOR_STRIDE(retarray
,n
);
512 dest
= retarray
->base_addr
;
516 *dest
= GFC_REAL_16_HUGE
;
520 while (count
[n
] == extent
[n
])
522 /* When we get to the end of a dimension, reset it and increment
523 the next dimension. */
525 /* We could precalculate these products, but this is a less
526 frequently used path so probably not worth it. */
527 dest
-= dstride
[n
] * extent
[n
];