xref: /netbsd-src/external/gpl3/gcc/dist/libgfortran/m4/ifunction_logical.m4 (revision 181254a7b1bdde6873432bffef2d2decc4b5c22f)
1dnl Support macro file for intrinsic functions.
2dnl Contains the generic sections of the array functions.
3dnl This file is part of the GNU Fortran Runtime Library (libgfortran)
4dnl Distributed under the GNU GPL with exception.  See COPYING for details.
5dnl
6dnl Pass the implementation for a single section as the parameter to
7dnl {MASK_}ARRAY_FUNCTION.
8dnl The variables base, delta, and len describe the input section.
9dnl For masked section the mask is described by mbase and mdelta.
10dnl These should not be modified. The result should be stored in *dest.
11dnl The names count, extent, sstride, dstride, base, dest, rank, dim
12dnl retarray, array, pdim and mstride should not be used.
13dnl The variable n is declared as index_type and may be used.
14dnl Other variable declarations may be placed at the start of the code,
15dnl The types of the array parameter and the return value are
16dnl atype_name and rtype_name respectively.
17dnl Execution should be allowed to continue to the end of the block.
18dnl You should not return or break from the inner loop of the implementation.
19dnl Care should also be taken to avoid using the names defined in iparm.m4
20define(START_ARRAY_FUNCTION,
21`
22extern void name`'rtype_qual`_'atype_code (rtype * const restrict,
23	gfc_array_l1 * const restrict, const index_type * const restrict);
24export_proto(name`'rtype_qual`_'atype_code);
25
26void
27name`'rtype_qual`_'atype_code (rtype * const restrict retarray,
28	gfc_array_l1 * 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 GFC_LOGICAL_1 * 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 src_kind;
43  int continue_loop;
44
45  /* Make dim zero based to avoid confusion.  */
46  dim = (*pdim) - 1;
47  rank = GFC_DESCRIPTOR_RANK (array) - 1;
48
49  src_kind = GFC_DESCRIPTOR_SIZE (array);
50
51  len = GFC_DESCRIPTOR_EXTENT(array,dim);
52  if (len < 0)
53    len = 0;
54
55  delta = GFC_DESCRIPTOR_STRIDE_BYTES(array,dim);
56
57  for (n = 0; n < dim; n++)
58    {
59      sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n);
60      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
61
62      if (extent[n] < 0)
63	extent[n] = 0;
64    }
65  for (n = dim; n < rank; n++)
66    {
67      sstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(array,n + 1);
68      extent[n] = GFC_DESCRIPTOR_EXTENT(array,n + 1);
69
70      if (extent[n] < 0)
71	extent[n] = 0;
72    }
73
74  if (retarray->base_addr == NULL)
75    {
76      size_t alloc_size, str;
77
78      for (n = 0; n < rank; n++)
79        {
80          if (n == 0)
81            str = 1;
82          else
83            str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
84
85	  GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
86
87        }
88
89      retarray->offset = 0;
90      retarray->dtype.rank = rank;
91
92      alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
93
94      if (alloc_size == 0)
95	{
96	  /* Make sure we have a zero-sized array.  */
97	  GFC_DIMENSION_SET(retarray->dim[0], 0, -1, 1);
98	  return;
99	}
100      else
101	retarray->base_addr = xmallocarray (alloc_size, sizeof (rtype_name));
102    }
103  else
104    {
105      if (rank != GFC_DESCRIPTOR_RANK (retarray))
106	runtime_error ("rank of return array incorrect in"
107		       " u_name intrinsic: is %ld, should be %ld",
108		       (long int) GFC_DESCRIPTOR_RANK (retarray),
109		       (long int) rank);
110
111      if (unlikely (compile_options.bounds_check))
112	{
113	  for (n=0; n < rank; n++)
114	    {
115	      index_type ret_extent;
116
117	      ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
118	      if (extent[n] != ret_extent)
119		runtime_error ("Incorrect extent in return value of"
120			       " u_name intrinsic in dimension %d:"
121			       " is %ld, should be %ld", (int) n + 1,
122			       (long int) ret_extent, (long int) extent[n]);
123	    }
124	}
125    }
126
127  for (n = 0; n < rank; n++)
128    {
129      count[n] = 0;
130      dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
131      if (extent[n] <= 0)
132	return;
133    }
134
135  base = array->base_addr;
136
137  if (src_kind == 1 || src_kind == 2 || src_kind == 4 || src_kind == 8
138#ifdef HAVE_GFC_LOGICAL_16
139      || src_kind == 16
140#endif
141    )
142    {
143      if (base)
144	base = GFOR_POINTER_TO_L1 (base, src_kind);
145    }
146  else
147    internal_error (NULL, "Funny sized logical array in u_name intrinsic");
148
149  dest = retarray->base_addr;
150
151  continue_loop = 1;
152  while (continue_loop)
153    {
154      const GFC_LOGICAL_1 * restrict src;
155      rtype_name result;
156      src = base;
157      {
158')dnl
159define(START_ARRAY_BLOCK,
160`        if (len <= 0)
161	  *dest = '$1`;
162	else
163	  {
164	    for (n = 0; n < len; n++, src += delta)
165	      {
166')dnl
167define(FINISH_ARRAY_FUNCTION,
168    `          }
169	    *dest = result;
170	  }
171      }
172      /* Advance to the next element.  */
173      count[0]++;
174      base += sstride[0];
175      dest += dstride[0];
176      n = 0;
177      while (count[n] == extent[n])
178        {
179          /* When we get to the end of a dimension, reset it and increment
180             the next dimension.  */
181          count[n] = 0;
182          /* We could precalculate these products, but this is a less
183             frequently used path so probably not worth it.  */
184          base -= sstride[n] * extent[n];
185          dest -= dstride[n] * extent[n];
186          n++;
187          if (n >= rank)
188            {
189              /* Break out of the loop.  */
190              continue_loop = 0;
191              break;
192            }
193          else
194            {
195              count[n]++;
196              base += sstride[n];
197              dest += dstride[n];
198            }
199        }
200    }
201}')dnl
202define(ARRAY_FUNCTION,
203`START_ARRAY_FUNCTION
204$2
205START_ARRAY_BLOCK($1)
206$3
207FINISH_ARRAY_FUNCTION')dnl
208