OSDN Git Service

2008-02-10 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / libgfortran / m4 / ifunction_logical.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         gfc_array_l1 * 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         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
44   /* Make dim zero based to avoid confusion.  */
45   dim = (*pdim) - 1;
46   rank = GFC_DESCRIPTOR_RANK (array) - 1;
47
48   src_kind = GFC_DESCRIPTOR_SIZE (array);
49
50   len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
51   delta = array->dim[dim].stride * src_kind;
52
53   for (n = 0; n < dim; n++)
54     {
55       sstride[n] = array->dim[n].stride * src_kind;
56       extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
57
58       if (extent[n] < 0)
59         extent[n] = 0;
60     }
61   for (n = dim; n < rank; n++)
62     {
63       sstride[n] = array->dim[n + 1].stride * src_kind;
64       extent[n] =
65         array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
66
67       if (extent[n] < 0)
68         extent[n] = 0;
69     }
70
71   if (retarray->data == NULL)
72     {
73       size_t alloc_size;
74
75       for (n = 0; n < rank; n++)
76         {
77           retarray->dim[n].lbound = 0;
78           retarray->dim[n].ubound = extent[n]-1;
79           if (n == 0)
80             retarray->dim[n].stride = 1;
81           else
82             retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
83         }
84
85       retarray->offset = 0;
86       retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
87
88       alloc_size = sizeof (rtype_name) * retarray->dim[rank-1].stride
89                    * extent[rank-1];
90
91       if (alloc_size == 0)
92         {
93           /* Make sure we have a zero-sized array.  */
94           retarray->dim[0].lbound = 0;
95           retarray->dim[0].ubound = -1;
96           return;
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 %d, should be %d",
106                        GFC_DESCRIPTOR_RANK (retarray), rank);
107
108       if (compile_options.bounds_check)
109         {
110           for (n=0; n < rank; n++)
111             {
112               index_type ret_extent;
113
114               ret_extent = retarray->dim[n].ubound + 1
115                 - retarray->dim[n].lbound;
116               if (extent[n] != ret_extent)
117                 runtime_error ("Incorrect extent in return value of"
118                                " u_name intrinsic in dimension %d:"
119                                " is %ld, should be %ld", n + 1,
120                                (long int) ret_extent, (long int) extent[n]);
121             }
122         }
123     }
124
125   for (n = 0; n < rank; n++)
126     {
127       count[n] = 0;
128       dstride[n] = retarray->dim[n].stride;
129       if (extent[n] <= 0)
130         len = 0;
131     }
132
133   base = array->data;
134
135   if (src_kind == 1 || src_kind == 2 || src_kind == 4 || src_kind == 8
136 #ifdef HAVE_GFC_LOGICAL_16
137       || src_kind == 16
138 #endif
139     )
140     {
141       if (base)
142         base = GFOR_POINTER_TO_L1 (base, src_kind);
143     }
144   else
145     internal_error (NULL, "Funny sized logical array in u_name intrinsic");
146
147   dest = retarray->data;
148
149   while (base)
150     {
151       const GFC_LOGICAL_1 * restrict src;
152       rtype_name result;
153       src = base;
154       {
155 ')dnl
156 define(START_ARRAY_BLOCK,
157 `        if (len <= 0)
158           *dest = '$1`;
159         else
160           {
161             for (n = 0; n < len; n++, src += delta)
162               {
163 ')dnl
164 define(FINISH_ARRAY_FUNCTION,
165     `          }
166             *dest = result;
167           }
168       }
169       /* Advance to the next element.  */
170       count[0]++;
171       base += sstride[0];
172       dest += dstride[0];
173       n = 0;
174       while (count[n] == extent[n])
175         {
176           /* When we get to the end of a dimension, reset it and increment
177              the next dimension.  */
178           count[n] = 0;
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];
183           n++;
184           if (n == rank)
185             {
186               /* Break out of the look.  */
187               base = NULL;
188               break;
189             }
190           else
191             {
192               count[n]++;
193               base += sstride[n];
194               dest += dstride[n];
195             }
196         }
197     }
198 }')dnl
199 define(ARRAY_FUNCTION,
200 `START_ARRAY_FUNCTION
201 $2
202 START_ARRAY_BLOCK($1)
203 $3
204 FINISH_ARRAY_FUNCTION')dnl