OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libgfortran/] [intrinsics/] [spread_generic.c] - Blame information for rev 15

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* Generic implementation of the SPREAD intrinsic
2
   Copyright 2002, 2005 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
Ligbfortran 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 <string.h>
35
#include "libgfortran.h"
36
 
37
static void
38
spread_internal (gfc_array_char *ret, const gfc_array_char *source,
39
                 const index_type *along, const index_type *pncopies,
40
                 index_type size)
41
{
42
  /* r.* indicates the return array.  */
43
  index_type rstride[GFC_MAX_DIMENSIONS];
44
  index_type rstride0;
45
  index_type rdelta = 0;
46
  index_type rrank;
47
  index_type rs;
48
  char *rptr;
49
  char *dest;
50
  /* s.* indicates the source array.  */
51
  index_type sstride[GFC_MAX_DIMENSIONS];
52
  index_type sstride0;
53
  index_type srank;
54
  const char *sptr;
55
 
56
  index_type count[GFC_MAX_DIMENSIONS];
57
  index_type extent[GFC_MAX_DIMENSIONS];
58
  index_type n;
59
  index_type dim;
60
  index_type ncopies;
61
 
62
  srank = GFC_DESCRIPTOR_RANK(source);
63
 
64
  rrank = srank + 1;
65
  if (rrank > GFC_MAX_DIMENSIONS)
66
    runtime_error ("return rank too large in spread()");
67
 
68
  if (*along > rrank)
69
      runtime_error ("dim outside of rank in spread()");
70
 
71
  ncopies = *pncopies;
72
 
73
  if (ret->data == NULL)
74
    {
75
      /* The front end has signalled that we need to populate the
76
         return array descriptor.  */
77
      ret->dtype = (source->dtype & ~GFC_DTYPE_RANK_MASK) | rrank;
78
      dim = 0;
79
      rs = 1;
80
      for (n = 0; n < rrank; n++)
81
        {
82
          ret->dim[n].stride = rs;
83
          ret->dim[n].lbound = 0;
84
          if (n == *along - 1)
85
            {
86
              ret->dim[n].ubound = ncopies - 1;
87
              rdelta = rs * size;
88
              rs *= ncopies;
89
            }
90
          else
91
            {
92
              count[dim] = 0;
93
              extent[dim] = source->dim[dim].ubound + 1
94
                - source->dim[dim].lbound;
95
              sstride[dim] = source->dim[dim].stride * size;
96
              rstride[dim] = rs * size;
97
 
98
              ret->dim[n].ubound = extent[dim]-1;
99
              rs *= extent[dim];
100
              dim++;
101
            }
102
        }
103
      ret->offset = 0;
104
      ret->data = internal_malloc_size (rs * size);
105
    }
106
  else
107
    {
108
      dim = 0;
109
      if (GFC_DESCRIPTOR_RANK(ret) != rrank)
110
        runtime_error ("rank mismatch in spread()");
111
 
112
      if (ret->dim[0].stride == 0)
113
        ret->dim[0].stride = 1;
114
 
115
      for (n = 0; n < rrank; n++)
116
        {
117
          if (n == *along - 1)
118
            {
119
              rdelta = ret->dim[n].stride * size;
120
            }
121
          else
122
            {
123
              count[dim] = 0;
124
              extent[dim] = source->dim[dim].ubound + 1
125
                - source->dim[dim].lbound;
126
              sstride[dim] = source->dim[dim].stride * size;
127
              rstride[dim] = ret->dim[n].stride * size;
128
              dim++;
129
            }
130
        }
131
      if (sstride[0] == 0)
132
        sstride[0] = size;
133
    }
134
  sstride0 = sstride[0];
135
  rstride0 = rstride[0];
136
  rptr = ret->data;
137
  sptr = source->data;
138
 
139
  while (sptr)
140
    {
141
      /* Spread this element.  */
142
      dest = rptr;
143
      for (n = 0; n < ncopies; n++)
144
        {
145
          memcpy (dest, sptr, size);
146
          dest += rdelta;
147
        }
148
      /* Advance to the next element.  */
149
      sptr += sstride0;
150
      rptr += rstride0;
151
      count[0]++;
152
      n = 0;
153
      while (count[n] == extent[n])
154
        {
155
          /* When we get to the end of a dimension, reset it and increment
156
             the next dimension.  */
157
          count[n] = 0;
158
          /* We could precalculate these products, but this is a less
159
             frequently used path so probably not worth it.  */
160
          sptr -= sstride[n] * extent[n];
161
          rptr -= rstride[n] * extent[n];
162
          n++;
163
          if (n >= srank)
164
            {
165
              /* Break out of the loop.  */
166
              sptr = NULL;
167
              break;
168
            }
169
          else
170
            {
171
              count[n]++;
172
              sptr += sstride[n];
173
              rptr += rstride[n];
174
            }
175
        }
176
    }
177
}
178
 
