OSDN Git Service

gcc/fortran/
[pf3gnuchains/gcc-fork.git] / libgfortran / generated / matmul_l4.c
1 /* Implementation of the MATMUL intrinsic
2    Copyright 2002 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 (libgfor).
6
7 Libgfortran is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 Libgfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with libgfor; see the file COPYING.LIB.  If not,
19 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 #include "config.h"
23 #include <stdlib.h>
24 #include <assert.h>
25 #include "libgfortran.h"
26
27 /* Dimensions: retarray(x,y) a(x, count) b(count,y).
28    Either a or b can be rank 1.  In this case x or y is 1.  */
29
30 extern void matmul_l4 (gfc_array_l4 *, gfc_array_l4 *, gfc_array_l4 *);
31 export_proto(matmul_l4);
32
33 void
34 matmul_l4 (gfc_array_l4 * retarray, gfc_array_l4 * a, gfc_array_l4 * b)
35 {
36   GFC_INTEGER_4 *abase;
37   GFC_INTEGER_4 *bbase;
38   GFC_LOGICAL_4 *dest;
39   index_type rxstride;
40   index_type rystride;
41   index_type xcount;
42   index_type ycount;
43   index_type xstride;
44   index_type ystride;
45   index_type x;
46   index_type y;
47
48   GFC_INTEGER_4 *pa;
49   GFC_INTEGER_4 *pb;
50   index_type astride;
51   index_type bstride;
52   index_type count;
53   index_type n;
54
55   assert (GFC_DESCRIPTOR_RANK (a) == 2
56           || GFC_DESCRIPTOR_RANK (b) == 2);
57
58   if (retarray->data == NULL)
59     {
60       if (GFC_DESCRIPTOR_RANK (a) == 1)
61         {
62           retarray->dim[0].lbound = 0;
63           retarray->dim[0].ubound = b->dim[1].ubound - b->dim[1].lbound;
64           retarray->dim[0].stride = 1;
65         }
66       else if (GFC_DESCRIPTOR_RANK (b) == 1)
67         {
68           retarray->dim[0].lbound = 0;
69           retarray->dim[0].ubound = a->dim[0].ubound - a->dim[0].lbound;
70           retarray->dim[0].stride = 1;
71         }
72       else
73         {
74           retarray->dim[0].lbound = 0;
75           retarray->dim[0].ubound = a->dim[0].ubound - a->dim[0].lbound;
76           retarray->dim[0].stride = 1;
77           
78           retarray->dim[1].lbound = 0;
79           retarray->dim[1].ubound = b->dim[1].ubound - b->dim[1].lbound;
80           retarray->dim[1].stride = retarray->dim[0].ubound+1;
81         }
82           
83       retarray->data
84         = internal_malloc_size (sizeof (GFC_LOGICAL_4) * size0 (retarray));
85       retarray->base = 0;
86     }
87
88   abase = a->data;
89   if (GFC_DESCRIPTOR_SIZE (a) != 4)
90     {
91       assert (GFC_DESCRIPTOR_SIZE (a) == 8);
92       abase = GFOR_POINTER_L8_TO_L4 (abase);
93       astride <<= 1;
94     }
95   bbase = b->data;
96   if (GFC_DESCRIPTOR_SIZE (b) != 4)
97     {
98       assert (GFC_DESCRIPTOR_SIZE (b) == 8);
99       bbase = GFOR_POINTER_L8_TO_L4 (bbase);
100       bstride <<= 1;
101     }
102   dest = retarray->data;
103
104   if (retarray->dim[0].stride == 0)
105     retarray->dim[0].stride = 1;
106   if (a->dim[0].stride == 0)
107     a->dim[0].stride = 1;
108   if (b->dim[0].stride == 0)
109     b->dim[0].stride = 1;
110
111
112   if (GFC_DESCRIPTOR_RANK (retarray) == 1)
113     {
114       rxstride = retarray->dim[0].stride;
115       rystride = rxstride;
116     }
117   else
118     {
119       rxstride = retarray->dim[0].stride;
120       rystride = retarray->dim[1].stride;
121     }
122
123   /* If we have rank 1 parameters, zero the absent stride, and set the size to
124      one.  */
125   if (GFC_DESCRIPTOR_RANK (a) == 1)
126     {
127       astride = a->dim[0].stride;
128       count = a->dim[0].ubound + 1 - a->dim[0].lbound;
129       xstride = 0;
130       rxstride = 0;
131       xcount = 1;
132     }
133   else
134     {
135       astride = a->dim[1].stride;
136       count = a->dim[1].ubound + 1 - a->dim[1].lbound;
137       xstride = a->dim[0].stride;
138       xcount = a->dim[0].ubound + 1 - a->dim[0].lbound;
139     }
140   if (GFC_DESCRIPTOR_RANK (b) == 1)
141     {
142       bstride = b->dim[0].stride;
143       assert(count == b->dim[0].ubound + 1 - b->dim[0].lbound);
144       ystride = 0;
145       rystride = 0;
146       ycount = 1;
147     }
148   else
149     {
150       bstride = b->dim[0].stride;
151       assert(count == b->dim[0].ubound + 1 - b->dim[0].lbound);
152       ystride = b->dim[1].stride;
153       ycount = b->dim[1].ubound + 1 - b->dim[1].lbound;
154     }
155
156   for (y = 0; y < ycount; y++)
157     {
158       for (x = 0; x < xcount; x++)
159         {
160           /* Do the summation for this element.  For real and integer types
161              this is the same as DOT_PRODUCT.  For complex types we use do
162              a*b, not conjg(a)*b.  */
163           pa = abase;
164           pb = bbase;
165           *dest = 0;
166
167           for (n = 0; n < count; n++)
168             {
169               if (*pa && *pb)
170                 {
171                   *dest = 1;
172                   break;
173                 }
174               pa += astride;
175               pb += bstride;
176             }
177
178           dest += rxstride;
179           abase += xstride;
180         }
181       abase -= xstride * xcount;
182       bbase += ystride;
183       dest += rystride - (rxstride * xcount);
184     }
185 }