Iteration causes crash - c++

What is wrong with this iteration?
This particular piece of code is causing my program to crash. When I disable the code it works but of course giving wrong results. It's supposed to compare sigma with sigma_last until they remain equal at e-14.
This is what I tried first:
long double sigma_last = NULL;
do{
if(sigma_last != NULL){
sigma = sigma_last;
}
sigma1 = atan( tan(beta1) / cos(A1) );
sigmaM = (2*sigma1 + sigma) / 2;
d_sigma = B*sin(sigma)*(cos(2*sigmaM)+(1/4)*B*(cos(sigma)
*(-1+2*pow(cos(2*sigmaM),2)))-(1/6)*B*cos(2*sigmaM)
*(-3+4*pow(sin(sigma),2))*(-3+4*pow(cos(2*sigmaM),2)));
sigma_last = sigma + d_sigma;
}
while(set_precision_14(sigma)<= set_precision_14(sigma_last) || set_precision_14(sigma)>= set_precision_14(sigma_last));
Then I tried using a pointer (desperately):
long double *sigma_last;
*sigma_last = NULL;
do{
if(*sigma_last != NULL){
sigma = *sigma_last;
}
sigma1 = atan( tan(beta1) / cos(A1) );
sigmaM = (2*sigma1 + sigma) / 2;
d_sigma = B*sin(sigma)*(cos(2*sigmaM)+(1/4)*B*(cos(sigma)
*(-1+2*pow(cos(2*sigmaM),2)))-(1/6)*B*cos(2*sigmaM)
*(-3+4*pow(sin(sigma),2))*(-3+4*pow(cos(2*sigmaM),2)));
*sigma_last = sigma + d_sigma;
}
while(set_precision_14(sigma)<= set_precision_14(*sigma_last) || set_precision_14(sigma)>= set_precision_14(*sigma_last));
Finding the source of error in entire code and trying to solve it took me hours, cannot really come up with another "maybe this?" . Feel free to smite me.
Here's a github link to my full code if anyone out there's interested.

