📄 ft_11.cc
字号:
// file: $isip/class/algo/FourierTransform/ft_11.cc// version: $Id: ft_11.cc,v 1.6 2002/01/31 21:41:46 zheng Exp $//// isip include files//#include "FourierTransform.h"#include "FourierTransformFh.h"// method: fhInit//// arguments:// long order: (input) new order//// return: a boolean value indicating status//// this method creates lookup tables for the fast hartley transform//// this code is based on the algorithm as described in the work by// Ron Mayer whose code is available as free-ware. the algorithm is// described in the paper:// Hsieh S. Hou,"The Fast Hartley Transform Algorithm",// IEEE Transactions on Computers, pp. 147-153, February 1987.//boolean FourierTransform::fhInit(long order_a) { // if previous implementation and order are the same as // the current ones and the current transform object // is valid, then we are done // if (is_valid_d && (prev_implementation_d == FAST_HARTLEY) && (prev_order_d == order_a)) { // exit gracefully // return true; } // refresh the previous implementation type and transform order // prev_implementation_d = FAST_HARTLEY; prev_order_d = order_a; // assign the order // order_d = order_a; // after this method the twiddle factors will be valid // is_valid_d = true; // allocate memory for the temporary workspace used // tempd_d.setLength(order_d); wd_real_d.setLength(order_d); wd_imag_d.setLength(order_d); // exit gracefully // return true; }// method: fhReal//// arguments:// VectorFloat& output: (output) output data vector// const VectorFloat& input: (input) input data vector// boolean isReal: (input) is the input data real?//// return: a boolean value indicating status//// this method implements a real fast hartley transform//// this code is based on the algorithm as described in the work by// Ron Mayer whose code is available as free-ware. the algorithm is// described in the paper:// Hsieh S. Hou,"The Fast Hartley Transform Algorithm",// IEEE Transactions on Computers, pp. 147-153, February 1987.//boolean FourierTransform::fhReal(VectorFloat& output_a, const VectorFloat& input_a, boolean isReal_a) { // declare local variables // float a, b; float c1, s1, s2, c2, s3, c3, s4, c4; float f0, g0, f1, g1, f2, g2, f3, g3; long i, j, kk, k, k1, k2, k3, k4, kx, m, temp; long fi, fn, gi; long N_d_2 = order_d >> 1; // initializes the variable in the lookup table // TRIG_VARS; // allocate memory for output vector // output_a.setLength(2 * order_d); if (!fhInit(order_d)) { return Error::handle(name(), L"fhReal", ERR_INIT, __FILE__, __LINE__); } if (!isPower((long&)m, 2, order_d)) { return Error::handle(name(), L"fhReal", ERR_ORDER, __FILE__, __LINE__); } // copy input data to temporary memory so that the input data is retained // after calculations. // for (k = 0; k < order_d; ++k) { output_a(k) = 0; tempd_d(k) = input_a(k); } // perform bit reversal // for (k1 = 1, k2 = 0; k1 < order_d; ++k1) { for (k = order_d >> 1; (!((k2 ^= k) & k)); k >>= 1) { ; } if (k1 > k2) { a = tempd_d(k1); tempd_d(k1) = tempd_d(k2); tempd_d(k2) = a; } } // get the exponent of two // for (k = 0; (1 << k) < order_d; ++k); k &= (long)1; // twiddleless radix-2 computations when order is an even power of 2 // completes the stage before the g's in fig.2 // if (k == 0) { for (fi = 0, fn = order_d; fi < fn; fi += 4) { f1 = tempd_d(fi + 0) - tempd_d(fi + 1); f0 = tempd_d(fi + 0) + tempd_d(fi + 1); f3 = tempd_d(fi + 2) - tempd_d(fi + 3); f2 = tempd_d(fi + 2) + tempd_d(fi + 3); tempd_d(fi + 2) = f0 - f2; tempd_d(fi + 0) = f0 + f2; tempd_d(fi + 3) = f1 - f3; tempd_d(fi + 1) = f1 + f3; } } // twiddleless radix-2 computations when order is an odd power of 2 // completes the stages till g's in fig. 1 // else { for (fi = 0, fn = order_d, gi = fi + 1; fi < fn; fi += 8, gi += 8) { c1 = tempd_d(fi + 0) - tempd_d(gi + 0); s1 = tempd_d(fi + 0) + tempd_d(gi + 0); c2 = tempd_d(fi + 2) - tempd_d(gi + 2); s2 = tempd_d(fi + 2) + tempd_d(gi + 2); c3 = tempd_d(fi + 4) - tempd_d(gi + 4); s3 = tempd_d(fi + 4) + tempd_d(gi + 4); c4 = tempd_d(fi + 6) - tempd_d(gi + 6); s4 = tempd_d(fi + 6) + tempd_d(gi + 6); f1 = s1 - s2; f0 = s1 + s2; g1 = c1 - c2; g0 = c1 + c2; f3 = s3 - s4; f2 = s3 + s4; g3 = c4 * Integral::SQRT2; g2 = c3 * Integral::SQRT2; tempd_d(fi + 4) = f0 - f2; tempd_d(fi + 0) = f0 + f2; tempd_d(fi + 6) = f1 - f3; tempd_d(fi + 2) = f1 + f3; tempd_d(gi + 4) = g0 - g2; tempd_d(gi + 0) = g0 + g2; tempd_d(gi + 6) = g1 - g3; tempd_d(gi + 2) = g1 + g3; } } // stop computations here if order is less than 16 // if (order_d < (long)16) { if (isReal_a) { // get fourier coefficients from hartley coefficients // for (i = 1, j = ((long)order_d - 1), k = N_d_2; i < k; ++i, --j) { a = tempd_d(i); b = tempd_d(j); tempd_d(j) = (a - b) * (double)0.5; tempd_d(i) = (a + b) * (double)0.5; } // interlace the output and put into output_a // output_a(0) = tempd_d(0); output_a(1) = 0.0; for ( kk = 1; kk <= N_d_2; ++kk ) { output_a(2 * kk) = output_a(2 * order_d - 2 * kk ) = tempd_d(kk); output_a(2 * order_d - 2 * kk + 1 ) = tempd_d(order_d - kk); output_a(2 * kk + 1) = -tempd_d(order_d - kk); } output_a((long)order_d + 1) = 0.0; } if (!isReal_a) { // get the output data // for (kk = 0; kk < order_d; ++kk) { output_a(kk) = tempd_d(kk); } } // exit gracefully // return true; } // if order is greater than 16, continue twiddled computations // // does the computations for the even indices // do { k += 2; k1 = 1 << k; temp = k1; k2 = temp << 1; temp = k2; k4 = temp << 1; k3 = k1 + k2; temp = k1; kx = temp >> 1; fi = 0; gi = fi + kx; fn = order_d; do { f1 = tempd_d(fi) - tempd_d(fi + k1); f0 = tempd_d(fi) + tempd_d(fi + k1); f3 = tempd_d(fi + k2) - tempd_d(fi + k3); f2 = tempd_d(fi + k2) + tempd_d(fi + k3); tempd_d(fi + k2) = f0 - f2; tempd_d(fi) = f0 + f2; tempd_d(fi + k3) = f1 - f3; tempd_d(fi + k1) = f1 + f3; g1 = tempd_d(gi) - tempd_d(gi + k1); g0 = tempd_d(gi) + tempd_d(gi + k1); g3 = (float)tempd_d(gi + k3) * Integral::SQRT2; g2 = (float)tempd_d(gi + k2) * Integral::SQRT2; tempd_d(gi + k2) = g0 - g2; tempd_d(gi) = g0 + g2; tempd_d(gi + k3) = g1 - g3; tempd_d(gi + k1) = g1 + g3; gi = gi + k4; fi = fi + k4; } while (fi < fn); TRIG_INIT(k, c1, s1); // does computations for odd indices, this includes multiplication by // the twiddles. note that these computations use some sort of look // ahead and avoids redundancy of computations. // for (i = 1; (long)i < (long)kx; ++i) { // uses the euler form of approximation to compute the cosines // TRIG_NEXT(k, c1, s1); c2 = (c1 * c1) - (s1 * s1); s2 = (c1 * s1) * 2; fn = order_d; fi = i; gi = k1 - i; do { b = s2 * tempd_d(fi + k1) - c2 * tempd_d(gi + k1); a = c2 * tempd_d(fi + k1) + s2 * tempd_d(gi + k1); f1 = tempd_d(fi) - a; f0 = tempd_d(fi) + a; g1 = tempd_d(gi) - b; g0 = tempd_d(gi) + b; b = s2 * tempd_d(fi + k3) - c2 * tempd_d(gi + k3); a = c2 * tempd_d(fi + k3) + s2 * tempd_d(gi + k3); f3 = tempd_d(fi + k2) - a; f2 = tempd_d(fi + k2) + a; g3 = tempd_d(gi + k2) - b; g2 = tempd_d(gi + k2) + b; b = s1 * f2 - c1 * g3; a = c1 * f2 + s1 * g3; tempd_d(fi + k2) = f0 - a; tempd_d(fi) = f0 + a; tempd_d(gi + k3) = g1 - b; tempd_d(gi + k1) = g1 + b; b = c1 * g2 - s1 * f3; a = s1 * g2 + c1 * f3; tempd_d(gi + k2) = g0 - a; tempd_d(gi) = g0 + a; tempd_d(fi + k3) = f1 - b; tempd_d(fi + k1) = f1 + b; gi = gi + k4; fi = fi + k4; } while (fi < fn); } TRIG_RESET(k, c1, s1); } while (k4 < order_d); a = b = (double)0; if (!isReal_a) { // get the output data // for (kk = 0; kk < order_d; ++kk) { output_a(kk) = tempd_d(kk); } } if (isReal_a) { // get fourier coefficients from hartley coefficients // for (i = 1, j = ((long)order_d - 1), k = N_d_2; i < k; ++i, --j) { a = tempd_d(i); b = tempd_d(j); tempd_d(j) = (a - b) * (double)0.5; tempd_d(i) = (a + b) * (double)0.5; } // interlace the output and put into output_a // output_a(0) = tempd_d(0); output_a(1) = (double)0; for (kk = 1; kk <= N_d_2; ++kk) { output_a(kk * 2) = output_a(2 * order_d - kk * 2 ) = tempd_d(kk); output_a(kk * 2 + 1) = -tempd_d(order_d - kk); output_a(2 * order_d - kk * 2 + 1 ) = tempd_d(order_d - kk); } output_a((long)order_d + 1) = 0.0; } // exit gracefully // return true;}// method: fhComplex//// arguments:// VectorFloat& output: (output) output data vector// const VectorFloat& input: (input) input data vector//// return: a boolean value indicating status//// this method implements a complex fast hartley transform//// this code is based on the algorithm as described in the work by// Ron Mayer whose code is available as free-ware. the algorithm is// described in the paper:// Hsieh S. Hou,"The Fast Hartley Transform Algorithm",// IEEE Transactions on Computers, pp. 147-153, February 1987.//boolean FourierTransform::fhComplex(VectorFloat& output_a, const VectorFloat& input_a) { // declare local variables // float a, b, c, d; float q, r, s, t; long i, j, k, m, N_d_2; // allocate memory for output vector // output_a.setLength(2 * order_d); if (!fhInit(order_d)) { return Error::handle(name(), L"fhComplex", ERR_INIT, __FILE__, __LINE__); } if (!isPower((long&)m, 2, order_d)) { return Error::handle(name(), L"fhComplex", ERR_ORDER, __FILE__, __LINE__); } // copy input data to temporary memory and zero the output so that // the input data is retained after calculations. // for (k = 0; k < order_d; ++k) { wd_real_d(k) = input_a(k*2); wd_imag_d(k) = input_a(k*2 + 1); } // prepare data for FHT computations // N_d_2 = order_d >> 1; for (i = 1, j = (long)order_d - 1, k = N_d_2; i < k; ++i, --j) { a = wd_real_d(i); b = wd_real_d(j); q = a + b; r = a - b; c = wd_imag_d(i); d = wd_imag_d(j); s = c + d; t = c - d; wd_real_d(i) = (q + t) * 0.5; wd_real_d(j) = (q - t) * 0.5; wd_imag_d(i) = (s - r) * 0.5; wd_imag_d(j) = (s + r) * 0.5; } // compute hartley transform of the real and imaginary parts separately // fhReal(output_a, wd_real_d, false); fhReal(wd_real_d, wd_imag_d, false); // interlace output and put into output_d array // for (k = (long)order_d - 1; k >= 0; --k) { output_a(k * 2) = output_a(k); output_a(k * 2 + 1) = wd_real_d(k); } // exit gracefully // return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -