ndarray
NumPy-friendly multidimensional arrays in C++
Loading...
Searching...
No Matches
FourierOps.h
Go to the documentation of this file.
1// -*- c++ -*-
2/*
3 * Copyright (c) 2010-2012, Jim Bosch
4 * All rights reserved.
5 *
6 * ndarray is distributed under a simple BSD-like license;
7 * see the LICENSE file that should be present in the root
8 * of the source distribution, or alternately available at:
9 * https://github.com/ndarray/ndarray
10 */
11#ifndef NDARRAY_FFT_FourierOps_h_INCLUDED
12#define NDARRAY_FFT_FourierOps_h_INCLUDED
13
20#include <boost/noncopyable.hpp>
21
22#include "ndarray.h"
23
24namespace ndarray {
26namespace detail {
27
28#ifdef _MSC_VER
30static const double M_PI = 4. * atan(1.);
31#endif
32
37template <typename T, int N>
38struct FourierOps {
39
40 template <int C>
41 static void shift(
42 T const * offset,
43 std::complex<T> const & factor,
44 ArrayRef<std::complex<T>,N,C> const & array,
45 int const real_last_dim
46 ) {
47 typename ArrayRef<std::complex<T>,N,C>::Iterator iter = array.begin();
48 T u = -2.0 * M_PI * (*offset) / array.size();
49 int kMid = (array.size() + 1) / 2;
50 for (int k = 0; k < kMid; ++k, ++iter) {
51 FourierOps<T,N-1>::shift(offset+1, factor * std::polar(static_cast<T>(1), u * k),
52 *iter, real_last_dim);
53 }
54 if (array.size() % 2 == 0) {
55 FourierOps<T,N-1>::shift(offset+1, factor * std::cos(u * kMid), *iter, real_last_dim);
56 ++iter;
57 ++kMid;
58 }
59 for (int k_n = kMid - array.size(); k_n < 0; ++k_n, ++iter) {
60 FourierOps<T,N-1>::shift(offset+1, factor * std::polar(static_cast<T>(1), u * k_n),
61 *iter, real_last_dim);
62 }
63 }
64
65 template <int C>
66 static void differentiate(int m, ArrayRef<std::complex<T>,N,C> const & array, int const real_last_dim) {
67 typename ArrayRef<std::complex<T>,N,C>::Iterator iter = array.begin();
68 int kMid = (array.size() + 1) / 2;
69 T u = 2.0 * M_PI / array.size();
70 for (int k = 0; k < kMid; ++k, ++iter) {
71 if (m == N) (*iter) *= std::complex<T>(static_cast<T>(0), u * T(k));
72 FourierOps<T,N-1>::differentiate(m, *iter, real_last_dim);
73 }
74 if (array.size() % 2 == 0) {
75 (*iter) = static_cast<T>(0);
76 ++iter;
77 ++kMid;
78 }
79 for (int k_n = kMid - array.size(); k_n < 0; ++k_n, ++iter) {
80 if (m == N) (*iter) *= std::complex<T>(static_cast<T>(0), u * T(k_n));
81 FourierOps<T,N-1>::differentiate(m, *iter, real_last_dim);
82 }
83 }
84
85};
86
91template <typename T>
92struct FourierOps<T,1> {
93
94 template <int C>
95 static void shift(
96 T const * offset,
97 std::complex<T> const & factor,
98 ArrayRef<std::complex<T>,1,C> const & array,
99 int const real_last_dim
100 ) {
101 typename ArrayRef<std::complex<T>,1,C>::Iterator iter = array.begin();
102 T u = -2.0 * M_PI * (*offset) / real_last_dim;
103 int kMid = (real_last_dim + 1) / 2;
104 for (int k = 0; k < kMid; ++k, ++iter) {
105 (*iter) *= factor * std::polar(1.0, u * T(k));
106 }
107 if (real_last_dim % 2 == 0) {
108 (*iter) *= factor * std::cos(u * kMid);
109 ++iter;
110 }
111 }
112
113 template <int C>
114 static void differentiate(int m, ArrayRef<std::complex<T>,1,C> const & array, int const real_last_dim) {
115 typename ArrayRef<std::complex<T>,1,C>::Iterator iter = array.begin();
116 int kMid = (real_last_dim + 1) / 2;
117 if (m == 1) {
118 T u = 2.0 * M_PI / real_last_dim;
119 for (int k = 0; k < kMid; ++k, ++iter) {
120 (*iter) *= std::complex<T>(static_cast<T>(0), u * T(k));
121 }
122 }
123 if (real_last_dim % 2 == 0) {
124 array[kMid] = static_cast<T>(0);
125 }
126 }
127
128};
129
130} // namespace detail
132
138template <typename T, int N, int C>
139void shift(
140 Vector<T,N> const & offset,
141 Array<std::complex<T>,N,C> const & array,
142 int const real_last_dim
143) {
144 detail::FourierOps<T,N>::shift(
145 offset.begin(),
146 static_cast< std::complex<T> >(1),
147 array.deep(),
148 real_last_dim
149 );
150}
151
157template <typename T, int N, int C>
159 int n,
160 Array<std::complex<T>,N,C> const & array,
161 int const real_last_dim
162) {
163 detail::FourierOps<T,N>::differentiate(N-n, array.deep(), real_last_dim);
164}
165
166} // namespace ndarray
167
168#endif // !NDARRAY_FFT_FourierOps_h_INCLUDED
A multidimensional strided array.
Definition Array.h:35
void shift(Vector< T, N > const &offset, Array< std::complex< T >, N, C > const &array, int const real_last_dim)
Perform a Fourier-space translation transform.
Definition FourierOps.h:139
void differentiate(int n, Array< std::complex< T >, N, C > const &array, int const real_last_dim)
Numerically differentiate the array in Fourier-space in the given dimension.
Definition FourierOps.h:158
Main public header file for ndarray.
A fixed-size 1D array class.
Definition Vector.h:82
iterator begin()
Return an iterator to the beginning of the Vector.
Definition Vector.h:111