1 /* Implementation of the MAXVAL intrinsic
2 Copyright 2002, 2007 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
5 This file is part of the GNU Fortran 95 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 2 of the License, or (at your option) any later version.
12 In addition to the permissions in the GNU General Public License, the
13 Free Software Foundation gives you unlimited permission to link the
14 compiled version of this file into combinations with other programs,
15 and to distribute those combinations without any restriction coming
16 from the use of this file. (The General Public License restrictions
17 do apply in other respects; for example, they cover modification of
18 the file, and distribution when not linked into a combine
21 Libgfortran is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public
27 License along with libgfortran; see the file COPYING. If not,
28 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
29 Boston, MA 02110-1301, USA. */
31 #include "libgfortran.h"
36 #if defined (HAVE_GFC_REAL_8) && defined (HAVE_GFC_REAL_8)
39 extern void maxval_r8 (gfc_array_r8
* const restrict
,
40 gfc_array_r8
* const restrict
, const index_type
* const restrict
);
41 export_proto(maxval_r8
);
44 maxval_r8 (gfc_array_r8
* const restrict retarray
,
45 gfc_array_r8
* const restrict array
,
46 const index_type
* const restrict pdim
)
48 index_type count
[GFC_MAX_DIMENSIONS
];
49 index_type extent
[GFC_MAX_DIMENSIONS
];
50 index_type sstride
[GFC_MAX_DIMENSIONS
];
51 index_type dstride
[GFC_MAX_DIMENSIONS
];
52 const GFC_REAL_8
* restrict base
;
53 GFC_REAL_8
* restrict dest
;
61 /* Make dim zero based to avoid confusion. */
63 rank
= GFC_DESCRIPTOR_RANK (array
) - 1;
65 len
= array
->dim
[dim
].ubound
+ 1 - array
->dim
[dim
].lbound
;
68 delta
= array
->dim
[dim
].stride
;
70 for (n
= 0; n
< dim
; n
++)
72 sstride
[n
] = array
->dim
[n
].stride
;
73 extent
[n
] = array
->dim
[n
].ubound
+ 1 - array
->dim
[n
].lbound
;
78 for (n
= dim
; n
< rank
; n
++)
80 sstride
[n
] = array
->dim
[n
+ 1].stride
;
82 array
->dim
[n
+ 1].ubound
+ 1 - array
->dim
[n
+ 1].lbound
;
88 if (retarray
->data
== NULL
)
92 for (n
= 0; n
< rank
; n
++)
94 retarray
->dim
[n
].lbound
= 0;
95 retarray
->dim
[n
].ubound
= extent
[n
]-1;
97 retarray
->dim
[n
].stride
= 1;
99 retarray
->dim
[n
].stride
= retarray
->dim
[n
-1].stride
* extent
[n
-1];
102 retarray
->offset
= 0;
103 retarray
->dtype
= (array
->dtype
& ~GFC_DTYPE_RANK_MASK
) | rank
;
105 alloc_size
= sizeof (GFC_REAL_8
) * retarray
->dim
[rank
-1].stride
110 /* Make sure we have a zero-sized array. */
111 retarray
->dim
[0].lbound
= 0;
112 retarray
->dim
[0].ubound
= -1;
116 retarray
->data
= internal_malloc_size (alloc_size
);
120 if (rank
!= GFC_DESCRIPTOR_RANK (retarray
))
121 runtime_error ("rank of return array incorrect in"
122 " MAXVAL intrinsic: is %ld, should be %ld",
123 (long int) (GFC_DESCRIPTOR_RANK (retarray
)),
126 if (compile_options
.bounds_check
)
128 for (n
=0; n
< rank
; n
++)
130 index_type ret_extent
;
132 ret_extent
= retarray
->dim
[n
].ubound
+ 1
133 - retarray
->dim
[n
].lbound
;
134 if (extent
[n
] != ret_extent
)
135 runtime_error ("Incorrect extent in return value of"
136 " MAXVAL intrinsic in dimension %ld:"
137 " is %ld, should be %ld", (long int) n
+ 1,
138 (long int) ret_extent
, (long int) extent
[n
]);
143 for (n
= 0; n
< rank
; n
++)
146 dstride
[n
] = retarray
->dim
[n
].stride
;
152 dest
= retarray
->data
;
155 while (continue_loop
)
157 const GFC_REAL_8
* restrict src
;
162 result
= -GFC_REAL_8_HUGE
;
164 *dest
= -GFC_REAL_8_HUGE
;
167 for (n
= 0; n
< len
; n
++, src
+= delta
)
176 /* Advance to the next element. */
181 while (count
[n
] == extent
[n
])
183 /* When we get to the end of a dimension, reset it and increment
184 the next dimension. */
186 /* We could precalculate these products, but this is a less
187 frequently used path so probably not worth it. */
188 base
-= sstride
[n
] * extent
[n
];
189 dest
-= dstride
[n
] * extent
[n
];
193 /* Break out of the look. */
208 extern void mmaxval_r8 (gfc_array_r8
* const restrict
,
209 gfc_array_r8
* const restrict
, const index_type
* const restrict
,
210 gfc_array_l1
* const restrict
);
211 export_proto(mmaxval_r8
);
214 mmaxval_r8 (gfc_array_r8
* const restrict retarray
,
215 gfc_array_r8
* const restrict array
,
216 const index_type
* const restrict pdim
,
217 gfc_array_l1
* const restrict mask
)
219 index_type count
[GFC_MAX_DIMENSIONS
];
220 index_type extent
[GFC_MAX_DIMENSIONS
];
221 index_type sstride
[GFC_MAX_DIMENSIONS
];
222 index_type dstride
[GFC_MAX_DIMENSIONS
];
223 index_type mstride
[GFC_MAX_DIMENSIONS
];
224 GFC_REAL_8
* restrict dest
;
225 const GFC_REAL_8
* restrict base
;
226 const GFC_LOGICAL_1
* restrict mbase
;
236 rank
= GFC_DESCRIPTOR_RANK (array
) - 1;
238 len
= array
->dim
[dim
].ubound
+ 1 - array
->dim
[dim
].lbound
;
244 mask_kind
= GFC_DESCRIPTOR_SIZE (mask
);
246 if (mask_kind
== 1 || mask_kind
== 2 || mask_kind
== 4 || mask_kind
== 8
247 #ifdef HAVE_GFC_LOGICAL_16
251 mbase
= GFOR_POINTER_TO_L1 (mbase
, mask_kind
);
253 runtime_error ("Funny sized logical array");
255 delta
= array
->dim
[dim
].stride
;
256 mdelta
= mask
->dim
[dim
].stride
* mask_kind
;
258 for (n
= 0; n
< dim
; n
++)
260 sstride
[n
] = array
->dim
[n
].stride
;
261 mstride
[n
] = mask
->dim
[n
].stride
* mask_kind
;
262 extent
[n
] = array
->dim
[n
].ubound
+ 1 - array
->dim
[n
].lbound
;
268 for (n
= dim
; n
< rank
; n
++)
270 sstride
[n
] = array
->dim
[n
+ 1].stride
;
271 mstride
[n
] = mask
->dim
[n
+ 1].stride
* mask_kind
;
273 array
->dim
[n
+ 1].ubound
+ 1 - array
->dim
[n
+ 1].lbound
;
279 if (retarray
->data
== NULL
)
283 for (n
= 0; n
< rank
; n
++)
285 retarray
->dim
[n
].lbound
= 0;
286 retarray
->dim
[n
].ubound
= extent
[n
]-1;
288 retarray
->dim
[n
].stride
= 1;
290 retarray
->dim
[n
].stride
= retarray
->dim
[n
-1].stride
* extent
[n
-1];
293 alloc_size
= sizeof (GFC_REAL_8
) * retarray
->dim
[rank
-1].stride
296 retarray
->offset
= 0;
297 retarray
->dtype
= (array
->dtype
& ~GFC_DTYPE_RANK_MASK
) | rank
;
301 /* Make sure we have a zero-sized array. */
302 retarray
->dim
[0].lbound
= 0;
303 retarray
->dim
[0].ubound
= -1;
307 retarray
->data
= internal_malloc_size (alloc_size
);
312 if (rank
!= GFC_DESCRIPTOR_RANK (retarray
))
313 runtime_error ("rank of return array incorrect in MAXVAL intrinsic");
315 if (compile_options
.bounds_check
)
317 for (n
=0; n
< rank
; n
++)
319 index_type ret_extent
;
321 ret_extent
= retarray
->dim
[n
].ubound
+ 1
322 - retarray
->dim
[n
].lbound
;
323 if (extent
[n
] != ret_extent
)
324 runtime_error ("Incorrect extent in return value of"
325 " MAXVAL intrinsic in dimension %ld:"
326 " is %ld, should be %ld", (long int) n
+ 1,
327 (long int) ret_extent
, (long int) extent
[n
]);
329 for (n
=0; n
<= rank
; n
++)
331 index_type mask_extent
, array_extent
;
333 array_extent
= array
->dim
[n
].ubound
+ 1 - array
->dim
[n
].lbound
;
334 mask_extent
= mask
->dim
[n
].ubound
+ 1 - mask
->dim
[n
].lbound
;
335 if (array_extent
!= mask_extent
)
336 runtime_error ("Incorrect extent in MASK argument of"
337 " MAXVAL intrinsic in dimension %ld:"
338 " is %ld, should be %ld", (long int) n
+ 1,
339 (long int) mask_extent
, (long int) array_extent
);
344 for (n
= 0; n
< rank
; n
++)
347 dstride
[n
] = retarray
->dim
[n
].stride
;
352 dest
= retarray
->data
;
357 const GFC_REAL_8
* restrict src
;
358 const GFC_LOGICAL_1
* restrict msrc
;
364 result
= -GFC_REAL_8_HUGE
;
366 *dest
= -GFC_REAL_8_HUGE
;
369 for (n
= 0; n
< len
; n
++, src
+= delta
, msrc
+= mdelta
)
372 if (*msrc
&& *src
> result
)
378 /* Advance to the next element. */
384 while (count
[n
] == extent
[n
])
386 /* When we get to the end of a dimension, reset it and increment
387 the next dimension. */
389 /* We could precalculate these products, but this is a less
390 frequently used path so probably not worth it. */
391 base
-= sstride
[n
] * extent
[n
];
392 mbase
-= mstride
[n
] * extent
[n
];
393 dest
-= dstride
[n
] * extent
[n
];
397 /* Break out of the look. */
413 extern void smaxval_r8 (gfc_array_r8
* const restrict
,
414 gfc_array_r8
* const restrict
, const index_type
* const restrict
,
416 export_proto(smaxval_r8
);
419 smaxval_r8 (gfc_array_r8
* const restrict retarray
,
420 gfc_array_r8
* const restrict array
,
421 const index_type
* const restrict pdim
,
422 GFC_LOGICAL_4
* mask
)
424 index_type count
[GFC_MAX_DIMENSIONS
];
425 index_type extent
[GFC_MAX_DIMENSIONS
];
426 index_type sstride
[GFC_MAX_DIMENSIONS
];
427 index_type dstride
[GFC_MAX_DIMENSIONS
];
428 GFC_REAL_8
* restrict dest
;
436 maxval_r8 (retarray
, array
, pdim
);
439 /* Make dim zero based to avoid confusion. */
441 rank
= GFC_DESCRIPTOR_RANK (array
) - 1;
443 for (n
= 0; n
< dim
; n
++)
445 sstride
[n
] = array
->dim
[n
].stride
;
446 extent
[n
] = array
->dim
[n
].ubound
+ 1 - array
->dim
[n
].lbound
;
452 for (n
= dim
; n
< rank
; n
++)
454 sstride
[n
] = array
->dim
[n
+ 1].stride
;
456 array
->dim
[n
+ 1].ubound
+ 1 - array
->dim
[n
+ 1].lbound
;
462 if (retarray
->data
== NULL
)
466 for (n
= 0; n
< rank
; n
++)
468 retarray
->dim
[n
].lbound
= 0;
469 retarray
->dim
[n
].ubound
= extent
[n
]-1;
471 retarray
->dim
[n
].stride
= 1;
473 retarray
->dim
[n
].stride
= retarray
->dim
[n
-1].stride
* extent
[n
-1];
476 retarray
->offset
= 0;
477 retarray
->dtype
= (array
->dtype
& ~GFC_DTYPE_RANK_MASK
) | rank
;
479 alloc_size
= sizeof (GFC_REAL_8
) * retarray
->dim
[rank
-1].stride
484 /* Make sure we have a zero-sized array. */
485 retarray
->dim
[0].lbound
= 0;
486 retarray
->dim
[0].ubound
= -1;
490 retarray
->data
= internal_malloc_size (alloc_size
);
494 if (rank
!= GFC_DESCRIPTOR_RANK (retarray
))
495 runtime_error ("rank of return array incorrect in"
496 " MAXVAL intrinsic: is %ld, should be %ld",
497 (long int) (GFC_DESCRIPTOR_RANK (retarray
)),
500 if (compile_options
.bounds_check
)
502 for (n
=0; n
< rank
; n
++)
504 index_type ret_extent
;
506 ret_extent
= retarray
->dim
[n
].ubound
+ 1
507 - retarray
->dim
[n
].lbound
;
508 if (extent
[n
] != ret_extent
)
509 runtime_error ("Incorrect extent in return value of"
510 " MAXVAL intrinsic in dimension %ld:"
511 " is %ld, should be %ld", (long int) n
+ 1,
512 (long int) ret_extent
, (long int) extent
[n
]);
517 for (n
= 0; n
< rank
; n
++)
520 dstride
[n
] = retarray
->dim
[n
].stride
;
523 dest
= retarray
->data
;
527 *dest
= -GFC_REAL_8_HUGE
;
531 while (count
[n
] == extent
[n
])
533 /* When we get to the end of a dimension, reset it and increment
534 the next dimension. */
536 /* We could precalculate these products, but this is a less
537 frequently used path so probably not worth it. */
538 dest
-= dstride
[n
] * extent
[n
];