pointers, pointer tot pointer, exc - c++

We need to understand the next code for college. Everything goes fine till the this instruction :
(*((*q1)+2))++;
Can someone tell me what's the effect of that instruction? q1 or p1 doesn't change. Here is the whole exercise.
double a = 2;
double b[] = {1,3,5};
double c[] = {4,6,8,10};
double & d = a;
double* p1 = b;
double* p2 = &c[1];
double **q1 = &p2;
double **q2 = &p1;
(*q1)++;
a = **q1-*(p1+1);
q1 = q2;
(*((*q1)+2))++;
p2-=2;
**q1 = *p2;
*q2 = &c[1];
b[2] -= *(p2+3)-**q1;
d = c[1];
cout << a << endl << b[0] << endl << b[1] << endl << b[2] << endl;

Considering that q1 is a double** :
*q1 Dereference q1, obtaining a double*&
( )+2 Add 2, ending up pointing two double's further
*( ) Dereference where we are, obtaining a double&
( )++; Increment that last double.

Work from the inside out.
(*((*q1)+2))++;
(*q1) is p2 so replace.
(*(p2 + 2))++;
p2 + 2 is the address of c[3] so replace
(*(&c[3])++;
*(&c[3]) is 10 so replace
10++ is 11

(*((*q1) + 2))++; is equivalent to (*(p1 + 2))++;

Related

Implementation of IIR Lowpass Filter in C++

I have the filter coefficients for a Butterworth lowpass filter, coming from the Matlab function [b, a] = butter(3, 0.4, 'low') and I am implemented the same computation Matlab is using according to their documentation for filter(b, a, X). The results for filtering a constant signal of 5.0, for example, are the same, but only for the first 10 values!?
I suppose that my circular buffer is wrong, but I cannot find any problems. The values are written correctly in x using the filter method, the arrays are initialized with zeros, the circular buffer pointer n has the right values... Do you have any ideas?
// Interface
class LowpassFilter {
private:
double x[10]; // input vector
double y[10]; // output vector
int n; // pointer to the current array index
public:
LowpassFilter();
double filter(double sample);
};
// Implementation
// filter coefficients a and b
const double a[] = {1.0, -0.577240524806303, 0.421787048689562, -0.056297236491843};
const double b[] = {0.098531160923927, 0.295593482771781, 0.295593482771781, 0.098531160923927};
static int c = 0;
LowpassFilter::LowpassFilter() : x{0.0}, y{0.0}, n(0) { } // Constructor
double LowpassFilter::filter(double sample)
{
x[n] = sample;
y[n] = b[0] * x[n] + b[1] * x[(n-1)%10] + b[2] * x[(n-2)%10] + b[3] * x[(n-3)%10]
- a[1] * y[(n-1)%10] - a[2] * y[(n-2)%10] - a[3] * y[(n-3)%10];
std::cout << c++ << ": " << y[n] << std::endl; // for checking the result with the Matlab results
double result = y[n];
n = (n + 1) % 10; // new pointer index
return result;
}
Thanks to Mike Seymour and emsr the problem were the negative indexes in the computation of y[n]. To solve the problem only one line has to be adopted:
y[n] = b[0] * x[n] + b[1] * x[(n-1+m)%m] + b[2] * x[(n-2+m)%m] + b[3] * x[(n-3+m)%m]
- a[1] * y[(n-1+m)%m] - a[2] * y[(n-2+m)%m] - a[3] * y[(n-3+m)%m];
to make sure that the index is positive. Now it works fine. Thanks alot!

what is wrong with my cross product code

I am a C++ beginner. I would like to get the normal vector of a surface, which is determined by three point a,b and c. I have the following code, but I do not know what is wrong with it. Thanks for the help.
#include <iostream>
using namespace std;
class point
{
public:
double x,y,z;
};
class crproduct:point
{
public:
double x1,x2,x3,y1,y2,y3,z1,z2,z3,Ax,Ay,Az,Bx,By,Bz;
point crproduc(point *a,point *b,point *c)
{
//point a
x1 = (*a).x;
y1 = (*a).y;
z1 = (*a).z;
//point b
x2 = (*b).x;
y2 = (*b).y;
z2 = (*b).z;
//point c
x3 = (*c).x;
y3 = (*c).y;
z3 = (*c).z;
//Vector A
Ax = x1-x2;
Ay = y1-y2;
Az = z1-z2;
//vector B
Bx = x2-x3;
By = y2-y3;
Bz = z2-z3;
//cross product
point vector;
vector.x = (Ay*Bz)-(By*Az);
vector.y = -(Ax*Bz)+(Bx*Az);
vector.z = (Ax*By)-(Ay*Bx);
return vector;
}
};
int main ()
{
point *pp, *p1, *p2;
point cd;
crproduct cr1,cr2,cr3,cr4;
(*pp).x = 12;
(*pp).y = 13;
(*pp).z = 15
(*p1).x = 10;
(*p1).y = 10;
(*p1).z = 10;
(*p2).x = 8;
(*p2).y = 5;
(*p2).z = 2;
cd = cr1.crproduc(pp,p1,p2);
cout << cd.x << " " << cd.y << " " << cd.z << endl;
system("pause");
return 0;
}
This is incorrect:
point *pp,*p1,*p2;
point cd;
crproduct cr1,cr2,cr3,cr4;
(*pp).x=12;
(*pp).y=13;
(*pp).z=15
(*p1).x=10;
(*p1).y=10;
(*p1).z=10;
(*p2).x=8;
(*p2).y=5;
(*p2).z=2;
Apart from the missing semicolon, the point *pp,*p1,*p2 line establishes three typed pointers. It doesn't create any objects or instantiate the pointers. So at that point, using the pointers will have undefined results.
You then go on to access the pointers.
If you want them on the stack, just declare the objects directly as:
point pp, p1, p2;
... and then access appropriately. If you need them on the heap then you should use new to create objects that the pointers can point to, e.g.
pp = new point;
And don't forget to delete later.

What's wrong with my durand-kerner implementation?

Implementing this simple root-finding algorithm.
http://en.wikipedia.org/wiki/Durand%E2%80%93Kerner_method
I cannot for the life of me figure out what's wrong with my implementation. The roots keep blowing up and no sign of convergence. Any suggestions?
Thanks.
#include <iostream>
#include <complex>
using namespace std;
typedef complex<double> dcmplx;
dcmplx f(dcmplx x)
{
// the function we are interested in
double a4 = 3;
double a3 = -3;
double a2 = 1;
double a1 = 0;
double a0 = 100;
return a4 * pow(x,4) + a3 * pow(x,3) + a2 * pow(x,2) + a1 * x + a0;
}
int main()
{
dcmplx p(.9,2);
dcmplx q(.1, .5);
dcmplx r(.7,1);
dcmplx s(.3, .5);
dcmplx p0, q0, r0, s0;
int max_iterations = 20;
bool done = false;
int i=0;
while (i<max_iterations && done == false)
{
p0 = p;
q0 = q;
r0 = r;
s0 = s;
p = p0 - f(p0)/((p0-q0)*(p0-r0)*(p0-s0));
q = q0 - f(q0)/((q0-p)*(q0-r0)*(q0-s0));
r = r0 - f(r0)/((r0-p)*(r0-q)*(r0-s0));
s = s0 - f(s0)/((s0-p)*(s0-q)*(s0-r));
// if convergence within small epsilon, declare done
if (abs(p-p0)<1e-5 && abs(q-q0)<1e-5 && abs(r-r0)<1e-5 && abs(s-s0)<1e-5)
done = true;
i++;
}
cout<<"roots are :\n";
cout << p << "\n";
cout << q << "\n";
cout << r << "\n";
cout << s << "\n";
cout << "number steps taken: "<< i << endl;
return 0;
}
A half year late: The solution to the enigma is that the denominator should be an approximation of the derivative of the polynomial, and thus needs to contain the leading coefficient a4 as factor.
Alternatively, one can divide the polynomial value by a4 in the return statement, so that the polynomial is effectively normed, i.e., has leading coefficient 1.
Note that the example code in wikipedia by Bo Jacoby is the Seidel-type variant of the method, the classical formulation is the Jordan-like method where all new approximations are simultaneously computed from the old approximation. Seidel can have faster convergence than the order 2 that the formulation as a multidimensional Newton method provides for Jacobi.
However, for large degrees Jacobi can be accelerated using fast polynomial multiplication algorithms for the required multi-point evaluations of polynomial values and the products in the denominators.
Ah, the problem was that the coefficients of an N-degree polynomial have to be specified as
1*x^N + a*x^(N-1) + b*x^(N-2) ... etc + z;
where 1 is the coefficient of the largest degree term. Otherwise the first root will never converge.
You haven't implemented for formulae correctly. For instance
s = s0 - f(s0)/((s0-p0)*(s0-q0)*(s0-r0));
should be
s = s0 - f(s0)/((s0-p)*(s0-q)*(s0-r));
Look again at the wiki article

Adding floats, integers and to pointer

I'm very new to programming and I have been trying to do the following, but I don't know if I am doing it right.
I have the following declarations
int a, b, c;
int *p1, *p2, *p3;
char d, str[10], *cp;
float big, r;
and with those declarations I have to find out how to declare the following q variables.
For example, if *p3 is a integer pointer and r is a float. then what would q1 would have to be. I need to find out how to declare it.
But since each one is of a different type, I don't know how to do it. Some hints would be kindly appreciated
q1 = r + *p3;
q2 = &p1 + 5;
q3 = *str + c;
q4 = &str[4];
q5 = *p2;
int a, b, c;
int *p1, *p2, *p3;
char d, str[10], *cp;
float big, r;
So I think the question is to use the declarations above, and the expressions below and come up with a valid set of types for the expressions.
q1 = r + *p3;
q2 = &p1 + 5;
q3 = *str + c;
q4 = &str[4];
q5 = *p2;
I think these types are valid for the expressions above:
float q1 = r + *p3; // float = float + int
int **q2 = &p1 + 5; // int ** = int** + int
int q3 = *str + c; // int = char + int
char *q4 = &str[4]; // char * = char *
int q5 = *p2; // int = *int*
q1, q3 and q5 could be any numeric type. I picked the one most obvious to me.

pointer to a two dimentional array

How can I let a pointer assigned with a two dimensional array?
The following code won't work.
float a1[2][2] = { {0,1},{2,3}};
float a2[3][2] = { {0,1},{2,3},{4,5}};
float a3[4][2] = { {0,1},{2,3},{4,5},{6,7}};
float** b = (float**)a1;
//float** b = (float**)a2;
//float** b = (float**)a3;
cout << b[0][0] << b[0][1] << b[1][0] << b[1][1] << endl;
a1 is not convertible to float**. So what you're doing is illegal, and wouldn't produce the desired result.
Try this:
float (*b)[2] = a1;
cout << b[0][0] << b[0][1] << b[1][0] << b[1][1] << endl;
This will work because two dimensional array of type float[M][2] can convert to float (*)[2]. They're compatible for any value of M.
As a general rule, Type[M][N] can convert to Type (*)[N] for any non-negative integral value of M and N.
If all your arrays will have final dimension 2 (as in your examples), then you can do
float (*b)[2] = a1; // Or a2 or a3
The way you do this is not legit in c++. You need to have an array of pointers.
The problem here is that the dimensions of b are not known to the compiler. The information gets lost when you cast a1 to a float**. The conversion itself is still valid, but you cannot reference the array with b[][].
You can do it explicitly:
float a1[2][2] = { {0,1},{2,3}};
float* fp[2] = { a1[0], a1[1] };
// Or
float (*fp)[2] = a1;
Try assigning b to be directly equals to a1, that's mean that the pointer b is pointing to the same memory location that pointer a1 is pointing at, they carry the same memory reference now, and you should be able to walk through the array.