View difference between Paste ID: ajUiQrQX and pTYUbaip
SHOW: | | - or go back to the newest paste.
1
#ifndef FFT_H_INCLUDED
2
#define FFT_H_INCLUDED
3
4
5
//   fft.h - template functions for FFT transform
6
//   The code is derived from LIBROW FFT code (www.librow.com)
7
8
#include <complex>
9
10
11
namespace fft {
12
13
14
	namespace _ {
15
16
17
		template<typename T> struct ComplexType { typedef std::complex< typename std::remove_reference<typename std::remove_const<T>::type>::type> type;};
18
		template<typename T> struct ComplexType<std::complex<T>> {typedef typename std::complex<T> type;};
19
20
		inline void updateTarget(size_t& target, const size_t size)
21
		{
22
			size_t Mask = size;
23
			while (target & (Mask >>= 1))
24
				target &= ~Mask;
25
			target |= Mask;
26
		}
27
28
29
30
		//! @return destination's end iterator
31
		template<typename IterSrc, typename IterDst>
32
		IterDst rearrange(IterSrc srcFirst, IterSrc srcLast, IterDst dstFirst)
33
		{
34
			const size_t size = srcLast - srcFirst;
35
			size_t target = 0;
36
			for (; srcFirst != srcLast; ++srcFirst)
37
			{
38
				*(dstFirst + target) = *srcFirst;
39
				updateTarget(target, size);
40
			}
41
			return dstFirst + size;
42
		}
43
44
45
46
		//! Inplace version of rearrange function
47
		template<typename IterDst>
48
		void rearrange(IterDst dstFirst, IterDst dstLast)
49
		{
50
			size_t target = 0;
51
			const size_t size = dstLast - dstFirst;
52
			for (auto i = dstFirst; i != dstLast; ++i)
53
			{
54
				if (target > size_t(i - dstFirst))
55
					std::swap(*i, *(dstFirst + target));
56
				updateTarget(target, size);
57
			}
58
		}
59
60
61
		//! Actual direct or inverse FFT on rearranged data
62
		template<typename IterDst>
63
		void perform(IterDst dstFirst, IterDst dstLast, const bool inverse = false)
64
		{
65
			typedef typename std::remove_reference<decltype(*dstFirst)>::type Complex;
66
			typedef typename Complex::value_type Number;
67
			const Number pi = inverse ? Number(3.14159265358979323846) : Number(-3.14159265358979323846);
68
			const size_t size = dstLast - dstFirst;
69
			for (size_t step = 1; step < size; step <<= 1)
70
			{
71
				const size_t jump = step << 1;
72
				const Number delta = pi / Number(step);
73-
				const Number sine = sin(delta * .5);
73+
				const Number sine = std::sin(delta * .5);
74-
				const Complex multiplier(-2. * sine * sine, sin(delta));
74+
				const Complex multiplier(-2. * sine * sine, std::sin(delta));
75
				Complex factor(1.);
76
				for (size_t group = 0; group < step; ++group)
77
				{
78
					for (size_t pair = group; pair < size; pair += jump)
79
					{
80
						const size_t match = pair + step;
81
						const Complex product(factor * dstFirst[match]);
82
						dstFirst[match] = dstFirst[pair] - product;
83
						dstFirst[pair] += product;
84
					}
85
					factor = multiplier * factor + factor;
86
				}
87
			}
88
		}
89
90
		//! Scaling of inverse FFT result
91
		template<typename IterDst>
92
		void scale(IterDst dstFirst, IterDst dstLast)
93
		{
94
			typedef typename std::remove_reference<decltype(*dstFirst)>::type Complex;
95
			typedef typename Complex::value_type Number;
96
			const Number factor = 1. / Number(dstLast - dstFirst);
97
			for (; dstFirst != dstLast; ++dstFirst)
98
				*dstFirst *= factor;
99
		}
100
101
102
103
	}
104
105
	//! Plain FFT
106
	//! @tparam IterSrc source iterator (read-only, random access), dereferences to numeric type Number1
107
	//! @tparam IterDst destination iterator (writeable, random access), dereferences to complex<Number2>, Number2 must be constructible from Number1
108
	//! @pre dstFirst has capacity at least srcLast - srcFirst, and srcLast - srcFirst must be power of 2
109
	//! @return destination's end iterator
110
	template<typename IterSrc, typename IterDst>
111
	IterDst transform (IterSrc srcFirst, IterSrc srcLast, IterDst dstFirst)
112
	{
113
		const auto dstLast = ::fft::_::rearrange(srcFirst, srcLast, dstFirst);
114
		::fft::_::perform(dstFirst, dstLast);
115
		return dstLast;
116
	}
117
118
	//! In-place FFT
119
	//! @tparam IterDst destination iterator (writeable, random access), dereferences to complex<Number>
120
	//! @pre srcLast - srcFirst must be power of 2
121
	template<typename IterDst>
122
	void transform (IterDst dstFirst, IterDst dstLast)
123
	{
124
		::fft::_::rearrange(dstFirst, dstLast);
125
		::fft::_::perform(dstFirst, dstLast);
126
	}
127
128
	//! Inverse FFT
129
	//! @tparam IterDst destination iterator (writeable, random access), dereferences to complex<Number>
130
	//! @pre dstFirst has capacity at least srcLast - srcFirst, and srcLast - srcFirst must be power of 2
131
	template<typename IterDst>
132
	void inverse (IterDst srcFirst, IterDst srcLast, IterDst dstFirst, const bool doScale = true)
133
	{
134-
		const auto dstLast = ::fft::transform(srcFirst, srcLast, dstFirst);
134+
135
		::fft::_::perform(dstFirst, dstLast, true);
136
		if(doScale)
137
			::fft::_::scale(dstFirst, dstLast);
138
	}
139
140
	//! In-place inverse FFT
141
	//! @tparam IterDst destination iterator (writeable, random access), dereferences to complex<Number>
142
	//! @pre srcLast - srcFirst must be power of 2
143
	template<typename IterDst>
144
	void inverse (IterDst dstFirst, IterDst dstLast, const bool doScale = true)
145-
		::fft::transform(dstFirst, dstLast);
145+
146
		::fft::_::rearrange(dstFirst, dstLast);
147
		::fft::_::perform(dstFirst, dstLast, true);
148
		if(doScale)
149
			::fft::_::scale(dstFirst, dstLast);
150
	}
151
152
153
}
154
155
#endif