x = 0;
for (i = 1; i <= n/2; i++) {
for (j = 1; j <=n; j++) {
if (j > i)
x++;
}
}
I'm trying to predict the value of x by capturing a summation but I'm kind of stuck because I know that for each iteration of the first for loop, the summation changes for the inner loop. For example if we assume x is 10, after the first completion of the inner loop, x would have 9, then after the 2nd completion, we add 8 to x, then 7, 6, etc. The final value of x would be 35. How would I represent this in a cohesive equation for any positive even integer n?
Skip to the end for a simple equation; here I show the steps you might take.
First, here's the original code:
x = 0;
for (i = 1; i <= n/2; i++) {
for (j = 1; j <=n; j++) {
if (j > i)
x++;
}
}
We can start j at i+1 to skip a lot of pointless loops
x = 0;
for (i = 1; i <= n/2; i++) {
for (j = i+1; j <=n; j++) {
if (j > i)
x++;
}
}
Then instead of adding 1 on each of n-i loops, we can just add n-i.
x = 0;
for (i = 1; i <= n/2; i++) {
x += (n-i)
}
That's the same as this (just writing out what we're adding in the loops):
x = (n-1) + (n-2) + ... + (n - n/2)
We can pull out the n's.
x = n * (n/2) - 1 - 2 - 3 - ... - n/2
The final simplification is for the summation of 1 through n/2.
x = n * (n/2) - ((n/2) * (n/2 + 1))/2
I am trying to write an algorithm which will find a(0),..., a(n-1), given the values of n, x_1, ..., x_n, a(n), such that:
a(n)*p^n + a(n-1)*p^(n-1) + ... + a(1)*p + a(0) = a(n)(p-x_1)(p-x_2)...(p-x_n)
for all real p.
After multiplying a(n)(p-x_1)(p-x_2) I've thought of using Viete's formulas to find the coefficients.
But it turns out writing the code down isn't as obvious as I expected.
I want to use only the basics in my code - that is loops, if-s addition and multiplication - no ready/ complex functions.
Here are the formulas:
First, I would like to emphasise that I only need a pseudocode, and I do not care about defining arrays for the root and coefficients. That's why I will just write a(n), xn. Oh, and I hope it won't bother you very much if I start indexing from i=1 not i=0 in order to be in synch with the mathematical notation. In order to start with i=0 I would have to renumerate the roots and introduce more brackets.
And this is what I've come up with so far:
a(n-1)=0;
for(i=1; i <= n; i++){
a(n-1) = a(n-1) + x_i;
}
a(n-1) = -a(n)*a(n-1);
a(n-2)=0;
for(i=1; i <= n; i++){
for(j=i; j <= n; j++){
a(n-2) = a(n-2)+ x_i * x_j;
}
}
a(n-2) = -a(n)*a(n-2);
a(n-3)=0;
for(i=1; i <= n; i++){
for(j=i; j <= n; j++){
for(k=j; k <= n; k++){
a(n-3) = a(n-3)+ x_i * x_j * x_k;
}
}
}
a(n-3) = a(n)*a(n-3);
...
a(0)=1;
for(i=1; i<=n; i++){
a(0) = a(0) * x_i;
}
if(n%2 == 0) a(0) = a(n) * a(0);
else a(0) = -a(n) * a(0);
As you can see, it doesn't look good.
I would like to link all those loops into one loop, because without I cannot write the full code, I cannot fill the gap between a(0) and a(n-j) for a fixed j.
Could you help me out?
This is what I have, based on Nico Schertler's answer:
for(i=1; i<=n; i++)
{a(i)=1;
for(j=1; j <= n; j++)
{b(i)= clone( a(i) );
a(i) = a(i-1);
b(i) = x_j * b(i);
c(i) = a(i) - b(i);
}
}
Would it be the same if instead we wrote
for(i=1; i<=n; i++)
{a(i)=1; b(i)=1;
for(j=1; j <= n; j++)
{t = a(i) ;
a(i) = a(i-1);
b(i) = x_j * t;
c(i) = a(i) - b(i);
}
}
(this is how we for example swap two elements of an array, by keeping the value of a[i] in some variable t).
You can create the polynomial incrementally.
Start with p = 1. I.e. a(0) = 1.
In order to add a root, you have to multiply the current polynomial by x - x_i. This is:
p * (x - x_i) = p * x - p * x_i
So you need to support three operations:
1. Multiplication by x
This is quite simple. Just shift all coefficients by one to the left. I.e.
a(i ) := a(i - 1)
a(i - 1) := a(i - 2)
...
a(1 ) := a(0)
a(0 ) := 0
2. Multiplication by a scalar
This is equally simple. Multiply each coefficient:
a(i ) *= s
a(i - 1) *= s
...
3. Subtraction
Just subtract the respective coefficients:
c(i ) = a(i ) - b(i )
c(i - 1) = a(i - 1) - b(i - 1)
...
Altogether
Add root by root. First, clone your current polynomial. Then, do the operations as described above:
p := 1
for each root r
p' = clone(p)
multiply p with x
multiply p' with r
p := p - p'
next
A static function in c# for this purpose.
The roots of x^4-11x^3+44x^2-76x+48 are {2,2,3,4} and given the argument
roots = new Complex[4] {2, 2, 3, 4}
this function returns [48,-76,44,-11,1]
public static double[] FromRoots(Complex[] roots)
{
int N = roots.Length;
Complex[] coefs = new Complex[N + 1];
coefs[0] = -roots[0];
coefs[1] = 1.0;
for (int k = 2; k <= N; k++)
{
coefs[k] = 1.0;
for (int i = k - 2; i >= 0; i--)
{
coefs[i + 1] = coefs[i] - roots[k - 1] * coefs[i + 1];
}
coefs[0] *= -roots[k - 1];
if (Math.IEEERemainder(k, 2) == 1)
coefs[k] = -coefs[k];
}
double[] realCoefs = new double[N + 1];
for (int i = 0; i < N + 1; i++)
realCoefs[i] = coefs[i].Real; // Not sure about this part!
return realCoefs;
}
I have the following algorithm to find all triples
for (int i = 0; i < N; i++)
for (int j = i+1; j < N; j++)
for (int k = j+1; k < N; k++)
if (a[i] + a[j] + a[k] == 0)
{ cnt++; }
I now that I have triple loop and I check all triples. How to show that the number of different triples that can be chosen from N items is precisely N*(N-1)*(N-2)/6 ?
If we have two loops
for (int i = 0; i < N; i++)
for (int j = i+1; j < N; j++)
...
when i = 0 we go to the second loop N-1 times
i = 1 => N-2 times
...
i = N-1 => 1 time
i = N => 0 time
So 0 + 1 + 2 + 3 + ... + N-2 + N-1 = ((0 + N-1)/2)*N = N*N - N/2
But how to do the same proof with triples?
Ok, I'll do this step by step. It's more of a maths problem than anything.
Use a sample array for visualisation:
[1, 5, 7, 11, 6, 3, 2, 8, 5]
The first time the 3rd nested loop begins at 7, correct?
And the 2nd at 5, and the 1st loop at 1.
The 3rd nested loop is the important one.
It will loop through n-2 times. Then the 2nd loop increments.
At this point the 3rd loop loops through n-3 times.
We keep adding these till we get.
[(n-2) + (n-3) + ... + 2 + 1 + 0]
Then the 1st loop increments, so we begin at n-3 this time.
So we get:
[(n-3) + ... + 2 + 1 + 0]
Adding them all together we get:
[(n-2) + (n-3) + ... + 2 + 1 + 0] +
[(n-3) + ... + 2 + 1 + 0] +
[(n-4) + ... + 2 + 1 + 0] +
.
. <- (n-2 times)
.
[2 + 1 + 0] +
[1 + 0] +
[0]
We can rewrite this as:
(n-2)(1) + (n-3)(2) + (n-4)(3) + ... + (3)(n-4) + (2)(n-3) + (1)(n-2)
Which in maths notation we can write like this:
Make sure you look up the additive properties of Summations. (Back to college maths!)
We have
=
... Remember how to convert sums to polynomials
=
=
Which has a complexity of O(n^3).
One way is to realize that the number of such triples is equal to C(n, 3):
n!
C(n, 3) = --------
3!(n-3)!
= (n-2)(n-1)n/6
Another is to count what your loops do:
for (int i = 0; i < N; i++)
for (int j = i+1; j < N; j++)
for (int k = j+1; k < N; k++)
You've already showed that two loops from 0 to n-1 execute n(n-1)/2 operations.
For i = 0, the inner loops execute (n-1)(n-2)/2 operations.
For i = 1, the inner loops execute (n-2)(n-3)/2 operations.
...
For i = N - 1, the inner loops execute 0 operations.
We have:
(n-1)(n-2)/2 + (n-2)(n-3)/2 + ... =
= sum(i = 1 to n) {(n - i)(n - i - 1)/2}
= 1/2 sum(i = 1 to n) {n^2 - ni - n - ni + i^2 + i}
= 1/2 sum(i = 1 to n) {n^2} - sum{ni} - 1/2 sum{n} + 1/2 sum{i^2} + 1/2 sum{i}
= 1/2 n^3 - n^2(n+1)/2 - 1/2 n^2 + n(n+1)(2n+1)/12 + n(n+1)/4
Which reduces to the right formula, but it gets too ugly to continue here. You can check that it does on Wolfram.
I am trying to understand this bit reversal algorithm. I found a lot of sources but it doesn't really explain how the pseudo-code works. For example, I found the pseudo-code below from http://www.briangough.com/fftalgorithms.pdf
for i = 0 ... n − 2 do
k = n/2
if i < j then
swap g(i) and g(j)
end if
while k ≤ j do
j ⇐ j − k
k ⇐ k/2
end while
j ⇐ j + k
end for
From looking at this pseudo-code, I don't understand why you would do
swap g(i) and g(j)
when the if statement is true.
Also: what does the while loop do? It would be great if someone can explain this pseudo-code to me.
below is the c++ code that I found online.
void four1(double data[], int nn, int isign)
{
int n, mmax, m, j, istep, i;
double wtemp, wr, wpr, wpi, wi, theta;
double tempr, tempi;
n = nn << 1;
j = 1;
for (i = 1; i < n; i += 2) {
if (j > i) {
tempr = data[j]; data[j] = data[i]; data[i] = tempr;
tempr = data[j+1]; data[j+1] = data[i+1]; data[i+1] = tempr;
}
m = n >> 1;
while (m >= 2 && j > m) {
j -= m;
m >>= 1;
}
j += m;
}
Here is the full version of the source code that I found that does FFT
/************************************************
* FFT code from the book Numerical Recipes in C *
* Visit www.nr.com for the licence. *
************************************************/
// The following line must be defined before including math.h to correctly define M_PI
#define _USE_MATH_DEFINES
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define PI M_PI /* pi to machine precision, defined in math.h */
#define TWOPI (2.0*PI)
/*
FFT/IFFT routine. (see pages 507-508 of Numerical Recipes in C)
Inputs:
data[] : array of complex* data points of size 2*NFFT+1.
data[0] is unused,
* the n'th complex number x(n), for 0 <= n <= length(x)-1, is stored as:
data[2*n+1] = real(x(n))
data[2*n+2] = imag(x(n))
if length(Nx) < NFFT, the remainder of the array must be padded with zeros
nn : FFT order NFFT. This MUST be a power of 2 and >= length(x).
isign: if set to 1,
computes the forward FFT
if set to -1,
computes Inverse FFT - in this case the output values have
to be manually normalized by multiplying with 1/NFFT.
Outputs:
data[] : The FFT or IFFT results are stored in data, overwriting the input.
*/
void four1(double data[], int nn, int isign)
{
int n, mmax, m, j, istep, i;
double wtemp, wr, wpr, wpi, wi, theta;
double tempr, tempi;
n = nn << 1;
j = 1;
for (i = 1; i < n; i += 2) {
if (j > i) {
//swap the real part
tempr = data[j]; data[j] = data[i]; data[i] = tempr;
//swap the complex part
tempr = data[j+1]; data[j+1] = data[i+1]; data[i+1] = tempr;
}
m = n >> 1;
while (m >= 2 && j > m) {
j -= m;
m >>= 1;
}
j += m;
}
mmax = 2;
while (n > mmax) {
istep = 2*mmax;
theta = TWOPI/(isign*mmax);
wtemp = sin(0.5*theta);
wpr = -2.0*wtemp*wtemp;
wpi = sin(theta);
wr = 1.0;
wi = 0.0;
for (m = 1; m < mmax; m += 2) {
for (i = m; i <= n; i += istep) {
j =i + mmax;
tempr = wr*data[j] - wi*data[j+1];
tempi = wr*data[j+1] + wi*data[j];
data[j] = data[i] - tempr;
data[j+1] = data[i+1] - tempi;
data[i] += tempr;
data[i+1] += tempi;
}
wr = (wtemp = wr)*wpr - wi*wpi + wr;
wi = wi*wpr + wtemp*wpi + wi;
}
mmax = istep;
}
}
/********************************************************
* The following is a test routine that generates a ramp *
* with 10 elements, finds their FFT, and then finds the *
* original sequence using inverse FFT *
********************************************************/
int main(int argc, char * argv[])
{
int i;
int Nx;
int NFFT;
double *x;
double *X;
/* generate a ramp with 10 numbers */
Nx = 10;
printf("Nx = %d\n", Nx);
x = (double *) malloc(Nx * sizeof(double));
for(i=0; i<Nx; i++)
{
x[i] = i;
}
/* calculate NFFT as the next higher power of 2 >= Nx */
NFFT = (int)pow(2.0, ceil(log((double)Nx)/log(2.0)));
printf("NFFT = %d\n", NFFT);
/* allocate memory for NFFT complex numbers (note the +1) */
X = (double *) malloc((2*NFFT+1) * sizeof(double));
/* Storing x(n) in a complex array to make it work with four1.
This is needed even though x(n) is purely real in this case. */
for(i=0; i<Nx; i++)
{
X[2*i+1] = x[i];
X[2*i+2] = 0.0;
}
/* pad the remainder of the array with zeros (0 + 0 j) */
for(i=Nx; i<NFFT; i++)
{
X[2*i+1] = 0.0;
X[2*i+2] = 0.0;
}
printf("\nInput complex sequence (padded to next highest power of 2):\n");
for(i=0; i<NFFT; i++)
{
printf("x[%d] = (%.2f + j %.2f)\n", i, X[2*i+1], X[2*i+2]);
}
/* calculate FFT */
four1(X, NFFT, 1);
printf("\nFFT:\n");
for(i=0; i<NFFT; i++)
{
printf("X[%d] = (%.2f + j %.2f)\n", i, X[2*i+1], X[2*i+2]);
}
/* calculate IFFT */
four1(X, NFFT, -1);
/* normalize the IFFT */
for(i=0; i<NFFT; i++)
{
X[2*i+1] /= NFFT;
X[2*i+2] /= NFFT;
}
printf("\nComplex sequence reconstructed by IFFT:\n");
for(i=0; i<NFFT; i++)
{
printf("x[%d] = (%.2f + j %.2f)\n", i, X[2*i+1], X[2*i+2]);
}
getchar();
}
/*
Nx = 10
NFFT = 16
Input complex sequence (padded to next highest power of 2):
x[0] = (0.00 + j 0.00)
x[1] = (1.00 + j 0.00)
x[2] = (2.00 + j 0.00)
x[3] = (3.00 + j 0.00)
x[4] = (4.00 + j 0.00)
x[5] = (5.00 + j 0.00)
x[6] = (6.00 + j 0.00)
x[7] = (7.00 + j 0.00)
x[8] = (8.00 + j 0.00)
x[9] = (9.00 + j 0.00)
x[10] = (0.00 + j 0.00)
x[11] = (0.00 + j 0.00)
x[12] = (0.00 + j 0.00)
x[13] = (0.00 + j 0.00)
x[14] = (0.00 + j 0.00)
x[15] = (0.00 + j 0.00)
FFT:
X[0] = (45.00 + j 0.00)
X[1] = (-25.45 + j 16.67)
X[2] = (10.36 + j -3.29)
X[3] = (-9.06 + j -2.33)
X[4] = (4.00 + j 5.00)
X[5] = (-1.28 + j -5.64)
X[6] = (-2.36 + j 4.71)
X[7] = (3.80 + j -2.65)
X[8] = (-5.00 + j 0.00)
X[9] = (3.80 + j 2.65)
X[10] = (-2.36 + j -4.71)
X[11] = (-1.28 + j 5.64)
X[12] = (4.00 + j -5.00)
X[13] = (-9.06 + j 2.33)
X[14] = (10.36 + j 3.29)
X[15] = (-25.45 + j -16.67)
Complex sequence reconstructed by IFFT:
x[0] = (0.00 + j -0.00)
x[1] = (1.00 + j -0.00)
x[2] = (2.00 + j 0.00)
x[3] = (3.00 + j -0.00)
x[4] = (4.00 + j -0.00)
x[5] = (5.00 + j 0.00)
x[6] = (6.00 + j -0.00)
x[7] = (7.00 + j -0.00)
x[8] = (8.00 + j 0.00)
x[9] = (9.00 + j 0.00)
x[10] = (0.00 + j -0.00)
x[11] = (0.00 + j -0.00)
x[12] = (0.00 + j 0.00)
x[13] = (-0.00 + j -0.00)
x[14] = (0.00 + j 0.00)
x[15] = (0.00 + j 0.00)
*/
A bit-reversal algorithm creates a permutation of a data set by reversing the binary address of each item; so e.g. in a 16-item set the addresses:
0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
will be changed into:
1000 0100 1100 0010 1010 0110 1110 0001 1001 0101 1101 0011 1011 0111 1111
and the corresponding items are then moved to their new address.
Or in decimal notation:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
becomes
0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15
What the while loop in the pseudo-code does, is set variable j to this sequence. (Btw, the initial value of j should be 0).
You'll see that the sequence is made up like this:
0
0 1
0 2 1 3
0 4 2 6 1 5 3 7
0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15
with each sequence being made by multiplying the previous version by 2, and then repeating it with 1 added. Or looking at it another way: by repeating the previous sequence, interlaced with the values + n/2 (this more closely describes what happens in the algorithm).
0
0 1
0 2 1 3
0 4 2 6 1 5 3 7
0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15
Items i and j are then swapped in each iteration of the for loop, but only if i < j; otherwise every item would be swapped to its new place (e.g. when i = 3 and j = 12), and then back again (when i = 12 and j = 3).
function bitReversal(data) {
var n = data.length;
var j = 0;
for (i = 0; i < n - 1; i++) {
var k = n / 2;
if (i < j) {
var temp = data[i]; data[i] = data[j]; data[j] = temp;
}
while (k <= j) {
j -= k;
k /= 2;
}
j += k;
}
return(data);
}
console.log(bitReversal([0,1]));
console.log(bitReversal([0,1,2,3]));
console.log(bitReversal([0,1,2,3,4,5,6,7]));
console.log(bitReversal([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]));
console.log(bitReversal(["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p"]));
The C++ code you found appears to use the symmetry of the sequence to loop through it in double steps. It doesn't produce the correct result though, so either it's a failed attempt, or maybe it's designed to do something different entirely. Here's a version that uses the two-step idea:
function bitReversal2(data) {
var n = data.length;
var j = 0;
for (i = 0; i < n; i += 2) {
if (i < j) {
var temp = data[i]; data[i] = data[j]; data[j] = temp;
}
else {
var temp = data[n-1 - i]; data[n-1 - i] = data[n-1 - j]; data[n-1 - j] = temp;
}
var k = n / 4;
while (k <= j) {
j -= k;
k /= 2;
}
j += k;
}
return(data);
}
console.log(bitReversal2([0,1]));
console.log(bitReversal2([0,1,2,3]));
console.log(bitReversal2([0,1,2,3,4,5,6,7]));
console.log(bitReversal2([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]));
console.log(bitReversal2(["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p"]));
First off, thanks for everyone's help in answering my question. I was talking to the person who is helping me, and I think I understand my C++ code now. Maybe my question is kind unclear, but what I am trying to do is implementing FFT using C++. The C++ code I gave in the question is just the first half of the FFT source code that I found online. Essentially, this part of the C++ code is sorting the inputs into real and imaginary numbers, store the real numbers into the odd index, and imaginary numbers into the even index. (real_0, imag_0, real_1, imag_1, real_2, imag_2,.....) with index starts at 1 because we don't need to swap the zeroth index.
The swap operation below is swapping the real and imaginary numbers.
tempr = data[j]; data[j] = data[i]; data[i] = tempr;
tempr = data[j+1]; data[j+1] = data[i+1]; data[i+1] = tempr;
For example, we have an array length of 8 (nn=8), then 2*nn=16, and we separate our inputs into real and imag numbers and store it into an array of 16. So The first time going through the for loop of the C++ code, my j=1, i=1, it will skip the if and while statements, now in the second for loop, j=9, i=3, so the if statement will be true and data[9], data[3] will be swapped, data[9+1] and data[3+1] will be swapped. This is doing the bit reversal because index 3 and 4 has the real and imag number of the first input, and index 9 and 10 has the real and imag number of the fourth number.
As a result, 001 = 1 (fist input)
100 = 4 (fourth input)
is swapped, so, this is doing the bit reversal using the indexes.
I don't really understand the while loop yet, but I know from #m69, that it is just a way of setting a sequence, so that it can do bit reversal. Well helpful my explanation on my own question is kind clear to people who has the same questions. Once again, thanks everyone.