status_t Ifft(mcon::Vector<double>& timeSeries, const mcon::Matrix<double>& complex) { const size_t N = complex.GetColumnLength(); if (Count1(N) != 1) { return -ERROR_ILLEGAL; } mcon::Vector<double> tsPair; mcon::Vector<double> sinTable; mcon::Vector<double> cosTable; if ( false == timeSeries.Resize(N) || false == tsPair.Resize(N) || false == sinTable.Resize(N) || false == cosTable.Resize(N) ) { return -ERROR_CANNOT_ALLOCATE_MEMORY; } const double df = 2.0 * g_Pi / N; for (size_t i = 0; i < N / 2; ++i) { sinTable[i] = sin(df * i); cosTable[i] = cos(df * i); } // Substitute beforehand timeSeries = complex[0]; tsPair = complex[1]; size_t innerLoop = N / 2; size_t outerLoop = 1; // Decimation in frequency. for ( ; 0 < innerLoop; innerLoop >>= 1, outerLoop <<= 1) { //DEBUG_LOG("inner=%d, outer=%d\n", innerLoop, outerLoop); for (size_t outer = 0; outer < outerLoop; ++outer ) { const int& step = innerLoop; const int ofs = outer * step * 2; // Easier to look into. void* _pTs = timeSeries; void* _pTsPair = tsPair; double* pTsL = reinterpret_cast<double*>(_pTs) + ofs; double* pTsPairL = reinterpret_cast<double*>(_pTsPair) + ofs; double* pTsH = reinterpret_cast<double*>(_pTs) + ofs + step; double* pTsPairH = reinterpret_cast<double*>(_pTsPair) + ofs + step; for (size_t k = 0; k < innerLoop; ++k ) { const double r1 = pTsL[k]; const double i1 = pTsPairL[k]; const double r2 = pTsH[k]; const double i2 = pTsPairH[k]; const size_t idx = k * outerLoop; pTsL[k] = r1 + r2; pTsPairL[k] = i1 + i2; pTsH[k] = (r1 - r2) * cosTable[idx] - (i1 - i2) * sinTable[idx]; pTsPairH[k] = (r1 - r2) * sinTable[idx] + (i1 - i2) * cosTable[idx]; //DEBUG_LOG("step=%d, ofs=%d, k=%d, idx=%d\n", step, ofs, k, idx); } } } // Bit-reverse const int width = Ilog2(N); //DEBUG_LOG("width=%d\n", width); for (size_t i = 0; i < N; ++i ) { const size_t k = BitReverse(i, width); if (k < i) { continue; } const double ts_temp = timeSeries[k] / N; timeSeries[k] = timeSeries[i] / N; timeSeries[i] = ts_temp; } return NO_ERROR; }
status_t Fft(mcon::Matrix<double>& complex, const mcon::Vector<double>& timeSeries) { const size_t N = timeSeries.GetLength(); if (Count1(N) != 1) { return -ERROR_ILLEGAL; } bool status = complex.Resize(2, N); if (false == status) { return -ERROR_CANNOT_ALLOCATE_MEMORY; } mcon::VectordBase& real = complex[0]; mcon::VectordBase& imag = complex[1]; const double df = 2.0 * g_Pi / N; mcon::Vector<double> sinTable(N/2); mcon::Vector<double> cosTable(N/2); for (size_t i = 0; i < N / 2; ++i) { sinTable[i] = sin(df * i); cosTable[i] = cos(df * i); } // Substitute beforehand real = timeSeries; imag = 0; size_t innerLoop = N / 2; int outerLoop = 1; //DEBUG_LOG("N=%d\n", N); // Decimation in frequency. for ( ; 0 < innerLoop; innerLoop >>= 1, outerLoop <<= 1) { //DEBUG_LOG("inner=%d, outer=%d\n", innerLoop, outerLoop); for ( int outer = 0; outer < outerLoop; ++outer ) { const int& step = innerLoop; const int ofs = outer * step * 2; #if 0 for (size_t k = 0; k < innerLoop; ++k ) { const double r1 = real[k+ofs]; const double i1 = imag[k+ofs]; const double r2 = real[k+step+ofs]; const double i2 = imag[k+step+ofs]; real[k+ofs] = r1 + r2; imag[k+ofs] = i1 + i2; const int idx = k * outerLoop; //DEBUG_LOG("step=%d, ofs=%d, k=%d, idx=%d\n", step, ofs, k, idx); real[k+step+ofs] = (r1 - r2) * cosTable[idx] + (i1 - i2) * sinTable[idx]; imag[k+step+ofs] = - (r1 - r2) * sinTable[idx] + (i1 - i2) * cosTable[idx]; } #else // Easier to look into. void* _pReal = real; void* _pImag = imag; double* pRealL = reinterpret_cast<double*>(_pReal) + ofs; double* pImagL = reinterpret_cast<double*>(_pImag) + ofs; double* pRealH = reinterpret_cast<double*>(_pReal) + ofs + step; double* pImagH = reinterpret_cast<double*>(_pImag) + ofs + step; for (size_t k = 0; k < innerLoop; ++k ) { const double r1 = pRealL[k]; const double i1 = pImagL[k]; const double r2 = pRealH[k]; const double i2 = pImagH[k]; const size_t idx = k * outerLoop; pRealL[k] = r1 + r2; pImagL[k] = i1 + i2; pRealH[k] = (r1 - r2) * cosTable[idx] + (i1 - i2) * sinTable[idx]; pImagH[k] = - (r1 - r2) * sinTable[idx] + (i1 - i2) * cosTable[idx]; //DEBUG_LOG("step=%d, ofs=%d, k=%d, idx=%d\n", step, ofs, k, idx); } #endif } } // Bit-reverse const int width = Ilog2(N); //DEBUG_LOG("width=%d\n", width); for (size_t i = 0; i < N; ++i ) { const size_t k = BitReverse(i, width); if (k == i || k < i) { continue; } const double real_temp = real[k]; const double imag_temp = imag[k]; real[k] = real[i]; imag[k] = imag[i]; real[i] = real_temp; imag[i] = imag_temp; } return NO_ERROR; }
void HuffmanDecoder::Initialize(const unsigned int *codeBits, unsigned int nCodes) { // the Huffman codes are represented in 3 ways in this code: // // 1. most significant code bit (i.e. top of code tree) in the least significant bit position // 2. most significant code bit (i.e. top of code tree) in the most significant bit position // 3. most significant code bit (i.e. top of code tree) in n-th least significant bit position, // where n is the maximum code length for this code tree // // (1) is the way the codes come in from the deflate stream // (2) is used to sort codes so they can be binary searched // (3) is used in this function to compute codes from code lengths // // a code in representation (2) is called "normalized" here // The BitReverse() function is used to convert between (1) and (2) // The NormalizeCode() function is used to convert from (3) to (2) if (nCodes == 0) throw Err("null code"); m_maxCodeBits = *std::max_element(codeBits, codeBits+nCodes); if (m_maxCodeBits > MAX_CODE_BITS) throw Err("code length exceeds maximum"); if (m_maxCodeBits == 0) throw Err("null code"); // count number of codes of each length SecBlockWithHint<unsigned int, 15+1> blCount(m_maxCodeBits+1); std::fill(blCount.begin(), blCount.end(), 0); unsigned int i; for (i=0; i<nCodes; i++) blCount[codeBits[i]]++; // compute the starting code of each length code_t code = 0; SecBlockWithHint<code_t, 15+1> nextCode(m_maxCodeBits+1); nextCode[1] = 0; for (i=2; i<=m_maxCodeBits; i++) { // compute this while checking for overflow: code = (code + blCount[i-1]) << 1 if (code > code + blCount[i-1]) throw Err("codes oversubscribed"); code += blCount[i-1]; if (code > (code << 1)) throw Err("codes oversubscribed"); code <<= 1; nextCode[i] = code; } if (code > (1 << m_maxCodeBits) - blCount[m_maxCodeBits]) throw Err("codes oversubscribed"); else if (m_maxCodeBits != 1 && code < (1 << m_maxCodeBits) - blCount[m_maxCodeBits]) throw Err("codes incomplete"); // compute a vector of <code, length, value> triples sorted by code m_codeToValue.resize(nCodes - blCount[0]); unsigned int j=0; for (i=0; i<nCodes; i++) { unsigned int len = codeBits[i]; if (len != 0) { code = NormalizeCode(nextCode[len]++, len); m_codeToValue[j].code = code; m_codeToValue[j].len = len; m_codeToValue[j].value = i; j++; } } std::sort(m_codeToValue.begin(), m_codeToValue.end()); // initialize the decoding cache m_cacheBits = STDMIN(9U, m_maxCodeBits); m_cacheMask = (1 << m_cacheBits) - 1; m_normalizedCacheMask = NormalizeCode(m_cacheMask, m_cacheBits); CRYPTOPP_ASSERT(m_normalizedCacheMask == BitReverse(m_cacheMask)); if (m_cache.size() != size_t(1) << m_cacheBits) m_cache.resize(1 << m_cacheBits); for (i=0; i<m_cache.size(); i++) m_cache[i].type = 0; }