Problem: "Cannot convert argument 1 from 'double' to 'char(*)(double)'" - c++

I have a problem with the following assignment. The problem is to find the integral of the function. It gives me the error "Cannot convert argument 1 from 'double' to 'char(*)(double)'". I think the problem is in the bottom, where I define the function. And I am not even sure if I should use char for p.
Does anyone know, what the problem is?
/*43. Modify program chapter6_11 to estimate the integral of the function
f (x) = 3x − 2x^2.*/
#include <iostream> //Required for cin, cout
#include <fstream>
#include <cstdlib> //Required for srand(), rand().
#include <cmath> //Required for pow().
using namespace std;
/*-----------------------------------------------------------------*/
/* Program chapter6_11 */
/* */
/* This program finds the real roots of a cubic polynomial */
/* using the Newton-Raphson method. */
double integral(char(p)(double x), double a, double b, double n);
int main(){
// Declare objects.
int iterations(0);
double a1, a2, a3, x, p, dp, tol;
cout << "Enter coefficients a1, a2, a3 (here -2, 3 and 0)\n";
cin >> a1 >> a2 >> a3;
cout << "Enter initial guess for root\n";
cin >> x;
// Evaluate p at initial guess.
p = -2* x * x + 3 * x + 0;
// Determine tolerance.
tol = fabs(p);
while (tol > 0.001 && iterations < 100)
{
// Calculate the derivative.
dp = 2 * -2 * x + 3;
// Calculate next estimated root.
x = x - p / dp;
// Evaluate p at estimated root.
p = -2 * x * x + 3 * x + 0;
tol = fabs(p);
iterations++;
}
if (tol < 0.001)
{
cout << "Root is " << x << endl;
cout << iterations << " iterations\n";
cout << "Integral is" << integral(p, -100000, 100000, 1000);
}
else
cout << "Did not converge after 100 iterations\n";
return 0;
}
double integral(char(p)(double x), double a, double b, double n) {
double step = (b - a) / n; // width of each small rectangle
double area = 0.0; // signed area
for (int i = 0; i < n; i++) {
area += p(a + (i + 0.5) * step) * step; // sum up each small rectangle
}
return area;
}

You are calling integral,
cout << "Integral is" << integral(p, -100000, 100000, 1000);
Where p is not a pointer to a function returning a char and taking a double
char func(double x);
maybe you meant to define such at function?

Related

c++ Eigen: spline derivatives() gives strange derivatives