Your first (and only) iteration, sigma_last will be null, resulting in crash:
*sigma_last = NULL; // <-- dereferencing uninitialized ptr here
if(*sigma_last != NULL) { // <-- dereferencing uninitialized ptr here too
and if that would have been fixed, here:
*sigma_last == sigma + d_sigma;
This is because you have not set sigma_last to point to some valid floating-point space in memory. There doesn't seem to be any point to using a pointer in this particular case, so if I were you, I'd drop it and use a normal long double instead, as in your first attempt.
In your first example you assign NULL, which is really the value zero, to sigma_last. If zero is not what you're intending, you could either go with a value that most certainly will be out of range (say 1e20 and then compare to say < 1e19) or keep a separate boolan for the job. I personally prefer the first option:
long double sigma_last = 1e20;
...
if(sigma_last < 1e19){
sigma = sigma_last;
}
A better way still would be to use an infinite, or finite, loop and then break out at a certain condition. This will make the code easier to read.
Logic
Finally, you seem to have a problem with your logic in the while, since the comparison sigma <= sigma_last || sigma >= sigma_last is always true. It's always smaller, bigger, or equal.

sigma_last does not need to be a pointer. You just need to somehow flag its value to know whether it was already set or not. From your code I am not sure if we can use zero for this purpose, but we can use some constant (long double minimum value), like this one:
#include <float.h>
const long double invalid_constant = LDBL_MIN;
Try this:
long double DESTINATION_CALCULATION_plusplus ( double phi, double lambda, double S, double azimuth,
double a, double b, double *phi2, double* lambda2, double* azimuth2){
phi = phi*M_PI/180;
lambda = lambda*M_PI/180;
double A1;
double eu2 = (pow(a, 2) - pow(b, 2)) / pow(b, 2); //second eccentricity
double c = pow(a,2) / b;
double v = sqrt(1 + (eu2 * pow(cos(phi) , 2)));
double beta1 = tan(phi) / v;
double Aeq = asin( cos(beta1) * sin(azimuth) );
double f = (a - b) / a; //flattening
double beta = atan((1-f)*tan(phi));
double u2 = pow(cos(Aeq),2)*eu2;
//////////////////////////////----------------------------------------------
long double sigma1 = atan( tan(beta1)/ cos(azimuth) );
long double A = 1 + u2*(4096 + u2*(-768+u2*(320-175*u2))) / 16384;
long double B = u2*(256 + u2*(-128+u2*(74-47*u2)))/1024;
long double sigma = S / (b*A);
long double sigmaM = (2*sigma1 + sigma) /2;
long double d_w;
long double d_sigma;
////////////////////////////------------------------------------------------
double C;
double d_lambda;
long double sigma_last=invalid_constant;
do{
if(sigma_last != invalid_constant){
sigma = sigma_last;
}
sigma1 = atan( tan(beta1) / cos(A1) );
sigmaM = (2*sigma1 + sigma) / 2;
d_sigma = B*sin(sigma)*(cos(2*sigmaM)+(1/4)*B*(cos(sigma)
*(-1+2*pow(cos(2*sigmaM),2)))-(1/6)*B*cos(2*sigmaM)
*(-3+4*pow(sin(sigma),2))*(-3+4*pow(cos(2*sigmaM),2)));
sigma_last = sigma + d_sigma;
}
while(set_precision_14(sigma)<= set_precision_14(sigma_last) || set_precision_14(sigma)>= set_precision_14(sigma_last));
sigma = sigma_last;
*phi2 = atan((sin(beta1)*cos(sigma)+cos(beta1)*sin(sigma)*cos(azimuth))/((1-f)
*sqrt(pow(sin(Aeq),2)+pow((sin(beta1)*sin(sigma)-cos(beta1)*cos(sigma)*cos(azimuth)),2))));
d_w = (sin(sigma)*sin(azimuth))/(cos(beta1)*cos(sigma) - sin(beta1)* sin(sigma)*cos(azimuth));
C = (f/16)*pow(cos(Aeq),2)*(4+f*(4-3*pow(cos(Aeq),2)));
d_lambda = d_w - (1-C)*f*sin(azimuth)*(sigma + C*sin(sigma)*
(cos(2*sigmaM)+C*cos(sigma)*(-1+2*pow(cos(2*sigmaM),2))));
*lambda2 = lambda + d_lambda;
*azimuth2 = sin(Aeq) / (-sin(beta1)*sin(sigma)+cos(beta1)*cos(sigma)*cos(azimuth));
*azimuth2 = *azimuth2 * 180/M_PI;
*lambda2 = *lambda2 * 180/M_PI;
*phi2 = *phi2 * 180/M_PI;
}

Related

Mathematica vs. C++ calculation result

I have two programs that should be identical but are giving different results. One in Mathematica (giving the correct result) and one in C++ (incorrect).
First the Mathematica:
q = 0.002344;
s = 0.0266;
v = 0.0744;
a = -q*PDCx^2;
b = s*PDCx - 2*q*PCLx*PDCx - PDCz;
c = -1*(PCLz + q*PCLx^2 - s*PCLx + v);
d = b*b - (4*a*c);
t = (-b + Sqrt[d])/(2*a)
Now the C++:
long double q = 0.002344;
long double s = 0.0266;
long double v = 0.0744;
long double a = -q * pow(PDCx, 2);
long double b = s * PDCx - 2 * q*PCLx*PDCx - PDCz;
long double c = (-1.0)*(PCLz + q * pow(PCLx, 2) - s * PCLx + v);
long double d = b * b - 4.0 * a*c;
t = (-b + sqrtf(d))/(2.0*a);
with
long double PCLx = -1.816017;
long double PCLz = 0.056013;
long double PDCx = 0.005073;
long double PDCz = -0.998134;
for each case. The Mathematica result is t = 0.1867646081 and C++ result is t = 0.124776. This is the "plus" solution of the quadratic. The minus solutions differ are 16549276.47723365 and 16549276.539223, respectively. I suspect that I am allowing the C++ result to be rounded incorrectly.

Fsolve equivalent in C++

I am trying to replicate Matlab's Fsolve as my project is in C++ solving an implicit RK4 scheme. I am using the NLopt library using the NLOPT_LD_MMA algorithm. I have run the required section in matlab and it is considerably faster. I was wondering whether anyone had any ideas of a better Fsolve equivalent in C++? Another reason is that I would like f1 and f2 to both tend to zero and it seems suboptimal to calculate the L2 norm to include both of them as NLopt seems to only allow a scalar return value from the objective function. Does anyone have any ideas of an alternative library or perhaps using a different algorithm/constraints to more closely replicate the default fsolve.
Would it be better (faster) perhaps to call the python scipy.minimise.fsolve from C++?
double implicitRK4(double time, double V, double dt, double I, double O, double C, double R){
const int number_of_parameters = 2;
double lb[number_of_parameters];
double ub[number_of_parameters];
lb[0] = -999; // k1 lb
lb[1] = -999;// k2 lb
ub[0] = 999; // k1 ub
ub[1] = 999; // k2 ub
double k [number_of_parameters];
k[0] = 0.01;
k[1] = 0.01;
kOptData addData(time,V,dt,I,O,C,R);
nlopt_opt opt; //NLOPT_LN_MMA NLOPT_LN_COBYLA
opt = nlopt_create(NLOPT_LD_MMA, number_of_parameters);
nlopt_set_lower_bounds(opt, lb);
nlopt_set_upper_bounds(opt, ub);
nlopt_result nlopt_remove_inequality_constraints(nlopt_opt opt);
// nlopt_result nlopt_remove_equality_constraints(nlopt_opt opt);
nlopt_set_min_objective(opt,solveKs,&addData);
double minf;
if (nlopt_optimize(opt, k, &minf) < 0) {
printf("nlopt failed!\n");
}
else {
printf("found minimum at f(%g,%g,%g) = %0.10g\n", k[0],k[1],minf);
}
nlopt_destroy(opt);
return V + (1/2)*dt*k[0] + (1/2)*dt*k[1];```
double solveKs(unsigned n, const double *x, double *grad, void *my_func_data){
kOptData *unpackdata = (kOptData*) my_func_data;
double t1,y1,t2,y2;
double f1,f2;
t1 = unpackdata->time + ((1/2)-(1/6)*sqrt(3));
y1 = unpackdata->V + (1/4)*unpackdata->dt*x[0] + ((1/4)-(1/6)*sqrt(3))*unpackdata->dt*x[1];
t2 = unpackdata->time + ((1/2)+(1/6)*sqrt(3));
y2 = unpackdata->V + ((1/4)+(1/6)*sqrt(3))*unpackdata->dt*x[0] + (1/4)*unpackdata->dt*x[1];
f1 = x[0] - stateDeriv_implicit(t1,y1,unpackdata->dt,unpackdata->I,unpackdata->O,unpackdata->C,unpackdata->R);
f2 = x[1] - stateDeriv_implicit(t2,y2,unpackdata->dt,unpackdata->I,unpackdata->O,unpackdata->C,unpackdata->R);
return sqrt(pow(f1,2) + pow(f2,2));
My matlab version below seems to be a lot simpler but I would prefer the whole code in c++!
k1 = 0.01;
k2 = 0.01;
x0 = [k1,k2];
fun = #(x)solveKs(x,t,z,h,I,OCV1,Cap,Rct,static);
options = optimoptions('fsolve','Display','none');
k = fsolve(fun,x0,options);
% Calculate the next state vector from the previous one using RungeKutta
% update equation
znext = z + (1/2)*h*k(1) + (1/2)*h*k(2);``
function [F] = solveKs(x,t,z,h,I,O,C,R,static)
t1 = t + ((1/2)-(1/6)*sqrt(3));
y1 = z + (1/4)*h*x(1) + ((1/4)-(1/6)*sqrt(3))*h *x(2);
t2 = t + ((1/2)+(1/6)*sqrt(3));
y2 = z + ((1/4)+(1/6)*sqrt(3))*h*x(1) + (1/4)*h*x(2);
F(1) = x(1) - stateDeriv_implicit(t1,y1,h,I,O,C,R,static);
F(2) = x(2) - stateDeriv_implicit(t2,y2,h,I,O,C,R,static);
end

Levenberg–Marquardt not converging

I try to make a model fit using Levenberg-marquardt's method according to numerical recipes.
The Problem is: it does not converge or when it does, it's not precise... or at least the covariant matrix is strange.
int i=0;
for (i = 0; i < 3e4; i++) {
mrqmin(x, y, sig, NPCalib, a, ia, 3, covar, alpha, &chisk, afunc,
&alamda);
if (chisk < 1e-8)
sumchisk++;
if (sumchisk > 5)
break;
if (alamda > 1e8)
alamda = 1e8;
}
(x,y) are 3 points (double) that work pretty well with the form y=a(x-x0)^2.
using sumchisk like this is the recommendation of numerical recipees for using this function.
alamda is capped at the top here as otherwise there might have been an overflow.
Other definitions and data-points:
double a[4] = {0.0, 0.0001, 100.0, -1};
int ia[4] = {0.0, 1, 1, 0};
double *x = {0.0, 799.157549545577, 799.92196995454, 800.683769692575};
double *y = {0.0, 524.26491, 525.26768, 526.26586};
double *sig = {0.0, 0.1*y[1], 0.1*y[2], 0.1*y[3]};
double **covar = new double*[4];
covar[1] = new double[4];
covar[2] = new double[4];
covar[3] = new double[4];
double **alpha = new double*[4];
alpha[1] = new double[4];
alpha[2] = new double[4];
alpha[3] = new double[4];
double chisk = 0;
double alamda = -1;
void afunc(int i, double x[], double a[], double *y, double dyda[], int ma)
{
*y = a[1] * pow(x[i] + a[2], 2) / pow(1 + a[3] * CT[i - 1], 2);
dyda[1] = pow(x[i] + a[2], 2) / pow(1 + a[3] * CT[i - 1], 2);
dyda[2] = (2 * a[1] * (x[i] + a[2])) / pow
(1 + a[3] * CalibTurn[i - 1], 2);
dyda[3] = (-2 * a[1] * CT[i - 1] * pow(x[i] + a[2], 2)) / pow
(1 + a[3] * CT[i - 1], 3);
}
I changed the nr-sourcecode to use double instead of float. The first array-element is not used because this comes from fortran-code and I didn't feel like changing such a small detail.
The model also contains a 3. parameter, which isn't used in this fit and thus remains a[3]=-1, because ia[3]=0. ia[]=1 means the parameter is about to get fitted...
However, Now I have the problem that sometimes this doesn't converge. It finishes with alamda=1e8 and i=3e4. Especially when I set the treshold for chisk lower.
The sets of parameters seem to be fine, though... the chisk is e.g. about 1e-6 and the parameters seem fine, but looking at the diagonals of the covariant-matrix (which should give the squared standard deviation of each parameter), there is some rubish like ~800000 for a parameter 0.0001.
Does anyone know what I did wrong when using this algorithm?
Anything specific I need to write into covar/alpha when I start? Can the sig be set like this?

"double" does not print decimals

i was wondering why in this program, "pi_estimated" wouldn't print out as a number with decimal places although the variable was declared as a "double". However, it prints out an integer.
double get_pi(double required_accuracy)
{
double pi_estimation=0.0;
int x,y;
double p=0.0,q=0.0,r=0.0;
int D=0;
for(int N=1;N<=1e2;N++)
{
x = rand()%100;
p = (x/50.0 - 1.0)/100.0;
y = rand()%100;
q = (y/50.0 - 1.0)/100.0;
r = p*p + q*q;
if((sqrt(r))<1.0)
{
D++;
pi_estimation = 4.0*(double (D/N));
}
if(double (4/(N+1)) < (required_accuracy*pi_estimation/100.0))
{
cout<<pi_estimation<<endl;
return (pi_estimation);
}
}
}
int main()
{
double pi_approx=0.0, a, actual_accuracy=0.0;
for(a=0.1;a>=1e-14;a/=10)
{
pi_approx = get_pi(a);
actual_accuracy = (fabs((pi_approx - M_PI)/(M_PI)))*100.0;
cout<<actual_accuracy<<endl;
}
}
This line is the culprit:
pi_estimation = 4.0*(double (D/N));
Since D and N are both ints, D/N is an int. Casting the int to a double cannot magically make decimals appear out of nowhere.
Here's the line, fixed:
pi_estimation = 4.0 * (((double) D) / N));
You could also multiply first, so you don't need so many parens:
pi_estimation = 4.0 * D / N;
D is being multiplied by 4.0, so it becomes a double because double * int = double. Then it's divided by N. Since (x * y) / z === x * (y / z) (associative property), the expressions are equivalent.
The problem is here:
pi_estimation = 4.0*(double (D/N));
D and N are both integers, so D/N is an integer that you are casting to a double and then multiplying by 4.0.
You want to do this:
pi_estimation = 4.0 * (static_cast<double>(D) / N));
Since D and N are both integral types, D/N is performed in integer arithmetic; the cast to double happens too late as precision is lost prior to the cast.
One fix is to write 4.0 * D / N. This will ensure that everything is calculated in floating point. (Since * and / have the same precedence, you don't need to write (double).)

C++ Question on the pow function

I'm trying to get this expression to work, I'm pretty sure its not the parenthesis because I counted all of them. Perhaps there something I'm doing wrong involving the parameter pow (x,y).
double calculatePeriodicPayment()
{
periodicPaymentcalc = (loan * ((interestRate / yearlyPayment))) / (1-((pow ((1+(interestRate / yearlyPayment)))),(-(yearlyPayment * numOfYearLoan))));
return periodicPaymentcalc;
}
Notice how much easier it is to figure out what the function is doing if you break each step up into pieces:
(I find it even easier if your variables match the source material, so I'll name my variables after the ones Wikipedia uses.)
// amortization calculator
// uses annuity formula (http://en.wikipedia.org/wiki/Amortization_calculator)
// A = (P x i) / (1 - pow(1 + i,-n))
// Where:
// A = periodic payment amount
// P = amount of principal
// i = periodic interest rate
// n = total number of payments
double calculatePeriodicPayment()
{
const double P = loan;
const double i = interestRate / yearlyPayment;
const double n = yearlyPayment * numOfYearLoan;
const double A = (P * i) / (1 - pow(1.0 + i, -n));
return A;
}
It's much easier to confirm that the logic of this function does what it should this way.
If you're curious, substituting my variable names in, your parenthises problem is as follows:
const double A = (P * i) / (1 - pow(1 + i)), -n; // <- this is how you have it
const double A = (P * i) / (1 - pow(1 + i, -n)); // <- this is how it should be
With this grouping, you're only passing one argument to pow, which is why the compiler says no overloaded function takes 1 arguments.
Edit: You mentioned I used more variables. However, your compiler will use temporary variables much like I did. Your complex statement will be broken up into pieces, and may look something like this:
double calculatePeriodicPayment()
{
const double temp1 = interestRate / yearlyPayment;
const double temp2 = loan * temp1;
const double temp3 = interestRate / yearlyPayment;
const double temp4 = 1.0 + temp3;
const double temp5 = yearlyPayment * numOfYearLoan;
const double temp6 = -temp5;
const double temp7 = pow(temp4, temp5);
const double temp8 = 1 - temp7;
const double temp9 = temp2 / temp8;
periodicPaymentcalc = temp9;
return periodicPaymentcalc;
}
Mine will also be broken up, and will look like:
double calculatePeriodicPayment()
{
const double P = loan;
const double i = interestRate / yearlyPayment;
const double n = yearlyPayment * numOfYearLoan;
const double temp1 = P * i;
const double temp2 = 1.0 + i;
const double temp3 = -n;
const double temp4 = pow(temp2, temp3);
const double temp5 = 1 - temp4;
const double temp6 = temp1 / temp5;
const double A = temp6;
return A;
}
Perhaps there are some optimizations that the compiler will use, such as noticing that it uses interestRate / yearlyPayment twice in your function, and use the same temporary for both places, but there's no gurantee this will happen. Notice that we use pretty much the same number of variables in both of our functions. I just used more named variables, and fewer unnamed temporaries.
There's a misplaced bracket. Here's a fixed version:
periodicPaymentcalc = (loan * ((interestRate / yearlyPayment))) / (1 - ((pow ((1+(interestRate / yearlyPayment)),(-(yearlyPayment * numOfYearLoan))))));
Use an editor that highlights matching brackets to avoid this kind of errors. Or simply create temporary variables to hold intermediate values.
periodicPaymentcalc = (loan * interestRate / yearlyPayment) /
(1.0 - pow (1.0 + interestRate / yearlyPayment, -yearlyPayment * numOfYearLoan));
Try that. I removed all the redundant parentheses too, as well as changing all literals to doubles, just for good measure.