1 /* Implementation of the PRODUCT intrinsic
2 Copyright 2002 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
5 This file is part of the GNU Fortran 95 runtime library (libgfortran).
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.
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
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.
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. */
34 #include "libgfortran.h"
37 #if defined (HAVE_GFC_COMPLEX_16) && defined (HAVE_GFC_COMPLEX_16)
40 extern void product_c16 (gfc_array_c16
* const restrict
,
41 gfc_array_c16
* const restrict
, const index_type
* const restrict
);
42 export_proto(product_c16
);
45 product_c16 (gfc_array_c16
* const restrict retarray
,
46 gfc_array_c16
* const restrict array
,
47 const index_type
* const restrict pdim
)
49 index_type count
[GFC_MAX_DIMENSIONS
];
50 index_type extent
[GFC_MAX_DIMENSIONS
];
51 index_type sstride
[GFC_MAX_DIMENSIONS
];
52 index_type dstride
[GFC_MAX_DIMENSIONS
];
53 const GFC_COMPLEX_16
* restrict base
;
54 GFC_COMPLEX_16
* restrict dest
;
61 /* Make dim zero based to avoid confusion. */
63 rank
= GFC_DESCRIPTOR_RANK (array
) - 1;
65 len
= array
->dim
[dim
].ubound
+ 1 - array
->dim
[dim
].lbound
;
66 delta
= array
->dim
[dim
].stride
;
68 for (n
= 0; n
< dim
; n
++)
70 sstride
[n
] = array
->dim
[n
].stride
;
71 extent
[n
] = array
->dim
[n
].ubound
+ 1 - array
->dim
[n
].lbound
;
73 for (n
= dim
; n
< rank
; n
++)
75 sstride
[n
] = array
->dim
[n
+ 1].stride
;
77 array
->dim
[n
+ 1].ubound
+ 1 - array
->dim
[n
+ 1].lbound
;
80 if (retarray
->data
== NULL
)
82 for (n
= 0; n
< rank
; n
++)
84 retarray
->dim
[n
].lbound
= 0;
85 retarray
->dim
[n
].ubound
= extent
[n
]-1;
87 retarray
->dim
[n
].stride
= 1;
89 retarray
->dim
[n
].stride
= retarray
->dim
[n
-1].stride
* extent
[n
-1];
93 = internal_malloc_size (sizeof (GFC_COMPLEX_16
)
94 * retarray
->dim
[rank
-1].stride
97 retarray
->dtype
= (array
->dtype
& ~GFC_DTYPE_RANK_MASK
) | rank
;
101 if (rank
!= GFC_DESCRIPTOR_RANK (retarray
))
102 runtime_error ("rank of return array incorrect");
105 for (n
= 0; n
< rank
; n
++)
108 dstride
[n
] = retarray
->dim
[n
].stride
;
114 dest
= retarray
->data
;
118 const GFC_COMPLEX_16
* restrict src
;
119 GFC_COMPLEX_16 result
;
128 for (n
= 0; n
< len
; n
++, src
+= delta
)
136 /* Advance to the next element. */
141 while (count
[n
] == extent
[n
])
143 /* When we get to the end of a dimension, reset it and increment
144 the next dimension. */
146 /* We could precalculate these products, but this is a less
147 frequently used path so probably not worth it. */
148 base
-= sstride
[n
] * extent
[n
];
149 dest
-= dstride
[n
] * extent
[n
];
153 /* Break out of the look. */
168 extern void mproduct_c16 (gfc_array_c16
* const restrict
,
169 gfc_array_c16
* const restrict
, const index_type
* const restrict
,
170 gfc_array_l4
* const restrict
);
171 export_proto(mproduct_c16
);
174 mproduct_c16 (gfc_array_c16
* const restrict retarray
,
175 gfc_array_c16
* const restrict array
,
176 const index_type
* const restrict pdim
,
177 gfc_array_l4
* const restrict mask
)
179 index_type count
[GFC_MAX_DIMENSIONS
];
180 index_type extent
[GFC_MAX_DIMENSIONS
];
181 index_type sstride
[GFC_MAX_DIMENSIONS
];
182 index_type dstride
[GFC_MAX_DIMENSIONS
];
183 index_type mstride
[GFC_MAX_DIMENSIONS
];
184 GFC_COMPLEX_16
* restrict dest
;
185 const GFC_COMPLEX_16
* restrict base
;
186 const GFC_LOGICAL_4
* restrict mbase
;
195 rank
= GFC_DESCRIPTOR_RANK (array
) - 1;
197 len
= array
->dim
[dim
].ubound
+ 1 - array
->dim
[dim
].lbound
;
200 delta
= array
->dim
[dim
].stride
;
201 mdelta
= mask
->dim
[dim
].stride
;
203 for (n
= 0; n
< dim
; n
++)
205 sstride
[n
] = array
->dim
[n
].stride
;
206 mstride
[n
] = mask
->dim
[n
].stride
;
207 extent
[n
] = array
->dim
[n
].ubound
+ 1 - array
->dim
[n
].lbound
;
209 for (n
= dim
; n
< rank
; n
++)
211 sstride
[n
] = array
->dim
[n
+ 1].stride
;
212 mstride
[n
] = mask
->dim
[n
+ 1].stride
;
214 array
->dim
[n
+ 1].ubound
+ 1 - array
->dim
[n
+ 1].lbound
;
217 if (retarray
->data
== NULL
)
219 for (n
= 0; n
< rank
; n
++)
221 retarray
->dim
[n
].lbound
= 0;
222 retarray
->dim
[n
].ubound
= extent
[n
]-1;
224 retarray
->dim
[n
].stride
= 1;
226 retarray
->dim
[n
].stride
= retarray
->dim
[n
-1].stride
* extent
[n
-1];
230 = internal_malloc_size (sizeof (GFC_COMPLEX_16
)
231 * retarray
->dim
[rank
-1].stride
233 retarray
->offset
= 0;
234 retarray
->dtype
= (array
->dtype
& ~GFC_DTYPE_RANK_MASK
) | rank
;
238 if (rank
!= GFC_DESCRIPTOR_RANK (retarray
))
239 runtime_error ("rank of return array incorrect");
242 for (n
= 0; n
< rank
; n
++)
245 dstride
[n
] = retarray
->dim
[n
].stride
;
250 dest
= retarray
->data
;
254 if (GFC_DESCRIPTOR_SIZE (mask
) != 4)
256 /* This allows the same loop to be used for all logical types. */
257 assert (GFC_DESCRIPTOR_SIZE (mask
) == 8);
258 for (n
= 0; n
< rank
; n
++)
261 mbase
= (GFOR_POINTER_L8_TO_L4 (mbase
));
266 const GFC_COMPLEX_16
* restrict src
;
267 const GFC_LOGICAL_4
* restrict msrc
;
268 GFC_COMPLEX_16 result
;
278 for (n
= 0; n
< len
; n
++, src
+= delta
, msrc
+= mdelta
)
287 /* Advance to the next element. */
293 while (count
[n
] == extent
[n
])
295 /* When we get to the end of a dimension, reset it and increment
296 the next dimension. */
298 /* We could precalculate these products, but this is a less
299 frequently used path so probably not worth it. */
300 base
-= sstride
[n
] * extent
[n
];
301 mbase
-= mstride
[n
] * extent
[n
];
302 dest
-= dstride
[n
] * extent
[n
];
306 /* Break out of the look. */
322 extern void sproduct_c16 (gfc_array_c16
* const restrict
,
323 gfc_array_c16
* const restrict
, const index_type
* const restrict
,
325 export_proto(sproduct_c16
);
328 sproduct_c16 (gfc_array_c16
* const restrict retarray
,
329 gfc_array_c16
* const restrict array
,
330 const index_type
* const restrict pdim
,
331 GFC_LOGICAL_4
* mask
)
336 GFC_COMPLEX_16
*dest
;
340 product_c16 (retarray
, array
, pdim
);
343 rank
= GFC_DESCRIPTOR_RANK (array
);
345 runtime_error ("Rank of array needs to be > 0");
347 if (retarray
->data
== NULL
)
349 retarray
->dim
[0].lbound
= 0;
350 retarray
->dim
[0].ubound
= rank
-1;
351 retarray
->dim
[0].stride
= 1;
352 retarray
->dtype
= (retarray
->dtype
& ~GFC_DTYPE_RANK_MASK
) | 1;
353 retarray
->offset
= 0;
354 retarray
->data
= internal_malloc_size (sizeof (GFC_COMPLEX_16
) * rank
);
358 if (GFC_DESCRIPTOR_RANK (retarray
) != 1)
359 runtime_error ("rank of return array does not equal 1");
361 if (retarray
->dim
[0].ubound
+ 1 - retarray
->dim
[0].lbound
!= rank
)
362 runtime_error ("dimension of return array incorrect");
365 dstride
= retarray
->dim
[0].stride
;
366 dest
= retarray
->data
;
368 for (n
= 0; n
< rank
; n
++)
369 dest
[n
* dstride
] = 1 ;