OSDN Git Service

9cfd8df0213aa300a4834921b5f03249757f96c2
[pf3gnuchains/gcc-fork.git] / libgfortran / generated / product_r16.c
1 /* Implementation of the PRODUCT intrinsic
2    Copyright 2002, 2007 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 "libgfortran.h"
32 #include <stdlib.h>
33 #include <assert.h>
34
35
36 #if defined (HAVE_GFC_REAL_16) && defined (HAVE_GFC_REAL_16)
37
38
39 extern void product_r16 (gfc_array_r16 * const restrict, 
40         gfc_array_r16 * const restrict, const index_type * const restrict);
41 export_proto(product_r16);
42
43 void
44 product_r16 (gfc_array_r16 * const restrict retarray, 
45         gfc_array_r16 * const restrict array, 
46         const index_type * const restrict pdim)
47 {
48   index_type count[GFC_MAX_DIMENSIONS];
49   index_type extent[GFC_MAX_DIMENSIONS];
50   index_type sstride[GFC_MAX_DIMENSIONS];
51   index_type dstride[GFC_MAX_DIMENSIONS];
52   const GFC_REAL_16 * restrict base;
53   GFC_REAL_16 * restrict dest;
54   index_type rank;
55   index_type n;
56   index_type len;
57   index_type delta;
58   index_type dim;
59
60   /* Make dim zero based to avoid confusion.  */
61   dim = (*pdim) - 1;
62   rank = GFC_DESCRIPTOR_RANK (array) - 1;
63
64   len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
65   delta = array->dim[dim].stride;
66
67   for (n = 0; n < dim; n++)
68     {
69       sstride[n] = array->dim[n].stride;
70       extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
71
72       if (extent[n] < 0)
73         extent[n] = 0;
74     }
75   for (n = dim; n < rank; n++)
76     {
77       sstride[n] = array->dim[n + 1].stride;
78       extent[n] =
79         array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
80
81       if (extent[n] < 0)
82         extent[n] = 0;
83     }
84
85   if (retarray->data == NULL)
86     {
87       size_t alloc_size;
88
89       for (n = 0; n < rank; n++)
90         {
91           retarray->dim[n].lbound = 0;
92           retarray->dim[n].ubound = extent[n]-1;
93           if (n == 0)
94             retarray->dim[n].stride = 1;
95           else
96             retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
97         }
98
99       retarray->offset = 0;
100       retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
101
102       alloc_size = sizeof (GFC_REAL_16) * retarray->dim[rank-1].stride
103                    * extent[rank-1];
104
105       if (alloc_size == 0)
106         {
107           /* Make sure we have a zero-sized array.  */
108           retarray->dim[0].lbound = 0;
109           retarray->dim[0].ubound = -1;
110           return;
111         }
112       else
113         retarray->data = internal_malloc_size (alloc_size);
114     }
115   else
116     {
117       if (rank != GFC_DESCRIPTOR_RANK (retarray))
118         runtime_error ("rank of return array incorrect in"
119                        " PRODUCT intrinsic: is %ld, should be %ld",
120                        (long int) (GFC_DESCRIPTOR_RANK (retarray)),
121                        (long int) rank);
122
123       if (compile_options.bounds_check)
124         {
125           for (n=0; n < rank; n++)
126             {
127               index_type ret_extent;
128
129               ret_extent = retarray->dim[n].ubound + 1
130                 - retarray->dim[n].lbound;
131               if (extent[n] != ret_extent)
132                 runtime_error ("Incorrect extent in return value of"
133                                " PRODUCT intrinsic in dimension %ld:"
134                                " is %ld, should be %ld", (long int) n + 1,
135                                (long int) ret_extent, (long int) extent[n]);
136             }
137         }
138     }
139
140   for (n = 0; n < rank; n++)
141     {
142       count[n] = 0;
143       dstride[n] = retarray->dim[n].stride;
144       if (extent[n] <= 0)
145         len = 0;
146     }
147
148   base = array->data;
149   dest = retarray->data;
150
151   while (base)
152     {
153       const GFC_REAL_16 * restrict src;
154       GFC_REAL_16 result;
155       src = base;
156       {
157
158   result = 1;
159         if (len <= 0)
160           *dest = 1;
161         else
162           {
163             for (n = 0; n < len; n++, src += delta)
164               {
165
166   result *= *src;
167           }
168             *dest = result;
169           }
170       }
171       /* Advance to the next element.  */
172       count[0]++;
173       base += sstride[0];
174       dest += dstride[0];
175       n = 0;
176       while (count[n] == extent[n])
177         {
178           /* When we get to the end of a dimension, reset it and increment
179              the next dimension.  */
180           count[n] = 0;
181           /* We could precalculate these products, but this is a less
182              frequently used path so probably not worth it.  */
183           base -= sstride[n] * extent[n];
184           dest -= dstride[n] * extent[n];
185           n++;
186           if (n == rank)
187             {
188               /* Break out of the look.  */
189               base = NULL;
190               break;
191             }
192           else
193             {
194               count[n]++;
195               base += sstride[n];
196               dest += dstride[n];
197             }
198         }
199     }
200 }
201
202
203 extern void mproduct_r16 (gfc_array_r16 * const restrict, 
204         gfc_array_r16 * const restrict, const index_type * const restrict,
205         gfc_array_l1 * const restrict);
206 export_proto(mproduct_r16);
207
208 void
209 mproduct_r16 (gfc_array_r16 * const restrict retarray, 
210         gfc_array_r16 * const restrict array, 
211         const index_type * const restrict pdim, 
212         gfc_array_l1 * const restrict mask)
213 {
214   index_type count[GFC_MAX_DIMENSIONS];
215   index_type extent[GFC_MAX_DIMENSIONS];
216   index_type sstride[GFC_MAX_DIMENSIONS];
217   index_type dstride[GFC_MAX_DIMENSIONS];
218   index_type mstride[GFC_MAX_DIMENSIONS];
219   GFC_REAL_16 * restrict dest;
220   const GFC_REAL_16 * restrict base;
221   const GFC_LOGICAL_1 * restrict mbase;
222   int rank;
223   int dim;
224   index_type n;
225   index_type len;
226   index_type delta;
227   index_type mdelta;
228   int mask_kind;
229
230   dim = (*pdim) - 1;
231   rank = GFC_DESCRIPTOR_RANK (array) - 1;
232
233   len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
234   if (len <= 0)
235     return;
236
237   mbase = mask->data;
238
239   mask_kind = GFC_DESCRIPTOR_SIZE (mask);
240
241   if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
242 #ifdef HAVE_GFC_LOGICAL_16
243       || mask_kind == 16
244 #endif
245       )
246     mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
247   else
248     runtime_error ("Funny sized logical array");
249
250   delta = array->dim[dim].stride;
251   mdelta = mask->dim[dim].stride * mask_kind;
252
253   for (n = 0; n < dim; n++)
254     {
255       sstride[n] = array->dim[n].stride;
256       mstride[n] = mask->dim[n].stride * mask_kind;
257       extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
258
259       if (extent[n] < 0)
260         extent[n] = 0;
261
262     }
263   for (n = dim; n < rank; n++)
264     {
265       sstride[n] = array->dim[n + 1].stride;
266       mstride[n] = mask->dim[n + 1].stride * mask_kind;
267       extent[n] =
268         array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
269
270       if (extent[n] < 0)
271         extent[n] = 0;
272     }
273
274   if (retarray->data == NULL)
275     {
276       size_t alloc_size;
277
278       for (n = 0; n < rank; n++)
279         {
280           retarray->dim[n].lbound = 0;
281           retarray->dim[n].ubound = extent[n]-1;
282           if (n == 0)
283             retarray->dim[n].stride = 1;
284           else
285             retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
286         }
287
288       alloc_size = sizeof (GFC_REAL_16) * retarray->dim[rank-1].stride
289                    * extent[rank-1];
290
291       retarray->offset = 0;
292       retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
293
294       if (alloc_size == 0)
295         {
296           /* Make sure we have a zero-sized array.  */
297           retarray->dim[0].lbound = 0;
298           retarray->dim[0].ubound = -1;
299           return;
300         }
301       else
302         retarray->data = internal_malloc_size (alloc_size);
303
304     }
305   else
306     {
307       if (rank != GFC_DESCRIPTOR_RANK (retarray))
308         runtime_error ("rank of return array incorrect in PRODUCT intrinsic");
309
310       if (compile_options.bounds_check)
311         {
312           for (n=0; n < rank; n++)
313             {
314               index_type ret_extent;
315
316               ret_extent = retarray->dim[n].ubound + 1
317                 - retarray->dim[n].lbound;
318               if (extent[n] != ret_extent)
319                 runtime_error ("Incorrect extent in return value of"
320                                " PRODUCT intrinsic in dimension %ld:"
321                                " is %ld, should be %ld", (long int) n + 1,
322                                (long int) ret_extent, (long int) extent[n]);
323             }
324           for (n=0; n<= rank; n++)
325             {
326               index_type mask_extent, array_extent;
327
328               array_extent = array->dim[n].ubound + 1 - array->dim[n].lbound;
329               mask_extent = mask->dim[n].ubound + 1 - mask->dim[n].lbound;
330               if (array_extent != mask_extent)
331                 runtime_error ("Incorrect extent in MASK argument of"
332                                " PRODUCT intrinsic in dimension %ld:"
333                                " is %ld, should be %ld", (long int) n + 1,
334                                (long int) mask_extent, (long int) array_extent);
335             }
336         }
337     }
338
339   for (n = 0; n < rank; n++)
340     {
341       count[n] = 0;
342       dstride[n] = retarray->dim[n].stride;
343       if (extent[n] <= 0)
344         return;
345     }
346
347   dest = retarray->data;
348   base = array->data;
349
350   while (base)
351     {
352       const GFC_REAL_16 * restrict src;
353       const GFC_LOGICAL_1 * restrict msrc;
354       GFC_REAL_16 result;
355       src = base;
356       msrc = mbase;
357       {
358
359   result = 1;
360         if (len <= 0)
361           *dest = 1;
362         else
363           {
364             for (n = 0; n < len; n++, src += delta, msrc += mdelta)
365               {
366
367   if (*msrc)
368     result *= *src;
369               }
370             *dest = result;
371           }
372       }
373       /* Advance to the next element.  */
374       count[0]++;
375       base += sstride[0];
376       mbase += mstride[0];
377       dest += dstride[0];
378       n = 0;
379       while (count[n] == extent[n])
380         {
381           /* When we get to the end of a dimension, reset it and increment
382              the next dimension.  */
383           count[n] = 0;
384           /* We could precalculate these products, but this is a less
385              frequently used path so probably not worth it.  */
386           base -= sstride[n] * extent[n];
387           mbase -= mstride[n] * extent[n];
388           dest -= dstride[n] * extent[n];
389           n++;
390           if (n == rank)
391             {
392               /* Break out of the look.  */
393               base = NULL;
394               break;
395             }
396           else
397             {
398               count[n]++;
399               base += sstride[n];
400               mbase += mstride[n];
401               dest += dstride[n];
402             }
403         }
404     }
405 }
406
407
408 extern void sproduct_r16 (gfc_array_r16 * const restrict, 
409         gfc_array_r16 * const restrict, const index_type * const restrict,
410         GFC_LOGICAL_4 *);
411 export_proto(sproduct_r16);
412
413 void
414 sproduct_r16 (gfc_array_r16 * const restrict retarray, 
415         gfc_array_r16 * const restrict array, 
416         const index_type * const restrict pdim, 
417         GFC_LOGICAL_4 * mask)
418 {
419   index_type count[GFC_MAX_DIMENSIONS];
420   index_type extent[GFC_MAX_DIMENSIONS];
421   index_type sstride[GFC_MAX_DIMENSIONS];
422   index_type dstride[GFC_MAX_DIMENSIONS];
423   GFC_REAL_16 * restrict dest;
424   index_type rank;
425   index_type n;
426   index_type dim;
427
428
429   if (*mask)
430     {
431       product_r16 (retarray, array, pdim);
432       return;
433     }
434   /* Make dim zero based to avoid confusion.  */
435   dim = (*pdim) - 1;
436   rank = GFC_DESCRIPTOR_RANK (array) - 1;
437
438   for (n = 0; n < dim; n++)
439     {
440       sstride[n] = array->dim[n].stride;
441       extent[n] = array->dim[n].ubound + 1 - array->dim[n].lbound;
442
443       if (extent[n] <= 0)
444         extent[n] = 0;
445     }
446
447   for (n = dim; n < rank; n++)
448     {
449       sstride[n] = array->dim[n + 1].stride;
450       extent[n] =
451         array->dim[n + 1].ubound + 1 - array->dim[n + 1].lbound;
452
453       if (extent[n] <= 0)
454         extent[n] = 0;
455     }
456
457   if (retarray->data == NULL)
458     {
459       size_t alloc_size;
460
461       for (n = 0; n < rank; n++)
462         {
463           retarray->dim[n].lbound = 0;
464           retarray->dim[n].ubound = extent[n]-1;
465           if (n == 0)
466             retarray->dim[n].stride = 1;
467           else
468             retarray->dim[n].stride = retarray->dim[n-1].stride * extent[n-1];
469         }
470
471       retarray->offset = 0;
472       retarray->dtype = (array->dtype & ~GFC_DTYPE_RANK_MASK) | rank;
473
474       alloc_size = sizeof (GFC_REAL_16) * retarray->dim[rank-1].stride
475                    * extent[rank-1];
476
477       if (alloc_size == 0)
478         {
479           /* Make sure we have a zero-sized array.  */
480           retarray->dim[0].lbound = 0;
481           retarray->dim[0].ubound = -1;
482           return;
483         }
484       else
485         retarray->data = internal_malloc_size (alloc_size);
486     }
487   else
488     {
489       if (rank != GFC_DESCRIPTOR_RANK (retarray))
490         runtime_error ("rank of return array incorrect in"
491                        " PRODUCT intrinsic: is %ld, should be %ld",
492                        (long int) (GFC_DESCRIPTOR_RANK (retarray)),
493                        (long int) rank);
494
495       if (compile_options.bounds_check)
496         {
497           for (n=0; n < rank; n++)
498             {
499               index_type ret_extent;
500
501               ret_extent = retarray->dim[n].ubound + 1
502                 - retarray->dim[n].lbound;
503               if (extent[n] != ret_extent)
504                 runtime_error ("Incorrect extent in return value of"
505                                " PRODUCT intrinsic in dimension %ld:"
506                                " is %ld, should be %ld", (long int) n + 1,
507                                (long int) ret_extent, (long int) extent[n]);
508             }
509         }
510     }
511
512   for (n = 0; n < rank; n++)
513     {
514       count[n] = 0;
515       dstride[n] = retarray->dim[n].stride;
516     }
517
518   dest = retarray->data;
519
520   while(1)
521     {
522       *dest = 1;
523       count[0]++;
524       dest += dstride[0];
525       n = 0;
526       while (count[n] == extent[n])
527         {
528           /* When we get to the end of a dimension, reset it and increment
529              the next dimension.  */
530           count[n] = 0;
531           /* We could precalculate these products, but this is a less
532              frequently used path so probably not worth it.  */
533           dest -= dstride[n] * extent[n];
534           n++;
535           if (n == rank)
536             return;
537           else
538             {
539               count[n]++;
540               dest += dstride[n];
541             }
542         }
543     }
544 }
545
546 #endif