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

Subversion Repositories scarts

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* Generic implementation of the EOSHIFT 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
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 "config.h"
32
#include <stdlib.h>
33
#include <assert.h>
34
#include <string.h>
35
#include "libgfortran.h"
36
 
37
/* TODO: make this work for large shifts when
38
   sizeof(int) < sizeof (index_type).  */
39
 
40
static void
41
eoshift0 (gfc_array_char * ret, const gfc_array_char * array,
42
          int shift, const char * pbound, int which, index_type size,
43
          char filler)
44
{
45
  /* r.* indicates the return array.  */
46
  index_type rstride[GFC_MAX_DIMENSIONS];
47
  index_type rstride0;
48
  index_type roffset;
49
  char *rptr;
50
  char *dest;
51
  /* s.* indicates the source array.  */
52
  index_type sstride[GFC_MAX_DIMENSIONS];
53
  index_type sstride0;
54
  index_type soffset;
55
  const char *sptr;
56
  const char *src;
57
 
58
  index_type count[GFC_MAX_DIMENSIONS];
59
  index_type extent[GFC_MAX_DIMENSIONS];
60
  index_type dim;
61
  index_type len;
62
  index_type n;
63
 
64
  /* The compiler cannot figure out that these are set, initialize
65
     them to avoid warnings.  */
66
  len = 0;
67
  soffset = 0;
68
  roffset = 0;
69
 
70
  if (ret->data == NULL)
71
    {
72
      int i;
73
 
74
      ret->data = internal_malloc_size (size * size0 ((array_t *)array));
75
      ret->offset = 0;
76
      ret->dtype = array->dtype;
77
      for (i = 0; i < GFC_DESCRIPTOR_RANK (array); i++)
78
        {
79
          ret->dim[i].lbound = 0;
80
          ret->dim[i].ubound = array->dim[i].ubound - array->dim[i].lbound;
81
 
82
          if (i == 0)
83
            ret->dim[i].stride = 1;
84
          else
85
            ret->dim[i].stride = (ret->dim[i-1].ubound + 1) * ret->dim[i-1].stride;
86
        }
87
    }
88
 
89
  which = which - 1;
90
 
91
  extent[0] = 1;
92
  count[0] = 0;
93
  n = 0;
94
  for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
95
    {
96
      if (dim == which)
97
        {
98
          roffset = ret->dim[dim].stride * size;
99
          if (roffset == 0)
100
            roffset = size;
101
          soffset = array->dim[dim].stride * size;
102
          if (soffset == 0)
103
            soffset = size;
104
          len = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
105
        }
106
      else
107
        {
108
          count[n] = 0;
109
          extent[n] = array->dim[dim].ubound + 1 - array->dim[dim].lbound;
110
          rstride[n] = ret->dim[dim].stride * size;
111
          sstride[n] = array->dim[dim].stride * size;
112
          n++;
113
        }
114
    }
115
  if (sstride[0] == 0)
116
    sstride[0] = size;
117
  if (rstride[0] == 0)
118
    rstride[0] = size;
119
 
120
  dim = GFC_DESCRIPTOR_RANK (array);
121
  rstride0 = rstride[0];
122
  sstride0 = sstride[0];
123
  rptr = ret->data;
124
  sptr = array->data;
125
 
126
  if ((shift >= 0 ? shift : -shift) > len)
127
    {
128
      shift = len;
129
      len = 0;
130
    }
131
  else
132
    {
133
      if (shift > 0)
134
        len = len - shift;
135
      else
136
        len = len + shift;
137
    }
138
 
139
  while (rptr)
140
    {
141
      /* Do the shift for this dimension.  */
142
      if (shift > 0)
143
        {
144
          src = &sptr[shift * soffset];
145
          dest = rptr;
146
        }
147
      else
148
        {
149
          src = sptr;
150
          dest = &rptr[-shift * roffset];
151
        }
152
      for (n = 0; n < len; n++)
153
        {
154
          memcpy (dest, src, size);
155
          dest += roffset;
156
          src += soffset;
157
        }
158
      if (shift >= 0)
159
        {
160
          n = shift;
161
        }
162
      else
163
        {
164
          dest = rptr;
165
          n = -shift;
166
        }
167
 
168
      if (pbound)
169
        while (n--)
170
          {
171
            memcpy (dest, pbound, size);
172
            dest += roffset;
173
          }
174
      else
175
        while (n--)
176
          {
177
            memset (dest, filler, size);
178
            dest += roffset;
179
          }
180
 
181
      /* Advance to the next section.  */
182
      rptr += rstride0;
183
      sptr += sstride0;
184
      count[0]++;
185
      n = 0;
186
      while (count[n] == extent[n])
187
        {
188
          /* When we get to the end of a dimension, reset it and increment
189
             the next dimension.  */
190
          count[n] = 0;
191
          /* We could precalculate these products, but this is a less
192
             frequently used path so proabably not worth it.  */
193
          rptr -= rstride[n] * extent[n];
194
          sptr -= sstride[n] * extent[n];
195
          n++;
196
          if (n >= dim - 1)
197
            {
198
              /* Break out of the loop.  */
199
              rptr = NULL;
200
              break;
201
            }
202
          else
203
            {
204
              count[n]++;
205
              rptr += rstride[n];
206
              sptr += sstride[n];
207
            }
208
        }
209
    }
210
}
211
 
212
 
213
#define DEFINE_EOSHIFT(N)                                                     \
214
  extern void eoshift0_##N (gfc_array_char *, const gfc_array_char *,         \
215
                            const GFC_INTEGER_##N *, const char *,            \
216
                            const GFC_INTEGER_##N *);                         \
217
  export_proto(eoshift0_##N);                                                 \
218
                                                                              \
219
  void                                                                        \
220
  eoshift0_##N (gfc_array_char *ret, const gfc_array_char *array,             \
221
                const GFC_INTEGER_##N *pshift, const char *pbound,            \
222
                const GFC_INTEGER_##N *pdim)                                  \
223
  {                                                                           \
224
    eoshift0 (ret, array, *pshift, pbound, pdim ? *pdim : 1,                  \
225
              GFC_DESCRIPTOR_SIZE (array), 0);                                 \
226
  }                                                                           \
227
                                                                              \
228
  extern void eoshift0_##N##_char (gfc_array_char *, GFC_INTEGER_4,           \
229
                                   const gfc_array_char *,                    \
230
                                   const GFC_INTEGER_##N *, const char *,     \
231
                                   const GFC_INTEGER_##N *, GFC_INTEGER_4,    \
232
                                   GFC_INTEGER_4);                            \
233
  export_proto(eoshift0_##N##_char);                                          \
234
                                                                              \
235
  void                                                                        \
236
  eoshift0_##N##_char (gfc_array_char *ret,                                   \
237
                       GFC_INTEGER_4 ret_length __attribute__((unused)),      \
238
                       const gfc_array_char *array,                           \
239
                       const GFC_INTEGER_##N *pshift,                         \
240
                       const char *pbound,                                    \
241
                       const GFC_INTEGER_##N *pdim,                           \
242
                       GFC_INTEGER_4 array_length,                            \
243
                       GFC_INTEGER_4 bound_length __attribute__((unused)))    \
244
  {                                                                           \
245
    eoshift0 (ret, array, *pshift, pbound, pdim ? *pdim : 1,                  \
246
              array_length, ' ');                                             \
247
  }
248
 
249
DEFINE_EOSHIFT (1);
250
DEFINE_EOSHIFT (2);
251
DEFINE_EOSHIFT (4);
252
DEFINE_EOSHIFT (8);

powered by: WebSVN 2.1.0

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