I'm trying to get a hold on how to work with splines in Eigen, specifically I want do find the value of the spline interpolation and its first and second derivatives in some point. Finding the interpolated value is easy, but when I try to calculate the derivative I get strange values.
I tried following the instructions for the derivatives command in the manual (http://eigen.tuxfamily.org/dox/unsupported/classEigen_1_1Spline.html#af3586ab1929959e0161bfe7da40155c6), and this is my attempt in code:
#include <iostream>
#include <Eigen/Core>
#include <unsupported/Eigen/Splines>
using namespace Eigen;
using namespace std;
double scaling(double x, double min, double max) // for scaling numbers
{
return (x - min)/(max - min);
}
VectorXd scale(VectorXd xvals) // for scaling vectors
{
const double min = xvals.minCoeff();
const double max = xvals.maxCoeff();
for (int k = 0; k < xvals.size(); k++)
xvals(k) = scaling(xvals(k),min,max);
return xvals;
}
int main()
{
typedef Spline<double,1,3> spline;
VectorXd xvals = (VectorXd(4) << 0,1,2,4).finished();
VectorXd yvals = xvals.array().square(); // x^2
spline testspline = SplineFitting<spline>::Interpolate(yvals.transpose(), 3,
scale(xvals).transpose());
cout << "derivative at x = 0: " << testspline.derivatives(0.00,2) << endl;
cout << "derivative at x = 1: " << testspline.derivatives(0.25,2) << endl;
cout << "derivative at x = 2: " << testspline.derivatives(0.50,2) << endl;
cout << "derivative at x = 3: " << testspline.derivatives(0.75,2) << endl;
cout << "derivative at x = 4: " << testspline.derivatives(1.00,2) << endl;
}
it outputs
derivative at x = 0: 0 0 32
derivative at x = 1: 1 8 32
derivative at x = 2: 4 16 32
derivative at x = 3: 9 24 32
derivative at x = 4: 16 32 32
That is, the interpolation is correct (c.f. x = 3), but the derivatives are not, and they are off in a systematic way, so I'm thinking I'm doing something wrong. Since these follow x^2, the derivatives should be 0,2,4,6,8 and the second order derivative should be 2.
Any ideas on how to solve this?
Edit 1
Changing x^2 to x^2 + 1 yields the same derivatives, so that checks out at least. But changing x^2 to x^3 is wrong, but wrong in a slightly different way, output would then be:
derivative at x = 2: 8 48 192
derivative at x = 3: 27 108 288
derivative at x = 4: 64 192 384
Which is wrong, it should be 6, 9, 12.
Also running the x^2 case, but changing he input vector to 0,1,...9 yields the same derivative as using the original input vector, but the second order derivative becomes a steady 200, which too is wrong. I fail to see why the second order derivative should depend on the number of input points.
Solved it. You were very close. All you had to do was scale the derivatives
with
1 / (x_max - x_min) (first derivative)
1 / (x_max - x_min)^2 (second derivative).
TLDR: You normalized the x values to be between 0 and 1 while fitting the spline, but you didn't scale the y values.
Instead of the spline fitting x^2, you actually fitted:
x_norm = (x - x_min) / (x_max - x_min)
y = x_norm**2
So using the chain rule the first derivative of y = x_norm**2 would be 2x / (x_max - x_min) and the second derivative would be 2 / (x_max - x_min)**2.
Full example code:
#include <iostream>
#include <Eigen/Core>
#include <unsupported/Eigen/Splines>
using namespace Eigen;
using namespace std;
VectorXd normalize(const VectorXd &x) {
VectorXd x_norm;
x_norm.resize(x.size());
const double min = x.minCoeff();
const double max = x.maxCoeff();
for (int k = 0; k < x.size(); k++) {
x_norm(k) = (x(k) - min)/(max - min);
}
return x_norm;
}
int main() {
typedef Spline<double, 1, 3> Spline1D;
typedef SplineFitting<Spline1D> Spline1DFitting;
const Vector4d x{0, 1, 2, 4};
const Vector4d y = (x.array().square()); // x^2
const auto knots = normalize(x); // Normalize x to be between 0 and 1
const double scale = 1 / (x.maxCoeff() - x.minCoeff());
const double scale_sq = scale * scale;
Spline1D spline = Spline1DFitting::Interpolate(y.transpose(), 3, knots);
cout << "1st deriv at x = 0: " << spline.derivatives(0.00, 1)(1) * scale << endl;
cout << "1st deriv at x = 1: " << spline.derivatives(0.25, 1)(1) * scale << endl;
cout << "1st deriv at x = 2: " << spline.derivatives(0.50, 1)(1) * scale << endl;
cout << "1st deriv at x = 3: " << spline.derivatives(0.75, 1)(1) * scale << endl;
cout << "1st deriv at x = 4: " << spline.derivatives(1.00, 1)(1) * scale << endl;
cout << endl;
/**
* IMPORTANT NOTE: Eigen's spline module is not documented well. Once you fit a spline
* to find the derivative of the fitted spline at any point u [0, 1] you call:
*
* spline.derivatives(u, 1)(1)
* ^ ^ ^
* | | |
* | | +------- Access the result
* | +---------- Derivative order
* +------------- Parameter u [0, 1]
*
* The last bit `(1)` is if the spline is 1D. And value of `1` for the first
* order. `2` for the second order. Do not forget to scale the result.
*
* For higher dimensions, treat the return as a matrix and grab the 1st or
* 2nd column for the first and second derivative.
*/
cout << "2nd deriv at x = 0: " << spline.derivatives(0.00, 2)(2) * scale_sq << endl;
cout << "2nd deriv at x = 1: " << spline.derivatives(0.25, 2)(2) * scale_sq << endl;
cout << "2nd deriv at x = 2: " << spline.derivatives(0.50, 2)(2) * scale_sq << endl;
cout << "2nd deriv at x = 3: " << spline.derivatives(0.75, 2)(2) * scale_sq << endl;
cout << "2nd deriv at x = 4: " << spline.derivatives(1.00, 2)(2) * scale_sq << endl;
return 0;
}
Example output:
1st deriv at x = 0: 4.52754e-16
1st deriv at x = 1: 2
1st deriv at x = 2: 4
1st deriv at x = 3: 6
1st deriv at x = 4: 8
2nd deriv at x = 0: 2
2nd deriv at x = 1: 2
2nd deriv at x = 2: 2
2nd deriv at x = 3: 2
2nd deriv at x = 4: 2
Edit: see working .h-file for calculating B-splines of any order at the bottom.
Disclaimer: this is not an answer to my question as it is actually stated in the title, but rather a work-around with some comments.
After deliberations with user #Paul H. (see comments) I realized that my limited understanding of splines might have caused some confusion on my part. After some scrutiny of the Eigen documentation it seems plausible that the derivative() command does indeed works as intended, hence making my question badly phrased. The derivative() calculates the derivative of the spline rather than the derivative of the fitted function, as I intended it to. I have not figured out a way to get Eigen to output the function derivatives from the fit, and I don't think it is designed to to this. However, the derivatives can of course be readily calculated once the fitted points is obtained using some standard algorithm for calculating derivatives.
I wrote the following .h-file for calculating splines and their derivatives in the process which I thought worthwhile sharing. It's fairly well commented for convenience.
Note that this program uses 1-indexing rather than 0-indexing of the splines, hence for an e.g. quadratic B-spline order should be set to 4. This is a small quirk that is be easily fixed by changing the calculations to match wikipedia.
bsplines.h
//
// Header-file for calculating splines using standard libraries
//
// usage:
//
// x bsplines class constructs a set of splines up to some given order,
// on some given knot sequence, the splines are stored in a vector,
// such that splines[a][b] accesses the spline of order a and index b
// x get<some_member>() is an accessor that returns a pointer to some
// data member of the spline
// x calcsplines() calculates spline values as well as first and second
// order derivatives on some predefined grid
// x calcspline() returns the spline value as well as first and second
// derivatives in some point. This alborithm is slower than the grid
// one, due to unnecessary recalculations of intermediate results
// x writesplines() writes the splines and their derivatives to a file
// x for more details se the class declaration below
// TODO:
// x change to 0-indexation
// x introduce the possibility of calculating higher order derivatives
// recursively
//
// change log:
//
// 1.0 - initial release
// 1.1 - reworked grid such that the class now expects separate
// grid and knot files.
// - added the ability to calculate spline value in a point
// rather than calculate values on a grid
// - added a feature to change knots and grid
// 1.1.1 - reworked how returning single values works
// 1.1.2 - enabled swapping grid
//
// Note:
//
// This file uses 1-indexation rathar than 0-indexation, hence a qubic spline
// would be k = 4. Someone should eventually fix this as this is non-standard.
//
// Also, while only standard libraries are used here, you might want to check out
// some linear algebra package (e.g. Armadillo or Eigen) if you're going to use the
// splines in a context where you need linear algebraic operations.
//
// Originally developed by David Andersson
//
#include <iomanip>
#include <sstream>
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <functional>
using namespace std;
typedef unsigned int uint;
class bsplines // class for bsplines
{
// private section
uint order; // order of spline
uint gridpts; // number of grid points
uint knotpts; // number of knot points
double tolerance; // tolerance for float comparisons
vector<double> knots; // knot sequence
vector<double> grid; // grid points
class spline // a member spline in the set of splines
{
int index; // the spline index, or number
vector<double> vals; // spline values
vector<double> d1; // spline first derivatives
vector<double> d2; // spline second derivatives
double tval; // same, but in one point
double td1;
double td2;
friend bsplines; // for ease of access
public:
};
vector<vector <spline>> splines; // the set of splines
// puclic section
public:
void readknots(string); // read knots from file
void readknotsnorm(string); // read knots from file and normalize
void readgrid(string); // read grid from file
void swapgrid(string); // reads and swaps new grid from file
void writesplines(); // write spline vals and derivs to file
void buildsplines(); // build the set of splines
void calcsplines(); // calculate spline vals and derivs
void printknots(); // print knot sequence
void printgrid(); // print grid
void printgridsize(); // print gridsize
void printvals(uint,uint); // print values of a spline
vector <double> calcspline(uint,uint,double); // calculate spline in point
// accessors // returns pointer to member
vector <double>* getknots(){return &knots;}
vector <double>* getgrid(){return &grid;}
uint* getknotpts(){return &knotpts;}
uint* getgridpts(){return &gridpts;}
uint getnosplines(uint m){return splines[m].size();}
vector <spline>* getsplines(uint m){return &splines[m];}
vector <double>* getvals(uint m, uint n){return &splines[m][n].vals;}
vector <double>* getd1(uint m, uint n){return &splines[m][n].d1;}
vector <double>* getd2(uint m, uint n){return &splines[m][n].d2;}
// constructor // sets up the spline class
bsplines (string iknots, string igrid, uint iorder, double itol)
:order(iorder), tolerance(itol)
{
readknots(iknots);
readgrid(igrid);
buildsplines();
}
};
void bsplines::buildsplines()
{
{
for (uint l = 1; l <= order; l++)
{
vector <spline> splinevec;
for (uint k = 0; k < knotpts - l; k++)
{
spline tmp;
tmp.index = k;
tmp.vals.reserve(gridpts);
tmp.d1.reserve(gridpts);
tmp.d2.reserve(gridpts);
splinevec.push_back(tmp);
}
splines.push_back(splinevec);
}
}
}
vector <double> bsplines::calcspline(uint m, uint n, double x)
{
// first order splines // exceptions handles infinities
for (auto& sp : splines[0])
{
uint i = sp.index;
if (x > knots[i+1])
sp.tval = 0;
else if ((x >= knots[i] && x < knots[i+1]) || x == knots.back())
sp.tval = 1;
else
sp.tval = 0;
}
// higher order splines
for (uint o = 1; o < order; o++)
{
uint oo = o+1; // compensating for 1-indexation
for (auto& sp : splines[o])
{
uint i = sp.index;
double t1 = knots[i+oo-1] - knots[i];
double t2 = knots[i+oo] - knots[i+1];
double c = 0;
if (abs(t1) > tolerance)
c += (x - knots[i]) / t1 * splines[o-1][i].tval;
if (abs(t2) > tolerance)
c += (knots[i+oo] - x) / t2 * splines[o-1][i+1].tval;
sp.tval = c;
}
}
uint o = order - 1;
// first order derivatives
for (auto& sp : splines[o])
{
uint i = sp.index;
double t1 = knots[i+order-1] - knots[i];
double t2 = knots[i+order] - knots[i+1];
double c = 0;
if (abs(t1) > tolerance)
c += 1.0 / t1 * splines[o-1][i].tval;
if (abs(t2) > tolerance)
c -= 1.0 / t2 * splines[o-1][i+1].tval;
c *= (order-1);
sp.td1 = c;
}
// second order derivatives
for (auto& sp : splines[o])
{
uint i = sp.index;
double t1 = (knots[i+order-1] - knots[i+0]) * (knots[i+order-2] - knots[i+0]);
double t2 = (knots[i+order-1] - knots[i+0]) * (knots[i+order-1] - knots[i+1]);
double t3 = (knots[i+order-0] - knots[i+1]) * (knots[i+order-1] - knots[i+1]);
double t4 = (knots[i+order-0] - knots[i+1]) * (knots[i+order-0] - knots[i+2]);
double c = 0;
if (abs(t1) > tolerance)
c += 1.0 / t1 * splines[o-2][sp.index].tval;
if (abs(t2) > tolerance)
c -= 1.0 / t2 * splines[o-2][sp.index+1].tval;
if (abs(t3) > tolerance)
c -= 1.0 / t3 * splines[o-2][sp.index+1].tval;
if (abs(t4) > tolerance)
c += 1.0 / t4 * splines[o-2][sp.index+2].tval;
c *= (order-1)*(order-2);
sp.td2 = c;
}
vector <double> retvals = {splines[m][n].tval, splines[m][n].td1, splines[m][n].td2};
return retvals;
}
void bsplines::calcsplines()
{
// first order splines
for (auto& sp : splines[0])
{
uint i = sp.index;
for (auto& x : grid)
{
if (x > knots[i+1])
sp.vals.push_back(0);
else if ((x >= knots[i] && x < knots[i+1]) || x == knots.back())
sp.vals.push_back(1);
else
sp.vals.push_back(0);
}
}
// higher order splines
for (uint o = 1; o < order; o++)
{
uint oo = o+1; // compensating for 1-indexation
for (auto& sp : splines[o])
{
uint i = sp.index;
double t1 = knots[i+oo-1] - knots[i];
double t2 = knots[i+oo] - knots[i+1];
for (auto& x : grid)
{
uint k = &x - &grid[0];
double c = 0;
if (abs(t1) > tolerance)
c += (x - knots[i]) / t1 * splines[o-1][i].vals[k];
if (abs(t2) > tolerance)
c += (knots[i+oo] - x) / t2 * splines[o-1][i+1].vals[k];
sp.vals.push_back(c);
}
}
}
uint o = order - 1; // use this one when accessing splines;
// first order derivatives
for (auto& sp : splines[o])
{
uint i = sp.index;
double t1 = knots[i+order-1] - knots[i];
double t2 = knots[i+order] - knots[i+1];
for (auto& x : grid)
{
uint k = &x - &grid[0];
double c = 0;
if (abs(t1) > tolerance)
c += 1.0 / t1 * splines[o-1][i].vals[k];
if (abs(t2) > tolerance)
c -= 1.0 / t2 * splines[o-1][i+1].vals[k];
c *= (order-1);
sp.d1.push_back(c);
}
}
// second order derivatives
for (auto& sp : splines[o])
{
uint i = sp.index;
double t1 = (knots[i+order-1] - knots[i+0]) * (knots[i+order-2] - knots[i+0]);
double t2 = (knots[i+order-1] - knots[i+0]) * (knots[i+order-1] - knots[i+1]);
double t3 = (knots[i+order-0] - knots[i+1]) * (knots[i+order-1] - knots[i+1]);
double t4 = (knots[i+order-0] - knots[i+1]) * (knots[i+order-0] - knots[i+2]);
for (auto& x : grid)
{
uint k = &x - &grid[0];
double c = 0;
if (abs(t1) > tolerance)
c += 1.0 / t1 * splines[o-2][sp.index].vals[k];
if (abs(t2) > tolerance)
c -= 1.0 / t2 * splines[o-2][sp.index+1].vals[k];
if (abs(t3) > tolerance)
c -= 1.0 / t3 * splines[o-2][sp.index+1].vals[k];
if (abs(t4) > tolerance)
c += 1.0 / t4 * splines[o-2][sp.index+2].vals[k];
c *= (order-1)*(order-2);
sp.d2.push_back(c);
}
}
}
void bsplines::readknots(string knotfile)
{
double x;
ifstream readknots(knotfile);
while (readknots >> x)
knots.push_back(x);
for (uint k = 0; k < order - 1; k++)
{
knots.insert(knots.begin(),knots.front());
knots.insert(knots.end(),knots.back());
}
knotpts = knots.size();
}
void bsplines::readknotsnorm(string knotfile)
{
double x;
knots.reserve(knotpts + 2*(order - 1));
ifstream readknots(knotfile);
while (readknots >> x)
knots.push_back(x);
auto minmax = minmax_element(begin(knots), end(knots));
double min = *(minmax.first);
double max = *(minmax.second);
for (auto& el : knots)
el = (el - min) / (max-min);
}
void bsplines::readgrid(string gridfile)
{
double x;
ifstream readgrid(gridfile);
while (readgrid >> x)
grid.push_back(x);
gridpts = grid.size();
}
void bsplines::swapgrid(string gridfile)
{
grid = {};
double x;
ifstream readgrid(gridfile);
while (readgrid >> x)
grid.push_back(x);
gridpts = grid.size();
}
void bsplines::printknots()
{
cout << "content in knot vector: " << endl;
for (auto& el : knots)
cout << el << " ";
cout << endl;
}
void bsplines::printgrid()
{
cout << "content in grid vector: " << endl;
for (auto& el : grid)
cout << el << " ";
cout << endl;
}
void bsplines::printgridsize()
{
cout << "number of grid points: " << endl << grid.size() << endl;
}
void bsplines::printvals(uint m, uint n)
{
cout << "content in spline (B" << m << "," << n << ") vals vector: " << endl;
for (auto& el : splines[n][m].vals)
cout << el << " ";
cout << endl;
}
void bsplines::writesplines()
{
for (uint o = 0; o < order; o++)
for (auto& sp : splines[o])
{
uint i = sp.index;
ostringstream namestream;
namestream << "B(" << fixed << setprecision(1) << i << ","
<< fixed << setprecision(1) << o << ").csv";
string filename = namestream.str();
ofstream fs;
fs.open(filename);
if (o < order - 1)
{
for (uint k = 0; k < sp.vals.size(); k++)
fs << sp.vals[k] << "," << 0 << "," << 0 << endl;
fs.close();
}
else
{
for (uint k = 0; k < sp.vals.size(); k++)
fs << sp.vals[k] << "," << sp.d1[k] << "," << sp.d2[k] << endl;
fs.close();
}
cout << "write " << sp.vals.size() << " numbers to " << filename << endl;
}
}
Edit: updated .h-file.

How to Perform Tuckerman Rounding for Floating Point Square Root

I am trying to perform a Tuckerman Rounding Test in order to determine the correctly rounded to nearest result.
I created a program in C++ to compare two solutions to a square root of a number and perform a tuckerman test on them. However, the C++ math library solution fails to pass the tuckerman test, so I'm wondering what could be wrong?
Here is my output:
Square root program started
Input value is 62a83003
===Tuckerman Test with MATLAB result===
Square root result from MATLAB = 5112b968
g*(g-ulp) = 62a83001
b = 62a83003
g*(g+ulp) = 62a83003
=====>Passes Tuckerman test
===Tuckerman Test with correct result===
Correct square root result = 5112b969
g*(g-ulp) = 62a83003
b = 62a83003
g*(g+ulp) = 62a83005
=====>Fails Tuckerman test
Here is my code (C++):
#include <iostream>
#include <cmath>
#include <fstream>
using namespace std;
union newfloat{
float f;
unsigned int i;
};
int main ()
{
// Declare new floating point numbers
newfloat input;
newfloat result, resultm1, resultp1;
newfloat correct_result, correct_resultm1, correct_resultp1;
newfloat resultm1_times_result, resultp1_times_result;
newfloat correct_resultm1_times_result, correct_resultp1_times_result;
// Print message at start of program
cout << "Square root program started" << endl;
input.i = 0x62A83003; // Input we are trying to find the square root of
cout << "Input value is " << hex << input.i << "\n" << endl; // Print input value
result.i = 0x5112B968; // Result from MATLAB
resultm1.i = result.i - 1; // value minus 1 ulp
resultp1.i = result.i + 1; // value plus 1 ulp
correct_result.f = sqrt(input.f); // Compute correct square root
correct_resultm1.i = correct_result.i - 1; // correct value minus 1 ulp
correct_resultp1.i = correct_result.i + 1; // correct value plus 1 ulp
resultm1_times_result.f = result.f * resultm1.f; // Compute g(g-ulp) for matlab result
resultp1_times_result.f = result.f * resultp1.f; // Compute g(g+ulp) for matlab result
correct_resultm1_times_result.f = correct_result.f * correct_resultm1.f; // Compute g*(g-ulp) for correct result
correct_resultp1_times_result.f = correct_result.f * correct_resultp1.f; // Compute g*(g+ulp) for correct result
// Print output from MATLAB algorithm and perform tuckerman test
cout << "===Tuckerman Test with MATLAB result===" << endl;
cout << "Square root result from MATLAB = " << result.i << endl;
cout << "g*(g-ulp) = " << hex << resultm1_times_result.i << endl;
cout << "b = " << hex << input.i << endl;
cout << "g*(g+ulp) = " << hex << resultp1_times_result.i << endl;
if ((resultm1_times_result.f < input.f) && (input.f <= resultp1_times_result.f))
cout << "=====>Passes Tuckerman test" << endl;
else
cout << "=====>Fails Tuckerman test" << endl;
cout << "\n" << endl;
// Print output from C++ sqrt math library and perform tuckerman test
cout << "===Tuckerman Test with correct result===" << endl;
cout << "Correct square root result = " << hex << correct_result.i << endl;
cout << "g*(g-ulp) = " << hex << correct_resultm1_times_result.i << endl;
cout << "b = " << hex << input.i << endl;
cout << "g*(g+ulp) = " << hex << correct_resultp1_times_result.i << endl;
if ((correct_resultm1_times_result.f < input.f) && (input.f <= correct_resultp1_times_result.f))
cout << "=====>Passes Tuckerman test" << endl;
else
cout << "=====>Fails Tuckerman test" << endl;
return 0;
}
The original publication that introduced Tuckerman rounding for the square root was:
Ramesh C. Agarwal, James W. Cooley, Fred G. Gustavson, James B. Shearer, Gordon Slishman, Bryant Tuckerman,
"New scalar and vector elementary functions for the IBM System/370", IBM J. Res. Develop., Vol. 30, No. 2, March 1986, pp. 126-144.
This paper specifically points out that the multiplications used to compute the products g*(g-ulp) and g*(g+ulp) are truncating, not rounding multiplications:
"However, these inequalities can be shown to be equivalent to
y- * y < x <= y * y+ ,
where * denotes System/360/370 multiplication (which truncates the result), so that the tests are easily carried out
without the need for extra precision. (Note the asymmetry: one <, one <=.) If the left inequality fails, y is too large; if the
right inequality fails, y is too small."
The following C99 code shows how Tuckerman rounding is successfully utilized to deliver correctly rounded results in a single-precision square root function.
#include <stdio.h>
#include <stdlib.h>
#include <fenv.h>
#include <math.h>
#pragma STDC FENV_ACCESS ON
float mul_fp32_rz (float a, float b)
{
float r;
int orig_rnd = fegetround();
fesetround (FE_TOWARDZERO);
r = a * b;
fesetround (orig_rnd);
return r;
}
float my_sqrtf (float a)
{
float b, r, v, w, p, s;
int e, t, f;
if ((a <= 0.0f) || isinff (a) || isnanf (a)) {
if (a < 0.0f) {
r = 0.0f / 0.0f;
} else {
r = a + a;
}
} else {
/* compute exponent adjustments */
b = frexpf (a, &e);
t = e - 2*512;
f = t / 2;
t = t - 2 * f;
f = f + 512;
/* map argument into the primary approximation interval [0.25,1) */
b = ldexpf (b, t);
/* initial approximation to reciprocal square root */
r = -6.10005470e+0f;
r = r * b + 2.28990124e+1f;
r = r * b - 3.48110069e+1f;
r = r * b + 2.76135244e+1f;
r = r * b - 1.24472151e+1f;
r = r * b + 3.84509158e+0f;
/* round rsqrt approximation to 11 bits */
r = rintf (r * 2048.0f);
r = r * (1.0f / 2048.0f);
/* Use A. Schoenhage's coupled iteration for the square root */
v = 0.5f * r;
w = b * r;
w = (w * -w + b) * v + w;
v = (r * -w + 1.0f) * v + v;
w = (w * -w + b) * v + w;
/* Tuckerman rounding: mul_rz (w, w-ulp) < b <= mul_rz (w, w+ulp) */
p = nextafterf (w, 0.0f);
s = nextafterf (w, 2.0f);
if (b <= mul_fp32_rz (w, p)) {
w = p;
} else if (b > mul_fp32_rz (w, s)) {
w = s;
}
/* map back from primary approximation interval by jamming exponent */
r = ldexpf (w, f);
}
return r;
}
int main (void)
{
volatile union {
float f;
unsigned int i;
} arg, res, ref;
arg.i = 0;
do {
res.f = my_sqrtf (arg.f);
ref.f = sqrtf (arg.f);
if (res.i != ref.i) {
printf ("!!!! error # arg=%08x: res=%08x ref=%08x\n",
arg.i, res.i, ref.i);
break;
}
arg.i++;
} while (arg.i);
return EXIT_SUCCESS;
}

Finding the roots of a nonlinear equation using C++

What method would I use to find the roots of f(x) = 5x(e^-mod(x))cos(x) + 1 ? I have being trying the durand-kerner method but I can't get it to work. Are there any easier ways of doing it?
Here is the my code using the durand-kerner method
#include <iostream>
#include <complex>
#include <math.h>
using namespace std;
typedef complex<double> dcmplx;
dcmplx f(dcmplx x)
{
// the function we are interested in
double a4 = 5;
double a0 = 1;
return (a4 * x * exp(-x) * cos(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 = 100;
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-q)*(p0-r)*(p0-s));
q = q0 - f(q0)/((q0-p)*(q0-r)*(q0-s));
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;
}
This approach makes use of the bisection method, and the fact that you can do a little math to find an upper bound for the highest zero, respectively.
Reproduced at http://ideone.com/fFLjsh
#include <iostream>
#include <iomanip>
#include <cmath>
#include <vector>
#include <utility>
#define MINX (-20.0f)
//MAXX Happens to be an upper bound for all zeroes of the function...
#define MAXX (1.0f)
#define NUM_INTERVALS (1000000)
#define NUM_BISECTION_ITERATIONS (30)
using namespace std;
double f(double x){
return 5 * x * exp(-x) * cos(x) + 1;
}
double bisection_method(double x0, double x1){
for (unsigned int i = 0; i < NUM_BISECTION_ITERATIONS; i++){
double midpoint = 0.5*x0 + 0.5*x1;
f(x0) * f(midpoint) < 0 ? x1 = midpoint : x0 = midpoint;
}
return 0.5*x0 + 0.5*x1;
}
int main(int argc, char** argv){
vector<pair<double, double>> relevant_intervals;
for (unsigned int i = 0; i < NUM_INTERVALS - 1; i++){
double x0 = MINX + (MAXX - MINX) / NUM_INTERVALS * (i);
double x1 = MINX + (MAXX - MINX) / NUM_INTERVALS * (i + 1);
if (f(x0) * f(x1) < 0)
relevant_intervals.push_back(make_pair(x0, x1));
}
cout << fixed << setprecision(20);
for (const auto & x : relevant_intervals){
cout << "One solution is approximately " << bisection_method(x.first, x.second) << endl;
}
}
I am not familiar with Durand-Kerner method, but according to Wiki http://en.wikipedia.org/wiki/Durand%E2%80%93Kerner_method, it is suitable only for solving polynomial equations. Note the line in the wiki page: "The explanation is for equations of degree four. It is easily generalized to other degrees."
Your equation is not polynomial. The numerical solution will probably not converge.
Regardless of that your function f returns wrong formula: return a4 * x * exp(-abs(x)) * cos(x) + a0; (you forgot about complex modulo, i.e. abs)
and your iterations seem also wrong. They should read:
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));
but even if you make these changes, the solution will not converge - it will be oscilating. The reason is probably as written above - the method is not suitable for this type of equation.

