/// <summary> /// Performs FHT "in place" for given double[] array slice. /// </summary> /// <param name="slice">Double array slice.</param> /// <param name="length">Slice length.</param> /// <param name="lengthLog2">Log2(<paramref name="length" />).</param> static public void Fht(double *slice, uint length, int lengthLog2) { // Special fast processing for length == 4 if (length == 4) { Fht4(slice); return; } // Divide data into 2 recursively processed parts length >>= 1; --lengthLog2; double *rightSlice = slice + length; uint lengthDiv2 = length >> 1; uint lengthDiv4 = length >> 2; // Perform initial "butterfly" operations over left and right array parts double leftDigit = slice[0]; double rightDigit = rightSlice[0]; slice[0] = leftDigit + rightDigit; rightSlice[0] = leftDigit - rightDigit; leftDigit = slice[lengthDiv2]; rightDigit = rightSlice[lengthDiv2]; slice[lengthDiv2] = leftDigit + rightDigit; rightSlice[lengthDiv2] = leftDigit - rightDigit; // Get initial trig values //TrigValues trigValues = GetInitialTrigValues(lengthLog2); TrigValues trigValues = new TrigValues(); GetInitialTrigValues(&trigValues, lengthLog2); // Perform "butterfly" for (uint i = 1; i < lengthDiv4; ++i) { FhtButterfly(slice, rightSlice, i, length - i, trigValues.Cos, trigValues.Sin); FhtButterfly(slice, rightSlice, lengthDiv2 - i, lengthDiv2 + i, trigValues.Sin, trigValues.Cos); // Get next trig values NextTrigValues(&trigValues); } // Final "butterfly" FhtButterfly(slice, rightSlice, lengthDiv4, length - lengthDiv4, Sqrt2Div2, Sqrt2Div2); // Finally perform recursive run Fht(slice, length, lengthLog2); Fht(rightSlice, length, lengthLog2); }
/// <summary> /// Performs reverse FHT "in place" for given double[] array slice. /// </summary> /// <param name="slice">Double array slice.</param> /// <param name="length">Slice length.</param> /// <param name="lengthLog2">Log2(<paramref name="length" />).</param> static public void ReverseFht(double *slice, uint length, int lengthLog2) { // Special fast processing for length == 8 if (length == 8) { ReverseFht8(slice); return; } // Divide data into 2 recursively processed parts length >>= 1; --lengthLog2; double *rightSlice = slice + length; uint lengthDiv2 = length >> 1; uint lengthDiv4 = length >> 2; // Perform recursive run ReverseFht(slice, length, lengthLog2); ReverseFht(rightSlice, length, lengthLog2); // Get initial trig values TrigValues trigValues = new TrigValues(); GetInitialTrigValues(&trigValues, lengthLog2); // Perform "butterfly" for (uint i = 1; i < lengthDiv4; ++i) { ReverseFhtButterfly(slice, rightSlice, i, length - i, trigValues.Cos, trigValues.Sin); ReverseFhtButterfly(slice, rightSlice, lengthDiv2 - i, lengthDiv2 + i, trigValues.Sin, trigValues.Cos); // Get next trig values NextTrigValues(&trigValues); } // Final "butterfly" ReverseFhtButterfly(slice, rightSlice, lengthDiv4, length - lengthDiv4, Sqrt2Div2, Sqrt2Div2); ReverseFhtButterfly2(slice, rightSlice, 0, 0, 1.0, 0); ReverseFhtButterfly2(slice, rightSlice, lengthDiv2, lengthDiv2, 0, 1.0); }
/// <summary> /// Generates next trigonometry values for FHT basing on previous ones. /// </summary> /// <param name="valuesPtr">Current trig values.</param> private static void NextTrigValues(TrigValues* valuesPtr) { double oldCos = valuesPtr->Cos; valuesPtr->Cos = valuesPtr->Cos * valuesPtr->TableCos - valuesPtr->Sin * valuesPtr->TableSin + valuesPtr->Cos; valuesPtr->Sin = valuesPtr->Sin * valuesPtr->TableCos + oldCos * valuesPtr->TableSin + valuesPtr->Sin; }
/// <summary> /// Initializes trigonometry values for FHT. /// </summary> /// <param name="valuesPtr">Values to init.</param> /// <param name="lengthLog2">Log2(processing slice length).</param> private static void GetInitialTrigValues(TrigValues* valuesPtr, int lengthLog2) { valuesPtr->TableSin = SineTable[lengthLog2]; valuesPtr->TableCos = SineTable[lengthLog2 + 1]; valuesPtr->TableCos *= -2.0 * valuesPtr->TableCos; valuesPtr->Sin = valuesPtr->TableSin; valuesPtr->Cos = valuesPtr->TableCos + 1.0; }
/// <summary> /// Performs reverse FHT "in place" for given double[] array slice. /// </summary> /// <param name="slice">Double array slice.</param> /// <param name="length">Slice length.</param> /// <param name="lengthLog2">Log2(<paramref name="length" />).</param> public static void ReverseFht(double* slice, uint length, int lengthLog2) { // Special fast processing for length == 8 if (length == 8) { ReverseFht8(slice); return; } // Divide data into 2 recursively processed parts length >>= 1; --lengthLog2; double* rightSlice = slice + length; uint lengthDiv2 = length >> 1; uint lengthDiv4 = length >> 2; // Perform recursive run ReverseFht(slice, length, lengthLog2); ReverseFht(rightSlice, length, lengthLog2); // Get initial trig values TrigValues trigValues = new TrigValues(); GetInitialTrigValues(&trigValues, lengthLog2); // Perform "butterfly" for (uint i = 1; i < lengthDiv4; ++i) { ReverseFhtButterfly(slice, rightSlice, i, length - i, trigValues.Cos, trigValues.Sin); ReverseFhtButterfly(slice, rightSlice, lengthDiv2 - i, lengthDiv2 + i, trigValues.Sin, trigValues.Cos); // Get next trig values NextTrigValues(&trigValues); } // Final "butterfly" ReverseFhtButterfly(slice, rightSlice, lengthDiv4, length - lengthDiv4, Sqrt2Div2, Sqrt2Div2); ReverseFhtButterfly2(slice, rightSlice, 0, 0, 1.0, 0); ReverseFhtButterfly2(slice, rightSlice, lengthDiv2, lengthDiv2, 0, 1.0); }
/// <summary> /// Performs FHT "in place" for given double[] array slice. /// </summary> /// <param name="slice">Double array slice.</param> /// <param name="length">Slice length.</param> /// <param name="lengthLog2">Log2(<paramref name="length" />).</param> public static void Fht(double* slice, uint length, int lengthLog2) { // Special fast processing for length == 4 if (length == 4) { Fht4(slice); return; } // Divide data into 2 recursively processed parts length >>= 1; --lengthLog2; double* rightSlice = slice + length; uint lengthDiv2 = length >> 1; uint lengthDiv4 = length >> 2; // Perform initial "butterfly" operations over left and right array parts double leftDigit = slice[0]; double rightDigit = rightSlice[0]; slice[0] = leftDigit + rightDigit; rightSlice[0] = leftDigit - rightDigit; leftDigit = slice[lengthDiv2]; rightDigit = rightSlice[lengthDiv2]; slice[lengthDiv2] = leftDigit + rightDigit; rightSlice[lengthDiv2] = leftDigit - rightDigit; // Get initial trig values //TrigValues trigValues = GetInitialTrigValues(lengthLog2); TrigValues trigValues = new TrigValues(); GetInitialTrigValues(&trigValues, lengthLog2); // Perform "butterfly" for (uint i = 1; i < lengthDiv4; ++i) { FhtButterfly(slice, rightSlice, i, length - i, trigValues.Cos, trigValues.Sin); FhtButterfly(slice, rightSlice, lengthDiv2 - i, lengthDiv2 + i, trigValues.Sin, trigValues.Cos); // Get next trig values NextTrigValues(&trigValues); } // Final "butterfly" FhtButterfly(slice, rightSlice, lengthDiv4, length - lengthDiv4, Sqrt2Div2, Sqrt2Div2); // Finally perform recursive run Fht(slice, length, lengthLog2); Fht(rightSlice, length, lengthLog2); }