OSDN Git Service

2008-07-07 Thomas Koenig <tkoenig@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / libgfortran / generated / matmul_l16.c
1 /* Implementation of the MATMUL intrinsic
2    Copyright 2002, 2005, 2006, 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_LOGICAL_16)
37
38 /* Dimensions: retarray(x,y) a(x, count) b(count,y).
39    Either a or b can be rank 1.  In this case x or y is 1.  */
40
41 extern void matmul_l16 (gfc_array_l16 * const restrict, 
42         gfc_array_l1 * const restrict, gfc_array_l1 * const restrict);
43 export_proto(matmul_l16);
44
45 void
46 matmul_l16 (gfc_array_l16 * const restrict retarray, 
47         gfc_array_l1 * const restrict a, gfc_array_l1 * const restrict b)
48 {
49   const GFC_LOGICAL_1 * restrict abase;
50   const GFC_LOGICAL_1 * restrict bbase;
51   GFC_LOGICAL_16 * restrict dest;
52   index_type rxstride;
53   index_type rystride;
54   index_type xcount;
55   index_type ycount;
56   index_type xstride;
57   index_type ystride;
58   index_type x;
59   index_type y;
60   int a_kind;
61   int b_kind;
62
63   const GFC_LOGICAL_1 * restrict pa;
64   const GFC_LOGICAL_1 * restrict pb;
65   index_type astride;
66   index_type bstride;
67   index_type count;
68   index_type n;
69
70   assert (GFC_DESCRIPTOR_RANK (a) == 2
71           || GFC_DESCRIPTOR_RANK (b) == 2);
72
73   if (retarray->data == NULL)
74     {
75       if (GFC_DESCRIPTOR_RANK (a) == 1)
76         {
77           retarray->dim[0].lbound = 0;
78           retarray->dim[0].ubound = b->dim[1].ubound - b->dim[1].lbound;
79           retarray->dim[0].stride = 1;
80         }
81       else if (GFC_DESCRIPTOR_RANK (b) == 1)
82         {
83           retarray->dim[0].lbound = 0;
84           retarray->dim[0].ubound = a->dim[0].ubound - a->dim[0].lbound;
85           retarray->dim[0].stride = 1;
86         }
87       else
88         {
89           retarray->dim[0].lbound = 0;
90           retarray->dim[0].ubound = a->dim[0].ubound - a->dim[0].lbound;
91           retarray->dim[0].stride = 1;
92           
93           retarray->dim[1].lbound = 0;
94           retarray->dim[1].ubound = b->dim[1].ubound - b->dim[1].lbound;
95           retarray->dim[1].stride = retarray->dim[0].ubound+1;
96         }
97           
98       retarray->data
99         = internal_malloc_size (sizeof (GFC_LOGICAL_16) * size0 ((array_t *) retarray));
100       retarray->offset = 0;
101     }
102     else if (compile_options.bounds_check)
103       {
104         index_type ret_extent, arg_extent;
105
106         if (GFC_DESCRIPTOR_RANK (a) == 1)
107           {
108             arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound;
109             ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
110             if (arg_extent != ret_extent)
111               runtime_error ("Incorrect extent in return array in"
112                              " MATMUL intrinsic: is %ld, should be %ld",
113                              (long int) ret_extent, (long int) arg_extent);
114           }
115         else if (GFC_DESCRIPTOR_RANK (b) == 1)
116           {
117             arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound;
118             ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
119             if (arg_extent != ret_extent)
120               runtime_error ("Incorrect extent in return array in"
121                              " MATMUL intrinsic: is %ld, should be %ld",
122                              (long int) ret_extent, (long int) arg_extent);         
123           }
124         else
125           {
126             arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound;
127             ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound;
128             if (arg_extent != ret_extent)
129               runtime_error ("Incorrect extent in return array in"
130                              " MATMUL intrinsic for dimension 1:"
131                              " is %ld, should be %ld",
132                              (long int) ret_extent, (long int) arg_extent);
133
134             arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound;
135             ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound;
136             if (arg_extent != ret_extent)
137               runtime_error ("Incorrect extent in return array in"
138                              " MATMUL intrinsic for dimension 2:"
139                              " is %ld, should be %ld",
140                              (long int) ret_extent, (long int) arg_extent);
141           }
142       }
143
144   abase = a->data;
145   a_kind = GFC_DESCRIPTOR_SIZE (a);
146
147   if (a_kind == 1 || a_kind == 2 || a_kind == 4 || a_kind == 8
148 #ifdef HAVE_GFC_LOGICAL_16
149      || a_kind == 16
150 #endif
151      )
152     abase = GFOR_POINTER_TO_L1 (abase, a_kind);
153   else
154     internal_error (NULL, "Funny sized logical array");
155
156   bbase = b->data;
157   b_kind = GFC_DESCRIPTOR_SIZE (b);
158
159   if (b_kind == 1 || b_kind == 2 || b_kind == 4 || b_kind == 8
160 #ifdef HAVE_GFC_LOGICAL_16
161      || b_kind == 16
162 #endif
163      )
164     bbase = GFOR_POINTER_TO_L1 (bbase, b_kind);
165   else
166     internal_error (NULL, "Funny sized logical array");
167
168   dest = retarray->data;
169
170
171   if (GFC_DESCRIPTOR_RANK (retarray) == 1)
172     {
173       rxstride = retarray->dim[0].stride;
174       rystride = rxstride;
175     }
176   else
177     {
178       rxstride = retarray->dim[0].stride;
179       rystride = retarray->dim[1].stride;
180     }
181
182   /* If we have rank 1 parameters, zero the absent stride, and set the size to
183      one.  */
184   if (GFC_DESCRIPTOR_RANK (a) == 1)
185     {
186       astride = a->dim[0].stride * a_kind;
187       count = a->dim[0].ubound + 1 - a->dim[0].lbound;
188       xstride = 0;
189       rxstride = 0;
190       xcount = 1;
191     }
192   else
193     {
194       astride = a->dim[1].stride * a_kind;
195       count = a->dim[1].ubound + 1 - a->dim[1].lbound;
196       xstride = a->dim[0].stride * a_kind;
197       xcount = a->dim[0].ubound + 1 - a->dim[0].lbound;
198     }
199   if (GFC_DESCRIPTOR_RANK (b) == 1)
200     {
201       bstride = b->dim[0].stride * b_kind;
202       assert(count == b->dim[0].ubound + 1 - b->dim[0].lbound);
203       ystride = 0;
204       rystride = 0;
205       ycount = 1;
206     }
207   else
208     {
209       bstride = b->dim[0].stride * b_kind;
210       assert(count == b->dim[0].ubound + 1 - b->dim[0].lbound);
211       ystride = b->dim[1].stride * b_kind;
212       ycount = b->dim[1].ubound + 1 - b->dim[1].lbound;
213     }
214
215   for (y = 0; y < ycount; y++)
216     {
217       for (x = 0; x < xcount; x++)
218         {
219           /* Do the summation for this element.  For real and integer types
220              this is the same as DOT_PRODUCT.  For complex types we use do
221              a*b, not conjg(a)*b.  */
222           pa = abase;
223           pb = bbase;
224           *dest = 0;
225
226           for (n = 0; n < count; n++)
227             {
228               if (*pa && *pb)
229                 {
230                   *dest = 1;
231                   break;
232                 }
233               pa += astride;
234               pb += bstride;
235             }
236
237           dest += rxstride;
238           abase += xstride;
239         }
240       abase -= xstride * xcount;
241       bbase += ystride;
242       dest += rystride - (rxstride * xcount);
243     }
244 }
245
246 #endif
247