re PR fortran/15441 (RRSPACING broken for denormals)
[platform/upstream/gcc.git] / libgfortran / m4 / reshape.m4
1 `/* Implementation of the RESHAPE
2    Copyright 2002, 2006 Free Software Foundation, Inc.
3    Contributed by Paul Brook <paul@nowt.org>
4
5 This file is part of the GNU Fortran 95 runtime library (libgfortran).
6
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.
11
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
19 executable.)
20
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.
25
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.  */
30
31 #include "config.h"
32 #include <stdlib.h>
33 #include <assert.h>
34 #include "libgfortran.h"'
35 include(iparm.m4)dnl
36
37 `#if defined (HAVE_'rtype_name`)'
38
39 typedef GFC_ARRAY_DESCRIPTOR(1, index_type) shape_type;
40
41 /* The shape parameter is ignored. We can currently deduce the shape from the
42    return array.  */
43 dnl Only the kind (ie size) is used to name the function.
44
45 extern void reshape_`'rtype_ccode (rtype * const restrict, 
46         rtype * const restrict, 
47         shape_type * const restrict,
48         rtype * const restrict, 
49         shape_type * const restrict);
50 export_proto(reshape_`'rtype_ccode);
51
52 void
53 reshape_`'rtype_ccode (rtype * const restrict ret, 
54         rtype * const restrict source, 
55         shape_type * const restrict shape,
56         rtype * const restrict pad, 
57         shape_type * const restrict order)
58 {
59   /* r.* indicates the return array.  */
60   index_type rcount[GFC_MAX_DIMENSIONS];
61   index_type rextent[GFC_MAX_DIMENSIONS];
62   index_type rstride[GFC_MAX_DIMENSIONS];
63   index_type rstride0;
64   index_type rdim;
65   index_type rsize;
66   index_type rs;
67   index_type rex;
68   rtype_name *rptr;
69   /* s.* indicates the source array.  */
70   index_type scount[GFC_MAX_DIMENSIONS];
71   index_type sextent[GFC_MAX_DIMENSIONS];
72   index_type sstride[GFC_MAX_DIMENSIONS];
73   index_type sstride0;
74   index_type sdim;
75   index_type ssize;
76   const rtype_name *sptr;
77   /* p.* indicates the pad array.  */
78   index_type pcount[GFC_MAX_DIMENSIONS];
79   index_type pextent[GFC_MAX_DIMENSIONS];
80   index_type pstride[GFC_MAX_DIMENSIONS];
81   index_type pdim;
82   index_type psize;
83   const rtype_name *pptr;
84
85   const rtype_name *src;
86   int n;
87   int dim;
88
89   if (ret->data == NULL)
90     {
91       rdim = shape->dim[0].ubound - shape->dim[0].lbound + 1;
92       rs = 1;
93       for (n=0; n < rdim; n++)
94         {
95           ret->dim[n].lbound = 0;
96           rex = shape->data[n * shape->dim[0].stride];
97           ret->dim[n].ubound =  rex - 1;
98           ret->dim[n].stride = rs;
99           rs *= rex;
100         }
101       ret->offset = 0;
102       ret->data = internal_malloc_size ( rs * sizeof (rtype_name));
103       ret->dtype = (source->dtype & ~GFC_DTYPE_RANK_MASK) | rdim;
104     }
105   else
106     {
107       rdim = GFC_DESCRIPTOR_RANK (ret);
108     }
109
110   rsize = 1;
111   for (n = 0; n < rdim; n++)
112     {
113       if (order)
114         dim = order->data[n * order->dim[0].stride] - 1;
115       else
116         dim = n;
117
118       rcount[n] = 0;
119       rstride[n] = ret->dim[dim].stride;
120       rextent[n] = ret->dim[dim].ubound + 1 - ret->dim[dim].lbound;
121
122       if (rextent[n] != shape->data[dim * shape->dim[0].stride])
123         runtime_error ("shape and target do not conform");
124
125       if (rsize == rstride[n])
126         rsize *= rextent[n];
127       else
128         rsize = 0;
129       if (rextent[n] <= 0)
130         return;
131     }
132
133   sdim = GFC_DESCRIPTOR_RANK (source);
134   ssize = 1;
135   for (n = 0; n < sdim; n++)
136     {
137       scount[n] = 0;
138       sstride[n] = source->dim[n].stride;
139       sextent[n] = source->dim[n].ubound + 1 - source->dim[n].lbound;
140       if (sextent[n] <= 0)
141         abort ();
142
143       if (ssize == sstride[n])
144         ssize *= sextent[n];
145       else
146         ssize = 0;
147     }
148
149   if (pad)
150     {
151       pdim = GFC_DESCRIPTOR_RANK (pad);
152       psize = 1;
153       for (n = 0; n < pdim; n++)
154         {
155           pcount[n] = 0;
156           pstride[n] = pad->dim[n].stride;
157           pextent[n] = pad->dim[n].ubound + 1 - pad->dim[n].lbound;
158           if (pextent[n] <= 0)
159             abort ();
160           if (psize == pstride[n])
161             psize *= pextent[n];
162           else
163             psize = 0;
164         }
165       pptr = pad->data;
166     }
167   else
168     {
169       pdim = 0;
170       psize = 1;
171       pptr = NULL;
172     }
173
174   if (rsize != 0 && ssize != 0 && psize != 0)
175     {
176       rsize *= sizeof (rtype_name);
177       ssize *= sizeof (rtype_name);
178       psize *= sizeof (rtype_name);
179       reshape_packed ((char *)ret->data, rsize, (char *)source->data,
180                       ssize, pad ? (char *)pad->data : NULL, psize);
181       return;
182     }
183   rptr = ret->data;
184   src = sptr = source->data;
185   rstride0 = rstride[0];
186   sstride0 = sstride[0];
187
188   while (rptr)
189     {
190       /* Select between the source and pad arrays.  */
191       *rptr = *src;
192       /* Advance to the next element.  */
193       rptr += rstride0;
194       src += sstride0;
195       rcount[0]++;
196       scount[0]++;
197       /* Advance to the next destination element.  */
198       n = 0;
199       while (rcount[n] == rextent[n])
200         {
201           /* When we get to the end of a dimension, reset it and increment
202              the next dimension.  */
203           rcount[n] = 0;
204           /* We could precalculate these products, but this is a less
205              frequently used path so proabably not worth it.  */
206           rptr -= rstride[n] * rextent[n];
207           n++;
208           if (n == rdim)
209             {
210               /* Break out of the loop.  */
211               rptr = NULL;
212               break;
213             }
214           else
215             {
216               rcount[n]++;
217               rptr += rstride[n];
218             }
219         }
220       /* Advance to the next source element.  */
221       n = 0;
222       while (scount[n] == sextent[n])
223         {
224           /* When we get to the end of a dimension, reset it and increment
225              the next dimension.  */
226           scount[n] = 0;
227           /* We could precalculate these products, but this is a less
228              frequently used path so proabably not worth it.  */
229           src -= sstride[n] * sextent[n];
230           n++;
231           if (n == sdim)
232             {
233               if (sptr && pad)
234                 {
235                   /* Switch to the pad array.  */
236                   sptr = NULL;
237                   sdim = pdim;
238                   for (dim = 0; dim < pdim; dim++)
239                     {
240                       scount[dim] = pcount[dim];
241                       sextent[dim] = pextent[dim];
242                       sstride[dim] = pstride[dim];
243                       sstride0 = sstride[0];
244                     }
245                 }
246               /* We now start again from the beginning of the pad array.  */
247               src = pptr;
248               break;
249             }
250           else
251             {
252               scount[n]++;
253               src += sstride[n];
254             }
255         }
256     }
257 }
258
259 #endif