179
/* This version of spread_internal treats the special case of a scalar
180
   source.  This is much simpler than the more general case above.  */
181
 
182
static void
183
spread_internal_scalar (gfc_array_char *ret, const char *source,
184
                        const index_type *along, const index_type *pncopies,
185
                        index_type size)
186
{
187
  int n;
188
  int ncopies = *pncopies;
189
  char * dest;
190
 
191
  if (GFC_DESCRIPTOR_RANK (ret) != 1)
192
    runtime_error ("incorrect destination rank in spread()");
193
 
194
  if (*along > 1)
195
    runtime_error ("dim outside of rank in spread()");
196
 
197
  if (ret->data == NULL)
198
    {
199
      ret->data = internal_malloc_size (ncopies * size);
200
      ret->offset = 0;
201
      ret->dim[0].stride = 1;
202
      ret->dim[0].lbound = 0;
203
      ret->dim[0].ubound = ncopies - 1;
204
    }
205
  else
206
    {
207
      if (ret->dim[0].stride == 0)
208
        ret->dim[0].stride = 1;
209
 
210
      if (ncopies - 1 > (ret->dim[0].ubound - ret->dim[0].lbound)
211
                           / ret->dim[0].stride)
212
        runtime_error ("dim too large in spread()");
213
    }
214
 
215
  for (n = 0; n < ncopies; n++)
216
    {
217
      dest = (char*)(ret->data + n*size*ret->dim[0].stride);
218
      memcpy (dest , source, size);
219
    }
220
}
221
 
222
extern void spread (gfc_array_char *, const gfc_array_char *,
223
                    const index_type *, const index_type *);
224
export_proto(spread);
225
 
226
void
227
spread (gfc_array_char *ret, const gfc_array_char *source,
228
        const index_type *along, const index_type *pncopies)
229
{
230
  spread_internal (ret, source, along, pncopies, GFC_DESCRIPTOR_SIZE (source));
231
}
232
 
233
extern void spread_char (gfc_array_char *, GFC_INTEGER_4,
234
                         const gfc_array_char *, const index_type *,
235
                         const index_type *, GFC_INTEGER_4);
236
export_proto(spread_char);
237
 
238
void
239
spread_char (gfc_array_char *ret,
240
             GFC_INTEGER_4 ret_length __attribute__((unused)),
241
             const gfc_array_char *source, const index_type *along,
242
             const index_type *pncopies, GFC_INTEGER_4 source_length)
243
{
244
  spread_internal (ret, source, along, pncopies, source_length);
245
}
246
 
247
/* The following are the prototypes for the versions of spread with a
248
   scalar source.  */
249
 
250
extern void spread_scalar (gfc_array_char *, const char *,
251
                           const index_type *, const index_type *);
252
export_proto(spread_scalar);
253
 
254
void
255
spread_scalar (gfc_array_char *ret, const char *source,
256
               const index_type *along, const index_type *pncopies)
257
{
258
  if (!ret->dtype)
259
    runtime_error ("return array missing descriptor in spread()");
260
  spread_internal_scalar (ret, source, along, pncopies, GFC_DESCRIPTOR_SIZE (ret));
261
}
262
 
263
 
264
extern void spread_char_scalar (gfc_array_char *, GFC_INTEGER_4,
265
                                const char *, const index_type *,
266
                                const index_type *, GFC_INTEGER_4);
267
export_proto(spread_char_scalar);
268
 
269
void
270
spread_char_scalar (gfc_array_char *ret,
271
                    GFC_INTEGER_4 ret_length __attribute__((unused)),
272
                    const char *source, const index_type *along,
273
                    const index_type *pncopies, GFC_INTEGER_4 source_length)
274
{
275
  if (!ret->dtype)
276
    runtime_error ("return array missing descriptor in spread()");
277
  spread_internal_scalar (ret, source, along, pncopies, source_length);
278
}
279
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.