Vastly different output C++ monte carlo approximation

doing a C++ approximation of Pi using a random number generator, output works exactly as expected on my AMD 64 machine running Ubuntu, however on my school machine the second algorithm I've implemented is broken, and would love some insight as to why. Code is as follows:
#ifndef RANDOMNUMBER_H_
#define RANDOMNUMBER_H_
class RandomNumber {
public:
RandomNumber() {
x = time(NULL);
m = pow(2, 19); //some constant value
M = 65915 * 7915; //multiply of some simple numbers p and q
method = 1;
}
RandomNumber(int seed) {
x = ((seed > 0) ? seed : time(NULL));
m = pow(2, 19); //some constant value
method = 1; //method number
M = 6543 * 7915; //multiply of some simple numbers p and q
}
void setSeed(long int seed) {
x = seed; //set start value
}
void chooseMethod(int method) {
this->method = ((method > 0 && method <= 2) ? method : 1); //choose one of two method
}
long int linearCongruential() { //first generator, that uses linear congruential method
long int c = 0; // some constant
long int a = 69069; //some constant
x = (a * x + c) % m; //solution next value
return x;
}
long int BBS() { //algorithm Blum - Blum - Shub
x = (long int) (pow(x, 2)) % M;
return x;
}
double nextPoint() { //return random number in range (-1;1)
double point;
if (method == 1) //use first method
point = linearCongruential() / double(m);
else
point = BBS() / double(M);
return point;
}
private:
long int x; //current value
long int m; // some range for first method
long int M; //some range for second method
int method; //method number
};
#endif /* RANDOMNUMBER_H_ */
and test class:
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <iomanip>
#include "RandomNumber.h"
using namespace std;
int main(int argc, char* argv[]) {
cout.setf(ios::fixed);
cout.precision(6);
RandomNumber random;
random.setSeed(argc);
srand((unsigned) time(NULL));
cout << "---------------------------------" << endl;
cout << " Monte Carlo Pi Approximation" << endl;
cout << "---------------------------------" << endl;
cout << " Enter number of points: ";
long int k1;
cin >> k1;
cout << "Select generator number: ";
int method;
cin >> method;
random.chooseMethod(method);
cout << "---------------------------------" << endl;
long int k2 = 0;
double sumX = 0;
double sumY = 0;
for (long int i = 0; i < k1; i++) {
double x = pow(-1, int(random.nextPoint() * 10) % 2)
* random.nextPoint();
double y = pow(-1, int(random.nextPoint() * 10) % 2)
* random.nextPoint();
sumX += x;
sumY += y;
if ((pow(x, 2) + pow(y, 2)) <= 1)
k2++;
}
double pi = 4 * (double(k2) / k1);
cout << "M(X) = " << setw(10) << sumX / k1 << endl; //mathematical expectation of x
cout << "M(Y) = " << setw(10) << sumY / k1 << endl; //mathematical expectation of y
cout << endl << "Pi = " << pi << endl << endl; //approximate Pi
return 0;
}
The second method returns 4.000 consistently on my lab machine, yet returns a rather close approximation on my personal machine.
For one thing, the BBS generator as you're using it will always return 1.
Since your program takes no arguments, presumably its argc will be 1. You pass argc as the seed (why?), so the initial value of x is 1.
BBS() has the following logic:
x = (long int) (pow(x, 2)) % M;
Clearly, 1 squared modulo M gives 1, so x never changes.
When you run the simulation with such a generator, your program will always output 4.
P.S. Wikipedia has the following to say about the initial value x0 for Blum Blum Shub:
The seed x0 should be an integer that's co-prime to M (i.e. p and q are not factors of x0) and not 1 or 0.

