1 /* Implementation of the FINDLOC intrinsic
2 Copyright (C) 2018-2024 Free Software Foundation, Inc.
3 Contributed by Thomas König <tk@tkoenig.net>
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 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)
30 extern void findloc1_r16 (gfc_array_index_type
* const restrict retarray
,
31 gfc_array_r16
* const restrict array
, GFC_REAL_16 value
,
32 const index_type
* restrict pdim
, GFC_LOGICAL_4 back
);
33 export_proto(findloc1_r16
);
36 findloc1_r16 (gfc_array_index_type
* const restrict retarray
,
37 gfc_array_r16
* const restrict array
, GFC_REAL_16 value
,
38 const index_type
* restrict pdim
, GFC_LOGICAL_4 back
)
40 index_type count
[GFC_MAX_DIMENSIONS
];
41 index_type extent
[GFC_MAX_DIMENSIONS
];
42 index_type sstride
[GFC_MAX_DIMENSIONS
];
43 index_type dstride
[GFC_MAX_DIMENSIONS
];
44 const GFC_REAL_16
* restrict base
;
45 index_type
* restrict dest
;
53 /* Make dim zero based to avoid confusion. */
54 rank
= GFC_DESCRIPTOR_RANK (array
) - 1;
57 if (unlikely (dim
< 0 || dim
> rank
))
59 runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
60 "is %ld, should be between 1 and %ld",
61 (long int) dim
+ 1, (long int) rank
+ 1);
64 len
= GFC_DESCRIPTOR_EXTENT(array
,dim
);
67 delta
= GFC_DESCRIPTOR_STRIDE(array
,dim
);
69 for (n
= 0; n
< dim
; n
++)
71 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(array
,n
);
72 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
,n
);
77 for (n
= dim
; n
< rank
; n
++)
79 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(array
, n
+ 1);
80 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
, n
+ 1);
86 if (retarray
->base_addr
== NULL
)
88 size_t alloc_size
, str
;
90 for (n
= 0; n
< rank
; n
++)
95 str
= GFC_DESCRIPTOR_STRIDE(retarray
,n
-1) * extent
[n
-1];
97 GFC_DIMENSION_SET(retarray
->dim
[n
], 0, extent
[n
] - 1, str
);
101 retarray
->offset
= 0;
102 retarray
->dtype
.rank
= rank
;
104 alloc_size
= GFC_DESCRIPTOR_STRIDE(retarray
,rank
-1) * extent
[rank
-1];
106 retarray
->base_addr
= xmallocarray (alloc_size
, sizeof (index_type
));
112 if (rank
!= GFC_DESCRIPTOR_RANK (retarray
))
113 runtime_error ("rank of return array incorrect in"
114 " FINDLOC intrinsic: is %ld, should be %ld",
115 (long int) (GFC_DESCRIPTOR_RANK (retarray
)),
118 if (unlikely (compile_options
.bounds_check
))
119 bounds_ifunction_return ((array_t
*) retarray
, extent
,
120 "return value", "FINDLOC");
123 for (n
= 0; n
< rank
; n
++)
126 dstride
[n
] = GFC_DESCRIPTOR_STRIDE(retarray
,n
);
131 dest
= retarray
->base_addr
;
134 base
= array
->base_addr
;
135 while (continue_loop
)
137 const GFC_REAL_16
* restrict src
;
143 src
= base
+ (len
- 1) * delta
* 1;
144 for (n
= len
; n
> 0; n
--, src
-= delta
* 1)
156 for (n
= 1; n
<= len
; n
++, src
+= delta
* 1)
168 base
+= sstride
[0] * 1;
171 while (count
[n
] == extent
[n
])
174 base
-= sstride
[n
] * extent
[n
] * 1;
175 dest
-= dstride
[n
] * extent
[n
];
185 base
+= sstride
[n
] * 1;
191 extern void mfindloc1_r16 (gfc_array_index_type
* const restrict retarray
,
192 gfc_array_r16
* const restrict array
, GFC_REAL_16 value
,
193 const index_type
* restrict pdim
, gfc_array_l1
*const restrict mask
,
195 export_proto(mfindloc1_r16
);
198 mfindloc1_r16 (gfc_array_index_type
* const restrict retarray
,
199 gfc_array_r16
* const restrict array
, GFC_REAL_16 value
,
200 const index_type
* restrict pdim
, gfc_array_l1
*const restrict mask
,
203 index_type count
[GFC_MAX_DIMENSIONS
];
204 index_type extent
[GFC_MAX_DIMENSIONS
];
205 index_type sstride
[GFC_MAX_DIMENSIONS
];
206 index_type mstride
[GFC_MAX_DIMENSIONS
];
207 index_type dstride
[GFC_MAX_DIMENSIONS
];
208 const GFC_REAL_16
* restrict base
;
209 const GFC_LOGICAL_1
* restrict mbase
;
210 index_type
* restrict dest
;
220 /* Make dim zero based to avoid confusion. */
221 rank
= GFC_DESCRIPTOR_RANK (array
) - 1;
224 if (unlikely (dim
< 0 || dim
> rank
))
226 runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
227 "is %ld, should be between 1 and %ld",
228 (long int) dim
+ 1, (long int) rank
+ 1);
231 len
= GFC_DESCRIPTOR_EXTENT(array
,dim
);
235 delta
= GFC_DESCRIPTOR_STRIDE(array
,dim
);
236 mdelta
= GFC_DESCRIPTOR_STRIDE_BYTES(mask
,dim
);
238 mbase
= mask
->base_addr
;
240 mask_kind
= GFC_DESCRIPTOR_SIZE (mask
);
242 if (mask_kind
== 1 || mask_kind
== 2 || mask_kind
== 4 || mask_kind
== 8
243 #ifdef HAVE_GFC_LOGICAL_16
247 mbase
= GFOR_POINTER_TO_L1 (mbase
, mask_kind
);
249 internal_error (NULL
, "Funny sized logical array");
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
);
260 for (n
= dim
; n
< rank
; n
++)
262 sstride
[n
] = GFC_DESCRIPTOR_STRIDE(array
, n
+ 1);
263 mstride
[n
] = GFC_DESCRIPTOR_STRIDE_BYTES(mask
, n
+ 1);
264 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
, n
+ 1);
270 if (retarray
->base_addr
== NULL
)
272 size_t alloc_size
, str
;
274 for (n
= 0; n
< rank
; n
++)
279 str
= GFC_DESCRIPTOR_STRIDE(retarray
,n
-1) * extent
[n
-1];
281 GFC_DIMENSION_SET(retarray
->dim
[n
], 0, extent
[n
] - 1, str
);
285 retarray
->offset
= 0;
286 retarray
->dtype
.rank
= rank
;
288 alloc_size
= GFC_DESCRIPTOR_STRIDE(retarray
,rank
-1) * extent
[rank
-1];
290 retarray
->base_addr
= xmallocarray (alloc_size
, sizeof (index_type
));
296 if (rank
!= GFC_DESCRIPTOR_RANK (retarray
))
297 runtime_error ("rank of return array incorrect in"
298 " FINDLOC intrinsic: is %ld, should be %ld",
299 (long int) (GFC_DESCRIPTOR_RANK (retarray
)),
302 if (unlikely (compile_options
.bounds_check
))
303 bounds_ifunction_return ((array_t
*) retarray
, extent
,
304 "return value", "FINDLOC");
307 for (n
= 0; n
< rank
; n
++)
310 dstride
[n
] = GFC_DESCRIPTOR_STRIDE(retarray
,n
);
315 dest
= retarray
->base_addr
;
318 base
= array
->base_addr
;
319 while (continue_loop
)
321 const GFC_REAL_16
* restrict src
;
322 const GFC_LOGICAL_1
* restrict msrc
;
328 src
= base
+ (len
- 1) * delta
* 1;
329 msrc
= mbase
+ (len
- 1) * mdelta
;
330 for (n
= len
; n
> 0; n
--, src
-= delta
* 1, msrc
-= mdelta
)
332 if (*msrc
&& *src
== value
)
343 for (n
= 1; n
<= len
; n
++, src
+= delta
* 1, msrc
+= mdelta
)
345 if (*msrc
&& *src
== value
)
355 base
+= sstride
[0] * 1;
359 while (count
[n
] == extent
[n
])
362 base
-= sstride
[n
] * extent
[n
] * 1;
363 mbase
-= mstride
[n
] * extent
[n
];
364 dest
-= dstride
[n
] * extent
[n
];
374 base
+= sstride
[n
] * 1;
380 extern void sfindloc1_r16 (gfc_array_index_type
* const restrict retarray
,
381 gfc_array_r16
* const restrict array
, GFC_REAL_16 value
,
382 const index_type
* restrict pdim
, GFC_LOGICAL_4
*const restrict mask
,
384 export_proto(sfindloc1_r16
);
387 sfindloc1_r16 (gfc_array_index_type
* const restrict retarray
,
388 gfc_array_r16
* const restrict array
, GFC_REAL_16 value
,
389 const index_type
* restrict pdim
, GFC_LOGICAL_4
*const restrict mask
,
392 index_type count
[GFC_MAX_DIMENSIONS
];
393 index_type extent
[GFC_MAX_DIMENSIONS
];
394 index_type dstride
[GFC_MAX_DIMENSIONS
];
395 index_type
* restrict dest
;
402 if (mask
== NULL
|| *mask
)
404 findloc1_r16 (retarray
, array
, value
, pdim
, back
);
407 /* Make dim zero based to avoid confusion. */
408 rank
= GFC_DESCRIPTOR_RANK (array
) - 1;
411 if (unlikely (dim
< 0 || dim
> rank
))
413 runtime_error ("Dim argument incorrect in FINDLOC intrinsic: "
414 "is %ld, should be between 1 and %ld",
415 (long int) dim
+ 1, (long int) rank
+ 1);
418 len
= GFC_DESCRIPTOR_EXTENT(array
,dim
);
422 for (n
= 0; n
< dim
; n
++)
424 extent
[n
] = GFC_DESCRIPTOR_EXTENT(array
,n
);
430 for (n
= dim
; n
< rank
; n
++)
433 GFC_DESCRIPTOR_EXTENT(array
,n
+ 1);
440 if (retarray
->base_addr
== NULL
)
442 size_t alloc_size
, str
;
444 for (n
= 0; n
< rank
; n
++)
449 str
= GFC_DESCRIPTOR_STRIDE(retarray
,n
-1) * extent
[n
-1];
451 GFC_DIMENSION_SET(retarray
->dim
[n
], 0, extent
[n
] - 1, str
);
454 retarray
->offset
= 0;
455 retarray
->dtype
.rank
= rank
;
457 alloc_size
= GFC_DESCRIPTOR_STRIDE(retarray
,rank
-1) * extent
[rank
-1];
459 retarray
->base_addr
= xmallocarray (alloc_size
, sizeof (index_type
));
465 if (rank
!= GFC_DESCRIPTOR_RANK (retarray
))
466 runtime_error ("rank of return array incorrect in"
467 " FINDLOC intrinsic: is %ld, should be %ld",
468 (long int) (GFC_DESCRIPTOR_RANK (retarray
)),
471 if (unlikely (compile_options
.bounds_check
))
472 bounds_ifunction_return ((array_t
*) retarray
, extent
,
473 "return value", "FINDLOC");
476 for (n
= 0; n
< rank
; n
++)
479 dstride
[n
] = GFC_DESCRIPTOR_STRIDE(retarray
,n
);
483 dest
= retarray
->base_addr
;
486 while (continue_loop
)
493 while (count
[n
] == extent
[n
])
496 dest
-= dstride
[n
] * extent
[n
];