I am struggling since a couple of months to re-write Matlab code into C++
The bigger part of the work as been already done (fft, ifft, xcorr and binFreq functions have been already written in c++), now I am stuck to one function. the function is supposed to estimate delay between two signals S1 and S2. The function relies on FFT-based cross-correlation.
I am stuck in this line " e = [e, eIter];" where e is a vector with variable length ( e was declared earlier as : "e =[]";)
original function in Matlab:
% ****************************************************************
% estimates delay and scaling factor
% ****************************************************************
function [delay_samples, coeff] = iterDelayEst(s1, s2)
n = numel(s1);
halfN = floor(n/2);
assert(numel(s2) == n, 'signals must have same length');
% ****************************************************************
% constants
% ****************************************************************
% exit if uncertainty below threshold
thr_samples = 1e-7;
% exit after fixed number of iterations
nIter = 25;
% frequency domain representation of signals
fd1 = fft(s1);
fd2 = fft(s2);
% first round: No delay was applied
tau = []; %(1,0) ;
fd2Tau = fd2; % delayed s2 in freq. domain
% frequency corresponding to each FFT bin -0.5..0.5
f = binFreq(n);
% uncertainty plot data
e = [];
% normalization factor
nf = sqrt((fd1 * fd1') * (fd2 * fd2')) / n; % normalizes to 1
%nf = sqrt((fd1 .* conj(fd1)) * (fd2 .* conj(fd2))') / n;
% search window:
% known maximum and two surrounding points
x1 = -1;
x2 = -1;
x3 = -1;
y1 = -1;
y2 = -1;
y3 = -1;
% ****************************************************************
% iteration loop
% ****************************************************************
for count = 1:nIter
% ****************************************************************
% crosscorrelation with time-shifted signal
% ****************************************************************
xcorr = abs(ifft(fd2Tau .* conj(fd1)))/ nf;
% ****************************************************************
% detect peak
% ****************************************************************
if isempty(tau)
% ****************************************************************
% startup
% initialize with three adjacent bins around peak
% ****************************************************************
ix = find(xcorr == max(xcorr));
ix = ix(1); % use any, if multiple bitwise identical peaks
% indices of three bins around peak
ixLow = mod(ix-1-1, n) + 1; % one below
ixMid = ix;
ixHigh = mod(ix-1+1, n) + 1; % one above
% delay corresponding to the three bins
tauLow = mod(ixLow -1 + halfN, n) - halfN;
tauMid = mod(ixMid -1 + halfN, n) - halfN;
tauHigh = mod(ixHigh -1 + halfN, n) - halfN;
% crosscorrelation value for the three bins
xcLow = xcorr(ixLow);
xcMid = xcorr(ixMid);
xcHigh = xcorr(ixHigh);
x1 = tauLow;
x2 = tauMid;
x3 = tauHigh;
y1 = xcLow;
y2 = xcMid;
y3 = xcHigh;
else
% ****************************************************************
% only main peak at first bin is of interest
% ****************************************************************
tauMid = tau;
xcMid = xcorr(1);
if xcMid > y2
% ****************************************************************
% improve midpoint
% ****************************************************************
if tauMid > x2
% midpoint becomes lower point
x1 = x2;
y1 = y2;
else
% midpoint becomes upper point
x3 = x2;
y3 = y2;
end
x2 = tauMid;
y2 = xcMid;
elseif tauMid < x2
% ****************************************************************
% improve low point
% ****************************************************************
assert(tauMid >= x1); % bitwise identical is OK
assert(tauMid > x1 || xcMid > y1); % expect improvement
x1 = tauMid;
y1 = xcMid;
elseif tauMid > x2
% ****************************************************************
% improve high point
% ****************************************************************
assert(tauMid <= x3); % bitwise identical is OK
assert((tauMid < x3) || (xcMid > y3)); % expect improvement
x3 = tauMid;
y3 = xcMid;
else
assert(false, '?? evaluated for existing tau ??');
end
end
% ****************************************************************
% calculate uncertainty (window width)
% ****************************************************************
eIter = abs(x3 - x1);
e = [e, eIter];
if eIter < thr_samples
% disp('threshold reached, exiting');
break;
end
if y1 == y2 || y2 == y3
% reached limit of numerical accuracy on one side
usePoly = 0;
else
% ****************************************************************
% fit 2nd order polynomial and find maximum
% ****************************************************************
num = (x2^2-x1^2)*y3+(x1^2-x3^2)*y2+(x3^2-x2^2)*y1;
denom = (2*x2-2*x1)*y3+(2*x1-2*x3)*y2+(2*x3-2*x2)*y1;
if denom ~= 0
tau = (num / denom);
% is the point within [x1, x3]?
usePoly = ((tau > x1) && (tau < x3));
else
usePoly = 0;
end
end
if ~usePoly
% revert to linear interpolation on the side with the
% less-accurate outer sample
% Note: There is no guarantee that the side with the more accurate
% outer sample is the right one, as the samples aren't
% placed on a regular grid!
% Therefore, iterate to improve the "worse" side, which will
% eventually become the "better side", and iteration converges.
tauLow = (x1 + x2) / 2;
tauHigh = (x2 + x3) / 2;
if y1 < y3
o = [tauLow, tauHigh];
else
o = [tauHigh, tauLow];
end
% don't choose point that is identical to one that is already known
tau = o(1);
if tau == x1 || tau == x2 || tau == x3
tau = o(2);
if tau == x1 || tau == x2 || tau == x3
break;
end
end
end
% ****************************************************************
% advance 2nd signal according to location of maximum
% phase shift in frequency domain - delay in time domain
% ****************************************************************
fd2Tau = fd2 .* exp(2i * pi * f * tau);
end % for
% ****************************************************************
% the delay estimate is the final location of the delay that
% maximized crosscorrelation (center of window).
% ****************************************************************
delay_samples = x2;
% ****************************************************************
% Coefficient: Turn signal 1 into signal 2
% ****************************************************************
coeff = fd2Tau * fd1' ./ (fd1 * fd1');
end
C++ equivalent code I have written so far :
//iterDelayEst.cpp
#include <cstddef>
#include <utility>
#include <numeric>
#include <vector>
std::vector<std::size_t> max_indices(CArray const& y) {
struct acc_t {
std::vector<std::size_t> max_idcs;
double max_value;
std::size_t current_idx;
acc_t&& next() {
++current_idx;
return std::move(*this);
}
acc_t&& next_with_current() {
max_idcs.push_back(current_idx++);
return std::move(*this);
}
acc_t&& next_with(Complex const& c) {
max_value = c.real();
max_idcs.clear();
return next_with_current();
}
};
return std::accumulate(
std::begin(y), std::end(y), acc_t{},
[](acc_t acc, Complex const& c) {
return c.real() < acc.max_value ? acc.next()
: c.real() > acc.max_value ? acc.next_with(c)
: acc.next_with_current();
}
).max_idcs;
}
/****************************************************************************/
void tet(CArray const& y) {
auto const max_idcs = max_indices(y);
std::cout << "The max is " << y[max_idcs.front()] << " at indices [";
auto first = true;
for (auto const idx : max_idcs) {
if (!first) {
std::cout << ", ";
} else {
first = false;
}
std::cout << idx;
}
std::cout << "]\n";
}
/****************xcorr function**************************************************************/
void xcorr( CArray & x){
int i;
int n=32;
fft(x);
x *=x.apply(std::conj);
ifft(x);
for ( i = 0 ; i < n ; i++ ){
cout << "x[" << i <<"] =" << x[i] << endl;
}
}
double iterDelayEst(int n,CArray& x, CArray& y)
{
/***************************constants************************************************
/************************************************************************************/
//exit if uncertainty below threshold
int halfN=std::floor(n/2);
double thr_samples = 1e-7;
Complex eIter;
Complex e;
//exit after fixed number of iterations
double nIter = 25;
fft(x);
fft(y);
//frequency domain representation of signals
typedef std::vector < std::complex < double > > tau;
auto f = binFreq(n);
std::vector<double> e;
Complex nf3(0.0,0.0);
int j;
for ( j = 0 ; j < n ; j++ )
{
auto nf1 = ((x * x.apply(std::conj)) * (y * y.apply(std::conj)));
nf3 += nf1[j];
}
auto nf2 =std::sqrt(nf3);
auto nf =nf2/(double)n;
cout << "nf3" << nf3 <<endl;
cout << "nf2" << nf2 <<endl;
cout << "nf" << nf <<endl;
Complex x1(-1,0);
Complex x2(-1,0);
Complex x3(-1,0);
Complex y1(-1,0);
Complex y2(-1,0);
Complex y3(-1,0);
int i;
/***************************************iteration loop**********************************************
**************************************************************************************************/
//for(i=0; i<nIter; i++)
x = x.apply(std::conj);
y *= x;
ifft(y);
y =std::abs(y);
y=y/nf;
for ( i = 0 ; i < n ; i++ ){
cout << "y[" << i <<"] =" << y[i] << endl;
}
if (tau.empty())
{
tet(y);
Complex ix=y[0]; //use any, if multiple bitwise identical peaks
/***********indices of three bins around peak***********/
Complex ixLow= std::fmod(ix-1-1, n) +1 //one below
Complex ixMid=ix;
Complex ixHigh= std::fmod(ix-1+1, n) +1 //one above
/**********delay corresponding to the three bins*********/
Complex tauLow = std::fmod(ixLow -1 + halfN, n) - halfN;
Complex tauMid = std::fmod(ixMid -1 + halfN, n) - halfN;
Complex tauHigh = std::fmod(ixHigh -1 + halfN, n) - halfN;
/**********crosscorrelation value for the three bins******/
Complex xcLow = xcorr(ixLow);
Complex xcMid = xcorr(ixMid);
Complex xcHigh = xcorr(ixHigh);
x1 = tauLow;
x2 = tauMid;
x3 = tauHigh;
y1 = xcLow;
y2 = xcMid;
y3 = xcHigh;
}
else
{
/**********only main peak at first bin is of interest****/
tauMid =tau;
xcMid = xcorr(1);
if (xcMid > y2){
/**********improve midpoint***************************/
if(tauMid > x2){
//midpoint becomes lower point
x1 = x2;
y1 = y2;
}
else{
//midpoint becomes upper point
x3 = x2;
y3 = y2;
}
x2 = tauMid;
y2 = xcMid;
else if (tauMid < x2){
//improve high point
assert(tauMid >= x1); // bitwise identical is OK
assert(tauMid > x1 || xcMid > y1); //expect improvement
x1 = tauMid;
y1 = xcMid;
}
else if (tauMid > x2){
//improve high point
assert(tauMid <= x3); // bitwise identical is OK
assert((tauMid < x3) || (xcMid > y3)); // expect improvement
x3 = tauMid;
y3 = xcMid;
}
else{
assert(("?? evaluated for existing tau ??", false));
}
}
/*************Calculate uncertainty (Window Width)********************/
eIter =abs(x3-x1);
}
The entire Matlab program can be found here :
https://www.dsprelated.com/showcode/288.php
I will be very grateful for any help
Well, my Matlab training is really far away in time, but assuming that e = [e eIter] means that you append a value to e, then you need use a vector
define your e vector somewhere like this: you already done that in your code. Maybe you copied/pasted some code, I don't know, it looks rather neat.
std::vector<double> e;
However I doubt that will compile since you also have a Complex e declaration in the same scope...
// then in your loop populate it like this
eIter = abs(x3 - x1); // (this is your code)
e.push_back(eIter); // push_back was the method you need
Then you can access elements of e just like a standard C-array:
e[i]
To perform a loop, I use an old-style C++ iteration. I know there is better but my C++ is a bit rusty since 2006. Comments/edits are welcome to improve this:
// replace const_iterator by iterator to be able to modify the values
std::vector<double>::const_iterator it;
for (it = e.begin(); it != e.end(); it++)
{
const double &value = *it; // (remove const to be able to change the value)
...
Related
I have always used the function "fft(x)" in matlab where "x" is a vector of complex numbers. I am looking for an easy to use function in C++ that would return complex numbers.
I have found this code : http://paulbourke.net/miscellaneous/dft/
If it is equivalent, how can I use it ? Thank you for your time !
/*
This computes an in-place complex-to-complex FFT
x and y are the real and imaginary arrays of 2^m points.
dir = 1 gives forward transform
dir = -1 gives reverse transform
*/
short FFT(short int dir,long m,double *x,double *y)
{
long n,i,i1,j,k,i2,l,l1,l2;
double c1,c2,tx,ty,t1,t2,u1,u2,z;
/* Calculate the number of points */
n = 1;
for (i=0;i<m;i++)
n *= 2;
/* Do the bit reversal */
i2 = n >> 1;
j = 0;
for (i=0;i<n-1;i++) {
if (i < j) {
tx = x[i];
ty = y[i];
x[i] = x[j];
y[i] = y[j];
x[j] = tx;
y[j] = ty;
}
k = i2;
while (k <= j) {
j -= k;
k >>= 1;
}
j += k;
}
/* Compute the FFT */
c1 = -1.0;
c2 = 0.0;
l2 = 1;
for (l=0;l<m;l++) {
l1 = l2;
l2 <<= 1;
u1 = 1.0;
u2 = 0.0;
for (j=0;j<l1;j++) {
for (i=j;i<n;i+=l2) {
i1 = i + l1;
t1 = u1 * x[i1] - u2 * y[i1];
t2 = u1 * y[i1] + u2 * x[i1];
x[i1] = x[i] - t1;
y[i1] = y[i] - t2;
x[i] += t1;
y[i] += t2;
}
z = u1 * c1 - u2 * c2;
u2 = u1 * c2 + u2 * c1;
u1 = z;
}
c2 = sqrt((1.0 - c1) / 2.0);
if (dir == 1)
c2 = -c2;
c1 = sqrt((1.0 + c1) / 2.0);
}
/* Scaling for forward transform */
if (dir == 1) {
for (i=0;i<n;i++) {
x[i] /= n;
y[i] /= n;
}
}
return(TRUE);
}
Alternative Suggestion:
I had same problem. I used fft library from fftw.
http://www.fftw.org/download.html
Its performance is similar to matlab.
The code looks fine at first glance. The original FFT is not a lot of code.
One feature of the FFT is that it is an inplace operation. Many higher level bindings effectively hide that fact.
So you put your real and imaginary parts into the x and y arrays. After the executing the function you read those same arrays for your result.
This particularly simple implementation will only work with powers of 2 as the original FFT. If you have inputs of lengths other than powers of 2 you could zero-pad your signal.
Google the book Numerical Recipes and fft (older versions are freely available) if you want to read up on the background of the FFT. The version in that book is different from other implementations in that you have to feed in the real and imaginary parts interleaved.
What I'm missing on the implementation that you are quoting is the use of pi or trigonometric functions. You'll have to try it out to compare against Matlab.
I am unit testing the following C++ code using Visual Studio 2015's built in test framework. When I run the test below, no error is thrown (and the code compiles), but the test just hangs. It only does it when the line I have commented out which calls averageGradient is run. Why is this?
float averageGradient(int x1, int x2) {
int i = 0, y1 = 0, y2 = 0;
while (i < graph.size() && (y1 == 0 || y2 == 0)) { //if both y values haven't been solved then keep trying
if (x1 >= graph[i][0] && x1 < graph[i][1]) { // if x1 lies in the first straight line segment
y1 = (graph[i][2] * x1) + graph[i][2]; // then calculate it's y value (y1)
}
else if (x2 >= graph[i][0] && x2 < graph[i][1]) { //try the same thing for x2
y2 = (graph[i][2] * x2) + graph[i][3]; //calculate its y value (y2)
}
else { i++; } //otherwise incriment i to check the next straight line segment
}
float m = (y2 - y1) / (x2 - x1);
return m;
};
Unit Testing:
TEST_METHOD(Average_Gradient) {
int x1 = 683675;
int x2 = x1 + 86400;
//float gradient = averageGradient(x1, x2);
float answer = 0.0000895684639;
//Assert::AreEqual(answer, gradient);
}
There is an infinite loop in your code. This is not related to unit test.
float averageGradient(int x1, int x2) {
int i = 0, y1 = 0, y2 = 0;
while (i < graph.size() && (y1 == 0 || y2 == 0)) // 1
{
if (x1 >= graph[i][0] && x1 < graph[i][1]) // 2
{
y1 = (graph[i][2] * x1) + graph[i][2]; // 3
}
else if (x2 >= graph[i][0] && x2 < graph[i][1]) // 4
{
y2 = (graph[i][2] * x2) + graph[i][3];
}
else { i++; }
}
float m = (y2 - y1) / (x2 - x1);
return m;
};
In the first iteration of your loop, let's assume that condition in line marked with // 2 is true.
You enter line // 3, and change y1. i and y2 are not modified.
Now you go to next iteration.
i hasn't changed so i < graph.size() is still true.
y2 hasn't changed so (y1 == 0 || y2 == 0) is still true.
Thus, you go to line // 2: the condition is true again, as neither x1 nor graph[] values have changed.
Execution enters // 3, y1 is not modified
Execution continues at 3. (infinite loop)
If your first iteration enters // 4 instead of // 2, the same thing happens.
You should be able to easily analyze this just by running your code under debugger.
I am testing some code with Visual Studio's built in Unit test framework for C++. The test just call the following routine and then does an Assert::AreEqual(returned_value, (float)1)however, all other tests run and this just hangs. I can't see why the loops would be infinite loops, but I am likely missing something. Thanks.
vector< vector<float> > history;
vector< vector<float> > graph;
float calculateDeviation(int period) {
int x1 = history.front()[0];
int x2 = x1 + period;
int i = 0, minimum, maximum, SSres = 0, SStot = 0, j=0, R2 =0;
float average = 0;
while (x2 <= history.back()[0]) {
average += averageGradient(x1, x2);
x1 = x2;
x2 = + period;
}
x1 = history.front()[0];
x2 = x1 + period;
i++;
while (j < i) {
SSres += pow((graph[i][0]-((graph[i][2]*graph[i][0])+graph[i][3])), 2);
SStot += pow(graph[i][0] - average, 2);
x1 = x2;
x2 = + period;
j++;
}
R2 = 1 - (SSres / SStot);
return R2;
}
The following values are measured & returned in the unit test.
history.size() = 15
history[5].size() = 14
graph.size() = 14
graph[1].size() = 4
I'm trying to find prime roots with this algorithm:
std::vector<unsigned long long> Keyexchange::primroot(unsigned long long val) {
std::vector<unsigned long long> res;
for (unsigned long long i = 2; i<val - 1; i++) {
unsigned long long start = 1;
bool flag = 1;
for (unsigned long long j = 0; j<val / 2; j++) {
start = (start * i) % val;
if (start % val == 1) {
flag = 0;
break;
}
}
if (flag) {
res.push_back(i);
}
}
return res;
}
It works great but it is very very slow.
I want to calculate the primitive roots of big numbers like 1073741789. It would be the best if there is a possibility to set a range because I am calculating the whole set right now.
So basicely I am looking for a way [code snipet would be great] to generate about 100.000 of the biggest primitive roots out of that given big number.
I know that it is much faster with the Eulersche φ-function but I have no idea how to implement it.
Thanks a lot.
First, if you pick a random integer from 2 to p-1 then it has a decent chance of being a primitive root. So you pick a random integer (or you start with 2), check it, and if it fails, you pick the next one etc.
To check that x is a primitive root: It means that x^(p-1) = 1 (modulo p), but no smaller power of p is. Take for example p = 31, p-1 = 30 = 2 x 3 x 5. If p is not a primitive root, then one of x^(30/2), x^(30/3) and x^(30/5) must be 1 (modulo p).
Factor p-1 in its prime factors, calculate x^((p-1)/f) (modulo p) for every prime factor f, and x is a primitive root if none of the results is 1.
Of course x^y (modulo p) needs to be calculated with repeated squaring/multiplying. For example to calculate x^10 you would calculate x^2, x^4, x^5, x^10 in that order.
Once you found a primitive root g, g^k is a primitive root if gcd (k, p-1) = 1. But it would be a rare situation where you care for more than one primitive root.
If the input number is semi-prime and you have its (two) prime factors at hand, then you can use this:
vector<uint64> Roots(uint64 p,uint64 q)
{
vector<uint64> roots;
uint64 zstar = p*q;
for (uint64 y=1; y<zstar; y++)
{
if (GCD(zstar,y) == 1 && InQR(y,p,q))
{
uint64 yp = PowMod(y,(p+1)/4,p);
uint64 yq = PowMod(y,(q+1)/4,q);
uint64 r1 = Map(0+yp,0+yq,p,q);
uint64 r2 = Map(0+yp,q-yq,p,q);
uint64 r3 = Map(p-yp,0+yq,p,q);
uint64 r4 = Map(p-yp,q-yq,p,q);
roots.push_back(r1);
roots.push_back(r2);
roots.push_back(r3);
roots.push_back(r4);
}
}
return roots;
}
Here are the auxiliary functions:
uint64 GCD(uint64 a,uint64 b)
{
uint64 c = a%b;
if (c == 0)
return b;
return GCD(b,c);
}
uint64 PowMod(uint64 x,uint64 e,uint64 n)
{
uint64 y = 1;
while (e > 0)
{
if (e & 1)
y = (y*x)%n;
x = (x*x)%n;
e >>= 1;
}
return y;
}
bool InQR(uint64 y,uint64 p)
{
return PowMod(y,(p-1)/2,p) == 1;
}
bool InQR(uint64 y,uint64 p,uint64 q)
{
return InQR(y,p) && InQR(y,q);
}
uint64 Map(uint64 u,uint64 v,uint64 p,uint64 q)
{
uint64 a = q*Inverse(p,q);
uint64 b = p*Inverse(q,p);
return (u*a+v*b)%(p*q);
}
uint64 Inverse(uint64 n,uint64 a)
{
int64 x1 = 1;
int64 x2 = 0;
int64 y1 = 0;
int64 y2 = 1;
uint64 r1 = n;
uint64 r2 = a;
while (r2 != 0)
{
uint64 r3 = r1%r2;
uint64 q3 = r1/r2;
int64 x3 = x1-q3*x2;
int64 y3 = y1-q3*y2;
x1 = x2;
x2 = x3;
y1 = y2;
y2 = y3;
r1 = r2;
r2 = r3;
}
return (uint64)(y1>0? y1:y1+n);
}
Does anyone have a concise answer for this below? I saw this on career cup. http://www.careercup.com/question?id=4860021380743168
Given a binary representation of an integer say 15 as 1111, find the maximum longest continuous sequence of 0s. The twist is it needs to be done in log N.
For example. 10000101
the answer should be 4, because there are 4 continuous zeroes.
If you have an answer in c++ that would be best for me
Pretty trivial, just go through the binary notation, one linear pass. The binary notation has length log(N), so it will take log(N) time.
Seems like this has been asked before.
However, when I feel the need for bit-twiddling, I reach for my copy of the incomparable Hackers Delight. As it turns out, it contains discussions on finding the longest string of 1 bits, including a "logarithmic" implementation that could be used here on the bit/flipped (not) input:
int fmaxstr0(unsigned x, int *apos) {
// invert bits.
x = ~x;
unsigned x2, x4, x8, x16, y, t;
int s;
if (x == 0) {*apos = 32; return 0;}
x2 = x & (x << 1);
if (x2 == 0) {s = 1; y = x; goto L1;}
x4 = x2 & (x2 << 2);
if (x4 == 0) {s = 2; y = x2; goto L2;}
x8 = x4 & (x4 << 4);
if (x8 == 0) {s = 4; y = x4; goto L4;}
x16 = x8 & (x8 << 8);
if (x16 == 0) {s = 8; y = x8; goto L8;}
if (x == 0xFFFFFFFF) {*apos = 0; return 32;}
s = 16; y = x16;
L16: t = y & (x8 << s);
if (t != 0) {s = s + 8; y = t;}
L8: t = y & (x4 << s);
if (t != 0) {s = s + 4; y = t;}
L4: t = y & (x2 << s);
if (t != 0) {s = s + 2; y = t;}
L2: t = y & (x << s);
if (t != 0) {s = s + 1; y = t;}
L1: *apos = nlz(y);
return s;
}
Have fun!