Different output with c++ pi approximation [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Vastly different output C++ monte carlo approximation
On my 64-bit ubuntu computer, the following code works as expected, and returns a close approximation for pi with both algorithms. However, on the lab machine, where I must demo the code, a 32-bit rhel 3 machine, the second algorithm always returns 4, and I cannot figure out why. Any insight would be appreciated.
/*
* RandomNumber.h
*
*
*
*/
#ifndef RANDOMNUMBER_H_
#define RANDOMNUMBER_H_
class RandomNumber {
public:
RandomNumber() {
x = time(NULL);
m = pow(2, 31); //some constant value
M = 65915 * 7915; //multiply of some simple numbers p and q
method = 1;
}
RandomNumber(int seed) {
x = ((seed > 0) ? seed : time(NULL));
m = pow(2, 31); //some constant value
method = 1; //method number
M = 6543 * 7915; //multiply of some simple numbers p and q
}
void setSeed(long int seed) {
x = seed; //set start value
}
void chooseMethod(int method) {
this->method = ((method > 0 && method <= 2) ? method : 1); //choose one of two method
}
long int linearCongruential() { //first generator, that uses linear congruential method
long int c = 0; // some constant
long int a = 69069; //some constant
x = (a * x + c) % m; //solution next value
return x;
}
long int BBS() { //algorithm Blum - Blum - Shub
x = (long int) (pow(x, 2)) % M;
return x;
}
double nextPoint() { //return random number in range (-1;1)
double point;
if (method == 1) //use first method
point = linearCongruential() / double(m);
else
point = BBS() / double(M);
return point;
}
private:
long int x; //current value
long int m; // some range for first method
long int M; //some range for second method
int method; //method number
};
#endif /* RANDOMNUMBER_H_ */
And the test class:
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <iomanip>
#include "RandomNumber.h"
using namespace std;
int main() {
cout.setf(ios::fixed);
cout.precision(6);
RandomNumber random;
srand((unsigned) time(NULL));
cout << "---------------------------------" << endl;
cout << " Monte Carlo Pi Approximation" << endl;
cout << "---------------------------------" << endl;
cout << " Enter number of points: ";
long int k1;
cin >> k1;
cout << "Select generator number: ";
int method;
cin >> method;
random.chooseMethod(method);
cout << "---------------------------------" << endl;
long int k2 = 0;
double sumX = 0;
double sumY = 0;
for (long int i = 0; i < k1; i++) {
double x = pow(-1, int(random.nextPoint() * 10) % 2)
* random.nextPoint();
double y = pow(-1, int(random.nextPoint() * 10) % 2)
* random.nextPoint();
sumX += x;
sumY += y;
if ((pow(x, 2) + pow(y, 2)) <= 1)
k2++;
}
double pi = 4 * (double(k2) / k1);
cout << "M(X) = " << setw(10) << sumX / k1 << endl; //mathematical expectation of x
cout << "M(Y) = " << setw(10) << sumY / k1 << endl; //mathematical expectation of y
cout << endl << "Pi = " << pi << endl << endl; //approximate Pi
return 0;
}
The problem is that pow returns a double, which loses precision at the low end. Converting to long int for the % operator always returns the same result, and so your RNG outputs constant -60614748.
x = time(0) 1354284781
pow(x, 2) 1.83409e+18 0x1.973fdc9dc7787p+60
(long int) pow(x, 2) -2147483648 0x80000000
(long int) pow(x, 2) % M -60614748
The fix is to change x = (long int) (pow(x, 2)) % M; to x = x * x % M, performing all arithmetic within long int. Note that this is still strictly speaking incorrect, as signed overflow is undefined; more correct is to use unsigned long.
The truncation to long in BBS() causes the same "random" number to be generated.
PS. The return from the pow function is a number, which is too big to be represented in your machine's long type. When doing the conversion to long this results in undefined behaviour. One particular effect of the undefined behaviour might be the result of the conversion to be 0x80000000 or 0x7fffffff so you end up with a sequence of the same numbers.
x = time(0) 1354284781
pow(x, 2) 1.83409e+18 0x1.973fdc9dc7787p+60
A 32-bit int holds a value up to 2^31-1 the value of x^2 is greater than that.