transpose_c4.c 3.45 KB
Newer Older
1
/* Implementation of the TRANSPOSE intrinsic
2
   Copyright (C) 2003-2014 Free Software Foundation, Inc.
3 4
   Contributed by Tobias Schlter

5
This file is part of the GNU Fortran runtime library (libgfortran).
6 7 8 9

Libgfortran is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
10
version 3 of the License, or (at your option) any later version.
11 12 13 14 15 16

Libgfortran is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

17 18 19 20 21 22 23 24
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.

You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
<http://www.gnu.org/licenses/>.  */
25 26

#include "libgfortran.h"
27 28
#include <assert.h>

29

30 31
#if defined (HAVE_GFC_COMPLEX_4)

Janne Blomqvist committed
32 33
extern void transpose_c4 (gfc_array_c4 * const restrict ret, 
	gfc_array_c4 * const restrict source);
34 35 36
export_proto(transpose_c4);

void
Janne Blomqvist committed
37 38
transpose_c4 (gfc_array_c4 * const restrict ret, 
	gfc_array_c4 * const restrict source)
39 40 41
{
  /* r.* indicates the return array.  */
  index_type rxstride, rystride;
42
  GFC_COMPLEX_4 * restrict rptr;
43 44 45 46 47 48 49 50 51
  /* s.* indicates the source array.  */
  index_type sxstride, systride;
  const GFC_COMPLEX_4 *sptr;

  index_type xcount, ycount;
  index_type x, y;

  assert (GFC_DESCRIPTOR_RANK (source) == 2);

52
  if (ret->base_addr == NULL)
53 54 55 56
    {
      assert (GFC_DESCRIPTOR_RANK (ret) == 2);
      assert (ret->dtype == source->dtype);

57 58
      GFC_DIMENSION_SET(ret->dim[0], 0, GFC_DESCRIPTOR_EXTENT(source,1) - 1,
			1);
59

60 61
      GFC_DIMENSION_SET(ret->dim[1], 0, GFC_DESCRIPTOR_EXTENT(source,0) - 1,
			GFC_DESCRIPTOR_EXTENT(source, 1));
62

63
      ret->base_addr = xmalloc (sizeof (GFC_COMPLEX_4) * size0 ((array_t *) ret));
64
      ret->offset = 0;
65 66 67 68
    } else if (unlikely (compile_options.bounds_check))
    {
      index_type ret_extent, src_extent;

69 70
      ret_extent = GFC_DESCRIPTOR_EXTENT(ret,0);
      src_extent = GFC_DESCRIPTOR_EXTENT(source,1);
71 72 73 74 75 76 77

      if (src_extent != ret_extent)
	runtime_error ("Incorrect extent in return value of TRANSPOSE"
		       " intrinsic in dimension 1: is %ld,"
		       " should be %ld", (long int) src_extent,
		       (long int) ret_extent);

78 79
      ret_extent = GFC_DESCRIPTOR_EXTENT(ret,1);
      src_extent = GFC_DESCRIPTOR_EXTENT(source,0);
80 81 82 83 84 85 86

      if (src_extent != ret_extent)
	runtime_error ("Incorrect extent in return value of TRANSPOSE"
		       " intrinsic in dimension 2: is %ld,"
		       " should be %ld", (long int) src_extent,
		       (long int) ret_extent);

87 88
    }

89 90 91 92
  sxstride = GFC_DESCRIPTOR_STRIDE(source,0);
  systride = GFC_DESCRIPTOR_STRIDE(source,1);
  xcount = GFC_DESCRIPTOR_EXTENT(source,0);
  ycount = GFC_DESCRIPTOR_EXTENT(source,1);
93

94 95
  rxstride = GFC_DESCRIPTOR_STRIDE(ret,0);
  rystride = GFC_DESCRIPTOR_STRIDE(ret,1);
96

97 98
  rptr = ret->base_addr;
  sptr = source->base_addr;
99 100 101 102 103 104 105 106 107 108 109 110 111 112

  for (y=0; y < ycount; y++)
    {
      for (x=0; x < xcount; x++)
        {
          *rptr = *sptr;

          sptr += sxstride;
          rptr += rystride;
        }
        sptr += systride - (sxstride * xcount);
        rptr += rxstride - (rystride * xcount);
    }
}
113 114

#endif