]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgfortran/m4/ifunction.m4
[multiple changes]
[thirdparty/gcc.git] / libgfortran / m4 / ifunction.m4
1 dnl Support macro file for intrinsic functions.
2 dnl Contains the generic sections of the array functions.
3 dnl This file is part of the GNU Fortran 95 Runtime Library (libgfortran)
4 dnl Distributed under the GNU GPL with exception. See COPYING for details.
5 dnl
6 dnl Pass the implementation for a single section as the parameter to
7 dnl {MASK_}ARRAY_FUNCTION.
8 dnl The variables base, delta, and len describe the input section.
9 dnl For masked section the mask is described by mbase and mdelta.
10 dnl These should not be modified. The result should be stored in *dest.
11 dnl The names count, extent, sstride, dstride, base, dest, rank, dim
12 dnl retarray, array, pdim and mstride should not be used.
13 dnl The variable n is declared as index_type and may be used.
14 dnl Other variable declarations may be placed at the start of the code,
15 dnl The types of the array parameter and the return value are
16 dnl atype_name and rtype_name respectively.
17 dnl Execution should be allowed to continue to the end of the block.
18 dnl You should not return or break from the inner loop of the implementation.
19 dnl Care should also be taken to avoid using the names defined in iparm.m4
20 define(START_ARRAY_FUNCTION,
21 `
22 extern void name`'rtype_qual`_'atype_code (rtype * const restrict,
23 atype * const restrict, const index_type * const restrict);
24 export_proto(name`'rtype_qual`_'atype_code);
25
26 void
27 name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
28 atype * const restrict array,
29 const index_type * const restrict pdim)
30 {
31 index_type count[GFC_MAX_DIMENSIONS];
32 index_type extent[GFC_MAX_DIMENSIONS];
33 index_type sstride[GFC_MAX_DIMENSIONS];
34 index_type dstride[GFC_MAX_DIMENSIONS];
35 const atype_name * restrict base;
36 rtype_name * restrict dest;
37 index_type rank;
38 index_type n;
39 index_type len;
40 index_type delta;
41 index_type dim;
42 int continue_loop;
43
44 /* Make dim zero based to avoid confusion. */
45 dim = (*pdim) - 1;
46 rank = GFC_DESCRIPTOR_RANK (array) - 1;
47
48 len = GFC_DESCRIPTOR_EXTENT(array,dim);
49 if (len < 0)
50 len = 0;
51 delta = GFC_DESCRIPTOR_STRIDE(array,dim);
52
53 for (n = 0; n < dim; n++)
54 {
55 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
56 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
57
58 if (extent[n] < 0)
59 extent[n] = 0;
60 }
61 for (n = dim; n < rank; n++)
62 {
63 sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
64 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
65
66 if (extent[n] < 0)
67 extent[n] = 0;
68 }
69
70 if (retarray->data == NULL)
71 {
72 size_t alloc_size, str;
73
74 for (n = 0; n < rank; n++)
75 {
76 if (n == 0)
77 str = 1;
78 else
79 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
80
81 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
82
83 }
84
85 retarray->offset = 0;
86 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
87
88 alloc_size = sizeof (rtype_name) * GFC_DESCRIPTOR_STRIDE(retarray,rank-1)
89 * extent[rank-1];
90
91 if (alloc_size == 0)
92 {
93 /* Make sure we have a zero-sized array. */
94 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
95 return;
96
97 }
98 else
99 retarray->data = internal_malloc_size (alloc_size);
100 }
101 else
102 {
103 if (rank != GFC_DESCRIPTOR_RANK (retarray))
104 runtime_error ("rank of return array incorrect in"
105 " u_name intrinsic: is %ld, should be %ld",
106 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
107 (long int) rank);
108
109 if (unlikely (compile_options.bounds_check))
110 bounds_ifunction_return ((array_t *) retarray, extent,
111 "return value", "u_name");
112 }
113
114 for (n = 0; n < rank; n++)
115 {
116 count[n] = 0;
117 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
118 if (extent[n] <= 0)
119 len = 0;
120 }
121
122 base = array->data;
123 dest = retarray->data;
124
125 continue_loop = 1;
126 while (continue_loop)
127 {
128 const atype_name * restrict src;
129 rtype_name result;
130 src = base;
131 {
132 ')dnl
133 define(START_ARRAY_BLOCK,
134 ` if (len <= 0)
135 *dest = '$1`;
136 else
137 {
138 for (n = 0; n < len; n++, src += delta)
139 {
140 ')dnl
141 define(FINISH_ARRAY_FUNCTION,
142 ` }
143 *dest = result;
144 }
145 }
146 /* Advance to the next element. */
147 count[0]++;
148 base += sstride[0];
149 dest += dstride[0];
150 n = 0;
151 while (count[n] == extent[n])
152 {
153 /* When we get to the end of a dimension, reset it and increment
154 the next dimension. */
155 count[n] = 0;
156 /* We could precalculate these products, but this is a less
157 frequently used path so probably not worth it. */
158 base -= sstride[n] * extent[n];
159 dest -= dstride[n] * extent[n];
160 n++;
161 if (n == rank)
162 {
163 /* Break out of the look. */
164 continue_loop = 0;
165 break;
166 }
167 else
168 {
169 count[n]++;
170 base += sstride[n];
171 dest += dstride[n];
172 }
173 }
174 }
175 }')dnl
176 define(START_MASKED_ARRAY_FUNCTION,
177 `
178 extern void `m'name`'rtype_qual`_'atype_code (rtype * const restrict,
179 atype * const restrict, const index_type * const restrict,
180 gfc_array_l1 * const restrict);
181 export_proto(`m'name`'rtype_qual`_'atype_code);
182
183 void
184 `m'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
185 atype * const restrict array,
186 const index_type * const restrict pdim,
187 gfc_array_l1 * const restrict mask)
188 {
189 index_type count[GFC_MAX_DIMENSIONS];
190 index_type extent[GFC_MAX_DIMENSIONS];
191 index_type sstride[GFC_MAX_DIMENSIONS];
192 index_type dstride[GFC_MAX_DIMENSIONS];
193 index_type mstride[GFC_MAX_DIMENSIONS];
194 rtype_name * restrict dest;
195 const atype_name * restrict base;
196 const GFC_LOGICAL_1 * restrict mbase;
197 int rank;
198 int dim;
199 index_type n;
200 index_type len;
201 index_type delta;
202 index_type mdelta;
203 int mask_kind;
204
205 dim = (*pdim) - 1;
206 rank = GFC_DESCRIPTOR_RANK (array) - 1;
207
208 len = GFC_DESCRIPTOR_EXTENT(array,dim);
209 if (len <= 0)
210 return;
211
212 mbase = mask->data;
213
214 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
215
216 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
217 #ifdef HAVE_GFC_LOGICAL_16
218 || mask_kind == 16
219 #endif
220 )
221 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
222 else
223 runtime_error ("Funny sized logical array");
224
225 delta = GFC_DESCRIPTOR_STRIDE(array,dim);
226 mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
227
228 for (n = 0; n < dim; n++)
229 {
230 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
231 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
232 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
233
234 if (extent[n] < 0)
235 extent[n] = 0;
236
237 }
238 for (n = dim; n < rank; n++)
239 {
240 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
241 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
242 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
243
244 if (extent[n] < 0)
245 extent[n] = 0;
246 }
247
248 if (retarray->data == NULL)
249 {
250 size_t alloc_size, str;
251
252 for (n = 0; n < rank; n++)
253 {
254 if (n == 0)
255 str = 1;
256 else
257 str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
258
259 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
260
261 }
262
263 alloc_size = sizeof (rtype_name) * GFC_DESCRIPTOR_STRIDE(retarray,rank-1)
264 * extent[rank-1];
265
266 retarray->offset = 0;
267 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
268
269 if (alloc_size == 0)
270 {
271 /* Make sure we have a zero-sized array. */
272 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
273 return;
274 }
275 else
276 retarray->data = internal_malloc_size (alloc_size);
277
278 }
279 else
280 {
281 if (rank != GFC_DESCRIPTOR_RANK (retarray))
282 runtime_error ("rank of return array incorrect in u_name intrinsic");
283
284 if (unlikely (compile_options.bounds_check))
285 {
286 bounds_ifunction_return ((array_t *) retarray, extent,
287 "return value", "u_name");
288 bounds_equal_extents ((array_t *) mask, (array_t *) array,
289 "MASK argument", "u_name");
290 }
291 }
292
293 for (n = 0; n < rank; n++)
294 {
295 count[n] = 0;
296 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
297 if (extent[n] <= 0)
298 return;
299 }
300
301 dest = retarray->data;
302 base = array->data;
303
304 while (base)
305 {
306 const atype_name * restrict src;
307 const GFC_LOGICAL_1 * restrict msrc;
308 rtype_name result;
309 src = base;
310 msrc = mbase;
311 {
312 ')dnl
313 define(START_MASKED_ARRAY_BLOCK,
314 ` if (len <= 0)
315 *dest = '$1`;
316 else
317 {
318 for (n = 0; n < len; n++, src += delta, msrc += mdelta)
319 {
320 ')dnl
321 define(FINISH_MASKED_ARRAY_FUNCTION,
322 ` }
323 *dest = result;
324 }
325 }
326 /* Advance to the next element. */
327 count[0]++;
328 base += sstride[0];
329 mbase += mstride[0];
330 dest += dstride[0];
331 n = 0;
332 while (count[n] == extent[n])
333 {
334 /* When we get to the end of a dimension, reset it and increment
335 the next dimension. */
336 count[n] = 0;
337 /* We could precalculate these products, but this is a less
338 frequently used path so probably not worth it. */
339 base -= sstride[n] * extent[n];
340 mbase -= mstride[n] * extent[n];
341 dest -= dstride[n] * extent[n];
342 n++;
343 if (n == rank)
344 {
345 /* Break out of the look. */
346 base = NULL;
347 break;
348 }
349 else
350 {
351 count[n]++;
352 base += sstride[n];
353 mbase += mstride[n];
354 dest += dstride[n];
355 }
356 }
357 }
358 }')dnl
359 define(SCALAR_ARRAY_FUNCTION,
360 `
361 extern void `s'name`'rtype_qual`_'atype_code (rtype * const restrict,
362 atype * const restrict, const index_type * const restrict,
363 GFC_LOGICAL_4 *);
364 export_proto(`s'name`'rtype_qual`_'atype_code);
365
366 void
367 `s'name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
368 atype * const restrict array,
369 const index_type * const restrict pdim,
370 GFC_LOGICAL_4 * mask)
371 {
372 index_type count[GFC_MAX_DIMENSIONS];
373 index_type extent[GFC_MAX_DIMENSIONS];
374 index_type sstride[GFC_MAX_DIMENSIONS];
375 index_type dstride[GFC_MAX_DIMENSIONS];
376 rtype_name * restrict dest;
377 index_type rank;
378 index_type n;
379 index_type dim;
380
381
382 if (*mask)
383 {
384 name`'rtype_qual`_'atype_code (retarray, array, pdim);
385 return;
386 }
387 /* Make dim zero based to avoid confusion. */
388 dim = (*pdim) - 1;
389 rank = GFC_DESCRIPTOR_RANK (array) - 1;
390
391 for (n = 0; n < dim; n++)
392 {
393 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
394 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
395
396 if (extent[n] <= 0)
397 extent[n] = 0;
398 }
399
400 for (n = dim; n < rank; n++)
401 {
402 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
403 extent[n] =
404 GFC_DESCRIPTOR_EXTENT(array,n + 1);
405
406 if (extent[n] <= 0)
407 extent[n] = 0;
408 }
409
410 if (retarray->data == NULL)
411 {
412 size_t alloc_size, str;
413
414 for (n = 0; n < rank; n++)
415 {
416 if (n == 0)
417 str = 1;
418 else
419 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
420
421 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
422
423 }
424
425 retarray->offset = 0;
426 retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
427
428 alloc_size = sizeof (rtype_name) * GFC_DESCRIPTOR_STRIDE(retarray,rank-1)
429 * extent[rank-1];
430
431 if (alloc_size == 0)
432 {
433 /* Make sure we have a zero-sized array. */
434 GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
435 return;
436 }
437 else
438 retarray->data = internal_malloc_size (alloc_size);
439 }
440 else
441 {
442 if (rank != GFC_DESCRIPTOR_RANK (retarray))
443 runtime_error ("rank of return array incorrect in"
444 " u_name intrinsic: is %ld, should be %ld",
445 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
446 (long int) rank);
447
448 if (unlikely (compile_options.bounds_check))
449 {
450 for (n=0; n < rank; n++)
451 {
452 index_type ret_extent;
453
454 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
455 if (extent[n] != ret_extent)
456 runtime_error ("Incorrect extent in return value of"
457 " u_name intrinsic in dimension %ld:"
458 " is %ld, should be %ld", (long int) n + 1,
459 (long int) ret_extent, (long int) extent[n]);
460 }
461 }
462 }
463
464 for (n = 0; n < rank; n++)
465 {
466 count[n] = 0;
467 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
468 }
469
470 dest = retarray->data;
471
472 while(1)
473 {
474 *dest = '$1`;
475 count[0]++;
476 dest += dstride[0];
477 n = 0;
478 while (count[n] == extent[n])
479 {
480 /* When we get to the end of a dimension, reset it and increment
481 the next dimension. */
482 count[n] = 0;
483 /* We could precalculate these products, but this is a less
484 frequently used path so probably not worth it. */
485 dest -= dstride[n] * extent[n];
486 n++;
487 if (n == rank)
488 return;
489 else
490 {
491 count[n]++;
492 dest += dstride[n];
493 }
494 }
495 }
496 }')dnl
497 define(ARRAY_FUNCTION,
498 `START_ARRAY_FUNCTION
499 $2
500 START_ARRAY_BLOCK($1)
501 $3
502 FINISH_ARRAY_FUNCTION')dnl
503 define(MASKED_ARRAY_FUNCTION,
504 `START_MASKED_ARRAY_FUNCTION
505 $2
506 START_MASKED_ARRAY_BLOCK($1)
507 $3
508 FINISH_MASKED_ARRAY_FUNCTION')dnl