// Function as parameter of a function
#include <iostream>
#include <cmath>
#include <cassert>
using namespace std;
const double PI = 4 * atan(1.0); // tan^(-1)(1) == pi/4 then 4*(pi/4)== pi
typedef double(*FD2D)(double);
double root(FD2D, double, double); //abscissae of 2-points,
//For the algorithm to work, the function must assume values of opposite sign in these two points, check
// at point 8
double polyn(double x) { return 3 - x*(1 + x*(27 - x * 9)); }
int main() {
double r;
cout.precision(15);
r = root(sin, 3, 4);
cout << "sin: " << r << endl
<< "exactly: " << PI << endl << endl;
r = root(cos, -2, -1.5);
cout << "cos: " << r << endl
<< "exactly: " << -PI/2 << endl << endl;
r = root(polyn, 0, 1);
cout << "polyn: " << r << endl
<< "exactly: " << 1./3 << endl << endl;
/*
we look for the root of the function equivalent to function polyn
but this time defined as a lambda function
*/
r = root([](double x) -> double {
return 3 - x*(1 + x*(27 - x * 9));
}, 0, 1);
cout << "lambda: " << r << endl
<< "exactly: " << 1. / 3 << endl << endl;
return 0;
}
// Finding root of function using bisection.
// fun(a) and fun(b) must be of opposite sign
double root(FD2D fun, double a, double b) {
static const double EPS = 1e-15; // 1×10^(-15)
double f, s, h = b - a, f1 = fun(a), f2 = fun(b);
if (f1 == 0) return a;
if (f2 == 0) return b;
assert(f1*f2<0); // 8.- macro assert from header cassert.
do {
if ((f = fun((s = (a + b) / 2))) == 0) break;
if (f1*f2 < 0) {
f2 = f;
b = s;
}
else {
f1 = f;
a = s;
}
} while ((h /= 2) > EPS);
return (a + b) / 2;
}
Could somebody explain me how the loop in double root function works? I don't seem to understand 100%, I checked this bisection method online and try on paper, but I can't manage to figure it out from this example.
Thanks in advance!
It's a lot easier to understand if you split the "clever" line into multiple lines. Here's some modifications, plus comments:
double root(FD2D fun, double a, double b) {
static const double EPS = 1e-15; // 1×10^(-15)
double fa = fun(a), fb = fun(b);
// if either f(a) or f(b) are the root, return that
// nothing else to do
if (fa == 0) return a;
if (fb == 0) return b;
// this method only works if the signs of f(a) and f(b)
// are different. so just assert that
assert(fa * fb < 0); // 8.- macro assert from header cassert.
do {
// calculate fun at the midpoint of a,b
// if that's the root, we're done
// this line is awful, never write code like this...
//if ((f = fun((s = (a + b) / 2))) == 0) break;
// prefer:
double midpt = (a + b) / 2;
double fmid = fun(midpt);
if (fmid == 0) return midpt;
// adjust our bounds to either [a,midpt] or [midpt,b]
// based on where fmid ends up being. I'm pretty
// sure the code in the question is wrong, so I fixed it
if (fa * fmid < 0) { // fmid, not f1
fb = fmid;
b = midpt;
}
else {
fa = fmid;
a = midpt;
}
} while (b-a > EPS); // only loop while
// a and b are sufficiently far
// apart
return (a + b) / 2; // approximation
}
Related
My task is to find the root of a function with both the Newton Raphson and the bisection method within an error margin of 10E-7.
The point of all that is, that we learn that the Newton Raphson method is faster and more effective.
Now for some reason I come to the opposite result. Although I am aware that the initial guess of the root in both methods strongly affects the number of necessary iterations. But I entered a similar guess in both algorithms and my fellow students dont get the result I do.
Bisection method:
#include <iostream>
#include <iomanip>
using namespace std;
//Declaring the given function
double func1(double x) {
return 0.00000000027 * (x - 10000000) - 0.16460351745 * (-1 + ((1000000000) / (x))) * 1 / (sqrt(x));
}
int main() {
std::fixed;
//Initial guess: root ist at 10 to the 7.
double x1 = 10000000;
double x2 = 1000000000;
double eps = 0.0000001;
int i = 0;
double x0[100000];
x0[0] =0;
//Exception handler
if (func1(x1) * func1(x2) > 0) {
cout << "Root is not inside the bracket.";
goto end;
}
goto start;
//Bisection Algorithm
while (abs(x0[i] - x0[i-1]) >= eps) {
start:
i = i + 1;
x0[i] = 0.5 * (x1 + x2);
if (func1(x1) * func1(x0[i]) < 0) {
x2 = x0[i];
}
else {
x1 = x0[i];
}
}
cout << endl << "Bisection Method: " << fixed << setprecision(10) << x0[i] << endl << "Iterations: " << i << endl << endl << endl << endl << endl;
end:
return 0;
}
}
Newton Raphson:
#include <iostream>
#include <iomanip>
using namespace std;
// Declaring the function and its derivative
double func1(double x) {
return 0.00000000027 * (x - 10000000) - 0.16460351745 * (-1 + ((1000000000) / (x))) * 1 / (sqrt(x));
}
double funcderiv1(double x) {
return 0.00000000027+((0.1646035174)/(2*x*x*sqrt(x)))*(30000000-x);
}
int main()
{
std::fixed;
double eps = 1;
double x_start = 10000000;
double c;
int i = 0;
while (eps >= 0.0000001) {
c = x_start - ((func1(x_start)) / (funcderiv1(x_start)));
eps = abs(func1(x_start) / funcderiv1(x_start));
x_start = c;
i = i + 1;
}
cout << fixed << setprecision(5) << "RESULT " << c << endl << " Iterations: " << i << endl;
}
The root is at 17903534.23630
Does anyone know why my bisection method needs 55 iterations while Newton Raphson takes like 82?
For the function
f(x) = A * (x - B) - C * (D / x - 1) / sqrt(x)
A = 0.00000000027
B = 10000000
C = 0.16460351745
D = 1000000000
the correct derivative is:
f'(x) = A - C (x - 3D) / (2 * x * x * sqrt(x))
Compare this with your expression:
g(x) = A - C (x - 3B) / (2 * x * x * sqrt(x))
After fixing the formula (by adding two zeros), your code makes 6 iterations:
RESULT 17903534.23630
Iterations: 6
double round(double a)
{
double b, c, f, g;
float d[2];
c = modf(a, &b);
if (a > 0) {
f = a - c;
g = a - c + 1;
d[0] = f;
d[1] = g;
return d[0], d[1];
}
else {
f = a - c;
g = a - c - 1;
d[0] = f;
d[1] = g;
return d[0], d[1];
}
}
I need to get 2 numbers it the end(for ex: if I have num 12.34, I want to get 12 and 13)This is my function of rounding for pos and neg numbers. But it returns only 1 value(( So I'm stack...pls, help how to return 2 values?
You cannot return two things in the return, so return d[0],d[1] compiles but doesn't work as you expect. You can use two reference parameters in the function prototype to return. Something like void round(double a, double* result1, double* result2). Into the function, set d[0] to *result1 and d[1] to *result2.
Another thing: Are you sure the line g = a - c - 1; when a is negative is correct? I think you need to do g = a + c - 1;, because a is negative.
#include "pch.h"
#include <iostream>
#include <array>
using namespace std;
auto rounding(double x)
{
int part = static_cast<int>(x);
if (x < 0.0)
{
return array<int, 2> {
part - 1, part
};
}
else
{
return array<int, 2> {
part, part + 1
};
}
}
int main()
{
double x;
cout << "Please, enter a float number to round: ";
cin >> x;
auto r1 = rounding(x);
if (x > 0) {
cout << "A lower value: " << r1[0] << endl << "A bigger value: " << r1[1];
}
else {
cout << "A bigger value: " << r1[0] << endl << "A lower value: " << r1[1];
}
}
Just signed up, because my mind is blowing up on this stupid error.
I was calculating elliptic curves in a quick and dirty way with everything in 1 source-file.
Then I thought about cleaning up my code and start to separate the functions and classes in different files.
It's been a long time for me programming in C++ so I guess it is a really stupid beginner mistake.
So I am getting LNK1169-Error and LNK2005-Error and the solutions I found are about including .cpp which I am not doing. I although found out about the extern-keyword, but that seems to be kind of the solution for global variables.
Maybe someone can help me.
EDIT:
Sorry for putting that much code. I just don't know what is relevant for the error and what's not.
The error I am getting are like this:
fatal error LNK1169: one or more multiply defined symbols found. Elliptic 1 C:\Users\Björn\documents\visual studio 2015\Projects\Elliptic 1\Debug\Elliptic 1.exe
error LNK2005 "public: int __thiscall Value::operator==(class Value const &)" (??8Value##QAEHABV0##Z) already defined in Tests.obj
error LNK2005 "public: int __thiscall Value::operator==(int)" (??8Value##QAEHH#Z) already defined in Tests.obj
Here is my code:
Value.hpp
#pragma once
extern int PRIME;
// An own Int-Class to overload operators with modulo
class Value
{
public:
int v;
static friend std::ostream& operator<<(std::ostream& os, const Value& a);
Value()
{
this->v = 0;
}
Value(int a)
{
this->v = a;
}
Value operator+(const Value& other)
{
return Value((this->v + other.v) % PRIME);
}
Value operator+(int a)
{
return Value((this->v + a) % PRIME);
}
Value operator-(const Value& other)
{
Value t = Value((v - other.v) % PRIME);
if (t.v < 0)
{
t = t + PRIME;
return t;
}
return t;
}
Value operator-(int a)
{
Value t = Value((v - a) % PRIME);
if (t.v < 0)
{
t = t + PRIME;
return t;
}
return t;
}
void operator=(const Value other)
{
this->v = other.v;
}
Value operator*(const Value& a);
Value operator*(int a);
Value operator^(int a);
Value operator/(const Value& a);
int operator!=(int b);
int operator!=(const Value& b);
int operator==(int b);
int operator==(const Value& b);
Value operator~();
};
Value Value::operator*(const Value& a)
{
return Value((this->v*a.v) % PRIME);
}
Value Value::operator*(int a)
{
return Value((this->v*a) % PRIME);
}
Value Value::operator^(int b)
{
Value ret(1);
Value mul(this->v);
while (b)
{
if (b & 1)
ret = (ret * mul);
b = (b >> 1);
mul = mul * mul;
}
return ret;
}
Value Value::operator/(const Value& a)
{
if (a.v == 0)
return Value(0);
Value f = (Value)a ^ (PRIME - 2);
return *this * f;
}
int Value::operator!=(int b)
{
if (this->v != b)
return 1;
return 0;
}
int Value::operator!=(const Value& b)
{
if (this->v != b.v)
return 1;
return 0;
}
int Value::operator==(int b)
{
if (this->v == b)
return 1;
return 0;
}
int Value::operator==(const Value& b)
{
if (this->v == b.v)
return 1;
return 0;
}
Value Value::operator~()
{
return *this ^ ((PRIME - 1 + 2) / 4);
}
std::ostream& operator<<(std::ostream& os, const Value& a)
{
return os << a.v;
}
Point.hpp
#pragma once
#include "Value.hpp"
#include <iostream>
class Point
{
public:
Value x;
Value y;
Value z = 0;
static friend std::ostream& operator<<(std::ostream& os, const Point& p);
Point(int a, int b)
{
x.v = a;
y.v = b;
}
Point(int a, int b, int c)
{
x.v = a;
y.v = b;
z.v = c;
}
Point(Value a, Value b)
{
x.v = a.v;
y.v = b.v;
}
Point(Value a, Value b, Value c)
{
x.v = a.v;
y.v = b.v;
z.v = c.v;
}
Point& operator=(const Point& other)
{
x.v = other.x.v;
y.v = other.y.v;
z.v = other.z.v;
return *this;
}
int operator==(Point& other)
{
if (this->x == other.x && this->y == other.y && this->z == other.z)
return 1;
return 0;
}
int operator!=(Point& other)
{
if (this->x != other.x || this->y != other.y || this->z != other.z)
return 1;
return 0;
}
};
std::ostream& operator<<(std::ostream& os, const Point& p)
{
if ((Value)p.z == 0)
return os << "(" << p.x.v << "," << p.y.v << ")";
else
return os << "(" << p.x.v << "," << p.y.v << "," << p.z.v << ")";
}
Helper.hpp
#pragma once
#include "Point.hpp"
#include <vector>
// Forward declaration
int isEC(Value a, Value b);
Value calcEC(int x, Value a, Value b);
int testSqr(Value ySqr);
// Point Addition
Point add(Point p1, Point p2, Value a)
{
// 2D Addition
if (p1.z == 0 && p2.z == 0)
{
// 2 different points
if (p1.x.v != p2.x.v || p1.y.v != p2.y.v)
{
// m = (y2-y1)/(x2-x1)
Value h = p2.y - p1.y;
Value j = p2.x - p1.x;
Value m = h / j;
// x3 = m^2-x1-x2
Value f = m*m;
Value g = f - p1.x;
Value x3 = g - p2.x;
// y3 = m(x1-x3)-y1
Value t = p1.x - x3;
Value l = m * t;
Value y3 = l - p1.y;
if (x3.v < 0)
x3 = x3 + PRIME;
if (y3.v < 0)
y3 = y3 + PRIME;
return Point(x3, y3);
}
// Same points
else
{
// m = (3*x1^2+a)/(2*y1)
Value f = p1.x ^ 2;
Value g = f * 3;
Value h = g + a;
Value j = p1.y * 2;
Value m = h / j;
// x3 = m^2-2*x1
Value t = m*m;
Value x = p1.x * 2;
Value x3 = t - x;
// y3 = m(x1-x3)-y1
Value z = p1.x - x3;
Value i = m * z;
Value y3 = i - p1.y;
if (x3.v < 0)
x3 = x3 + PRIME;
if (y3.v < 0)
y3 = y3 + PRIME;
return Point(x3, y3);
}
}
// 3D Addition - Same points
else if (p1 == p2 && p1.z == 1 && p2.z == 1)
{
Value A = p1.y ^ 2;
Value B = p1.x * A * 4;
Value C = (A ^ 2) * 8;
Value D = (p1.x ^ 2)* 3 + a*(p1.z ^ 4);
//Value x3 = (((3 * (p1.x ^ 2) + a*(p1.z ^ 4)) ^ 2) - 8 * p1.x*(p1.y ^ 2));
Value x3 = (D ^ 2) - B * 2;
//Value y3 = (3 * (p1.x ^ 2) + a*(p1.z ^ 4)*(4 * p1.x*(p1.y ^ 2) - x3) - 8 * (p1.y ^ 4));
Value y3 = D*(B - x3) - C;
Value z3 = p1.y*p1.z * 2;
return Point(x3, y3, z3);
}
// 3D Addition - 2 different points
else if (p1 != p2)
{
Value A = p1.z ^ 2;
Value B = p1.z * A;
Value C = p2.x * A;
Value D = p2.y * B;
Value E = C - p1.x;
Value F = D - p1.y;
Value G = E ^ 2;
Value H = G * E;
Value I = p1.x * G;
Value x3 = (F ^ 2) - (H + (I * 2));
Value y3 = F*(I - x3) - p1.y*H;
Value z3 = p1.z * E;
return Point(x3, y3, z3);
}
return Point(0, 0, 0);
}
// Find all points and print them
std::vector<Point> findAllPoints(Value a, Value b)
{
Value ySqr;
std::vector<Point> vec;
std::cout << "Alle Punkte fuer a = " << a << ", b = " << b << " und Prime = " << PRIME << std::endl;
// Is it an elliptic curve?
if (isEC(a, b))
{
// Test all x-Values
for (int x = 0; x <= PRIME - 1;x++)
{
// y^2
ySqr = calcEC(x, a, b);
// Test ySqr for square by root
if (testSqr(ySqr))
{
//sqrt operator ~
Value yPos = ~ySqr;
std::cout << "(" << x << "," << yPos << ")\t";
Value yNeg = yPos - (yPos * 2);
// Save found points into vector
vec.push_back(Point(x, yPos));
vec.push_back(Point(x, yNeg));
if (yNeg != 0)
std::cout << "(" << x << "," << yNeg << ")\t";
}
}
//vec.insert(vec.begin(), Point(INFINITY, INFINITY));
std::cout << std::endl;
}
else
// Not an ellpitic curve
std::cout << "\na and b are not leading to an ellptic curve.";
return vec;
}
// Test if a and b lead to an EC
int isEC(Value a, Value b)
{
if ((a ^ 3) * 4 + (b ^ 2) * 27 != 0)
return 1;
return 0;
}
// Calculate y^2
Value calcEC(int x, Value a, Value b)
{
return Value(a*x + (x ^ 3) + b);
}
// Test ySqr for square by root
int testSqr(Value ySqr)
{
if ((ySqr ^ ((PRIME - 1) / 2)) == 1 || ySqr == 0)
return 1;
return 0;
}
Tests.hpp
#pragma once
#include "Helper.hpp"
class Tests
{
public:
void twoDAdd(Value a, Value b);
void twoDDoubling(Value a, Value b);
void threeDAdd(Value a, Value b);
void threeDDoubling(Value a, Value b);
};
Tests.cpp
#pragma once
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <math.h>
#include <time.h>
#include "Tests.hpp"
// 2D - Addition
void Tests::twoDAdd(Value a, Value b)
{
std::cout << "\n========== 2D Addition ==========\n";
Point p2D1 = Point(5, 22);
Point p2D2 = Point(16, 27);
std::cout << p2D1 << " + " << p2D2 << " = " << add(p2D1, p2D2, a);
std::cout << std::endl;
}
// 2D - Doubling
void Tests::twoDDoubling(Value a, Value b)
{
std::cout << "\n========== 2D Doubling ==========\n";
Point p2D1 = Point(5, 22);
std::cout << "2 * " << p2D1 << " = " << add(p2D1, p2D1, a);
std::cout << std::endl << std::endl;
}
// 3D - Addition
void Tests::threeDAdd(Value a, Value b)
{
std::cout << "\n========== 3D Addition ==========\n";
std::cout << "All points for a = " << a << ", b = " << b << " and prime = " << PRIME << std::endl;
std::vector<Point> allPoints = findAllPoints(a, b);
std::srand(time(NULL));
int random = std::rand() % (allPoints.capacity() - 1);
Point tmp = allPoints.at(random);
std::cout << std::endl << "Random Point 1: " << tmp << std::endl << std::endl;
tmp.z = 1;
Point p1 = add(tmp, tmp, a);
std::cout << p1 << std::endl;
random = std::rand() % (allPoints.capacity() - 1);
tmp = allPoints.at(random);
std::cout << std::endl << "Random Point 2: " << tmp << std::endl << std::endl;
tmp.z = 1;
Point p2 = add(tmp, tmp, a);
std::cout << p2 << std::endl;
Point p3 = add(p1, p2, a);
std::cout << p3 << std::endl;
}
// 3D - Doubling
void Tests::threeDDoubling(Value a, Value b)
{
std::cout << "\n========== 3D Doubling ==========\n";
std::cout << "All points for a = " << a << ", b = " << b << " and prime = " << PRIME << std::endl;
std::vector<Point> allPoints = findAllPoints(a, b);
int random = std::rand() % (allPoints.capacity() - 1);
Point tmp = allPoints[random];
std::cout << std::endl << "Random Point: " << tmp << std::endl << std::endl;
Point p1 = add(tmp, tmp, a);
std::cout << p1 << std::endl;
tmp.z = 1;
Point p2 = add(tmp, tmp, a);
std::cout << p2 << std::endl;
Point p3 = Point(p2.x / (p2.z ^ 2), p2.y / (p2.z ^ 3));
std::cout << p3 << std::endl;
if (p1 == p3)
std::cout << "Point p1 == Point p3" << std::endl;
else
std::cout << "Point p1 != Point p3" << std::endl;
}
Main.cpp
#pragma once
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <math.h>
#include <time.h>
#include "Tests.hpp"
int PRIME = 29;
void main()
{/*
Value a = 4;
Value b = 20;
std::vector<Point> allPoints = findAllPoints(a, b);
/*
// Tests ausfuehren
twoDAdd(a, b);
twoDDoubling(a, b);
threeDAdd(a, b);
threeDDoubling(a, b);
*/
std::cout << std::endl;
system("pause");
}
Thanks in advance and please excuse my "inperfect" way of coding.
This is happening because you have function definition in header files. Every file that we'll import your header files will have a body function - this is the reason why you have this error. If you want to have the definitions inside header files, you must use inline keyword. Otherwise you need to implement them in .cpp files (the "correct" way of solving this issue).
e.g
// Test if a and b lead to an EC
inline int isEC(Value a, Value b)
{
if ((a ^ 3) * 4 + (b ^ 2) * 27 != 0)
return 1;
return 0;
}
// Calculate y^2
inline Value calcEC(int x, Value a, Value b)
{
return Value(a*x + (x ^ 3) + b);
}
// Test ySqr for square by root
inline int testSqr(Value ySqr)
{
if ((ySqr ^ ((PRIME - 1) / 2)) == 1 || ySqr == 0)
return 1;
return 0;
}
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;
}
I was reading through How can I write a power function myself? and the answer given by dan04 caught my attention mainly because I am not sure about the answer given by fortran, but I took that and implemented this:
#include <iostream>
using namespace std;
float pow(float base, float ex){
// power of 0
if (ex == 0){
return 1;
// negative exponenet
}else if( ex < 0){
return 1 / pow(base, -ex);
// even exponenet
}else if ((int)ex % 2 == 0){
float half_pow = pow(base, ex/2);
return half_pow * half_pow;
//integer exponenet
}else{
return base * pow(base, ex - 1);
}
}
int main(){
for (int ii = 0; ii< 10; ii++){\
cout << "pow(" << ii << ".5) = " << pow(ii, .5) << endl;
cout << "pow(" << ii << ",2) = " << pow(ii, 2) << endl;
cout << "pow(" << ii << ",3) = " << pow(ii, 3) << endl;
}
}
though I am not sure if I translated this right because all of the calls giving .5 as the exponent return 0. In the answer it states that it might need a log2(x) based on a^b = 2^(b * log2(a)), but I am unsure about putting that in as I am unsure where to put it, or if I am even thinking about this right.
NOTE: I know that this might be defined in a math library, but I don't need all the added expense of an entire math library for a few functions.
EDIT: does anyone know a floating-point implementation for fractional exponents? (I have seen a double implementation, but that was using a trick with registers, and I need floating-point, and adding a library just to do a trick I would be better off just including the math library)
I have looked at this paper here which describes how to approximate the exponential function for double precision. After a little research on Wikipedia about single precision floating point representation I have worked out the equivalent algorithms. They only implemented the exp function, so I found an inverse function for the log and then simply did
POW(a, b) = EXP(LOG(a) * b).
compiling this gcc4.6.2 yields a pow function almost 4 times faster than the standard library's implementation (compiling with O2).
Note: the code for EXP is copied almost verbatim from the paper I read and the LOG function is copied from here.
Here is the relevant code:
#define EXP_A 184
#define EXP_C 16249
float EXP(float y)
{
union
{
float d;
struct
{
#ifdef LITTLE_ENDIAN
short j, i;
#else
short i, j;
#endif
} n;
} eco;
eco.n.i = EXP_A*(y) + (EXP_C);
eco.n.j = 0;
return eco.d;
}
float LOG(float y)
{
int * nTemp = (int*)&y;
y = (*nTemp) >> 16;
return (y - EXP_C) / EXP_A;
}
float POW(float b, float p)
{
return EXP(LOG(b) * p);
}
There is still some optimization you can do here, or perhaps that is good enough.
This is a rough approximation but if you would have been satisfied with the errors introduced using the double representation, I imagine this will be satisfactory.
I think the algorithm you're looking for could be 'nth root'. With an initial guess of 1 (for k == 0):
#include <iostream>
using namespace std;
float pow(float base, float ex);
float nth_root(float A, int n) {
const int K = 6;
float x[K] = {1};
for (int k = 0; k < K - 1; k++)
x[k + 1] = (1.0 / n) * ((n - 1) * x[k] + A / pow(x[k], n - 1));
return x[K-1];
}
float pow(float base, float ex){
if (base == 0)
return 0;
// power of 0
if (ex == 0){
return 1;
// negative exponenet
}else if( ex < 0){
return 1 / pow(base, -ex);
// fractional exponent
}else if (ex > 0 && ex < 1){
return nth_root(base, 1/ex);
}else if ((int)ex % 2 == 0){
float half_pow = pow(base, ex/2);
return half_pow * half_pow;
//integer exponenet
}else{
return base * pow(base, ex - 1);
}
}
int main_pow(int, char **){
for (int ii = 0; ii< 10; ii++){\
cout << "pow(" << ii << ", .5) = " << pow(ii, .5) << endl;
cout << "pow(" << ii << ", 2) = " << pow(ii, 2) << endl;
cout << "pow(" << ii << ", 3) = " << pow(ii, 3) << endl;
}
return 0;
}
test:
pow(0, .5) = 0.03125
pow(0, 2) = 0
pow(0, 3) = 0
pow(1, .5) = 1
pow(1, 2) = 1
pow(1, 3) = 1
pow(2, .5) = 1.41421
pow(2, 2) = 4
pow(2, 3) = 8
pow(3, .5) = 1.73205
pow(3, 2) = 9
pow(3, 3) = 27
pow(4, .5) = 2
pow(4, 2) = 16
pow(4, 3) = 64
pow(5, .5) = 2.23607
pow(5, 2) = 25
pow(5, 3) = 125
pow(6, .5) = 2.44949
pow(6, 2) = 36
pow(6, 3) = 216
pow(7, .5) = 2.64575
pow(7, 2) = 49
pow(7, 3) = 343
pow(8, .5) = 2.82843
pow(8, 2) = 64
pow(8, 3) = 512
pow(9, .5) = 3
pow(9, 2) = 81
pow(9, 3) = 729
I think that you could try to solve it by using the Taylor's series,
check this.
http://en.wikipedia.org/wiki/Taylor_series
With the Taylor's series you can solve any difficult to solve calculation such as 3^3.8 by using the already known results such as 3^4. In this case you have
3^4 = 81 so
3^3.8 = 81 + 3.8*3( 3.8 - 4) +..+.. and so on depend on how big is your n you will get the closer solution of your problem.
I and my friend faced similar problem while we're on an OpenGL project and math.h didn't suffice in some cases. Our instructor also had the same problem and he told us to seperate power to integer and floating parts. For example, if you are to calculate x^11.5 you may calculate sqrt(x^115, 10) which may result more accurate result.
Reworked on #capellic answer, so that nth_root works with bigger values as well.
Without the limitation of an array that is allocated for no reason:
#include <iostream>
float pow(float base, float ex);
inline float fabs(float a) {
return a > 0 ? a : -a;
}
float nth_root(float A, int n, unsigned max_iterations = 500, float epsilon = std::numeric_limits<float>::epsilon()) {
if (n < 0)
throw "Invalid value";
if (n == 1 || A == 0)
return A;
float old_value = 1;
float value;
for (int k = 0; k < max_iterations; k++) {
value = (1.0 / n) * ((n - 1) * old_value + A / pow(old_value, n - 1));
if (fabs(old_value - value) < epsilon)
return value;
old_value = value;
}
return value;
}
float pow(float base, float ex) {
if (base == 0)
return 0;
if (ex == 0){
// power of 0
return 1;
} else if( ex < 0) {
// negative exponent
return 1 / pow(base, -ex);
} else if (ex > 0 && ex < 1) {
// fractional exponent
return nth_root(base, 1/ex);
} else if ((int)ex % 2 == 0) {
// even exponent
float half_pow = pow(base, ex/2);
return half_pow * half_pow;
} else {
// integer exponent
return base * pow(base, ex - 1);
}
}
int main () {
for (int i = 0; i <= 128; i++) {
std::cout << "pow(" << i << ", .5) = " << pow(i, .5) << std::endl;
std::cout << "pow(" << i << ", .3) = " << pow(i, .3) << std::endl;
std::cout << "pow(" << i << ", 2) = " << pow(i, 2) << std::endl;
std::cout << "pow(" << i << ", 3) = " << pow(i, 3) << std::endl;
}
std::cout << "pow(" << 74088 << ", .3) = " << pow(74088, .3) << std::endl;
return 0;
}
This solution of MINE will be accepted upto O(n) time complexity
utpo input less then 2^30 or 10^8
IT will not accept more then these inputs
It WILL GIVE TIME LIMIT EXCEED warning
but easy understandable solution
#include<bits/stdc++.h>
using namespace std;
double recursive(double x,int n)
{
// static is important here
// other wise it will store same values while multiplying
double p = x;
double ans;
// as we multiple p it will multiply it with q which has the
//previous value of this ans latter we will update the q
// so that q has fresh value for further test cases here
static double q=1; // important
if(n==0){ ans = q; q=1; return ans;}
if(n>0)
{
p *= q;
// stored value got multiply by p
q=p;
// and again updated to q
p=x;
//to update the value to the same value of that number
// cout<<q<<" ";
recursive(p,n-1);
}
return ans;
}
class Solution {
public:
double myPow(double x, int n) {
// double q=x;double N=n;
// return pow(q,N);
// when both sides are double this function works
if(n==0)return 1;
x = recursive(x,abs(n));
if(n<0) return double(1/x);
// else
return x;
}
};
For More help you may try
LEETCODE QUESTION NUMBER 50
**NOW the Second most optimize code pow(x,n) **
logic is that we have to solve it in O(logN) so we devide the n by 2
when we have even power n=4 , 4/2 is 2 means we have to just square it (22)(22)
but when we have odd value of power like n=5, 5/2 here we have square it to get
also the the number itself to it like (22)(2*2)*2 to get 2^5 = 32
HOPE YOU UNDERSTAND FOR MORE YOU CAN VISIT
POW(x,n) question on leetcode
below the optimized code and above code was for O(n) only
*
#include<bits/stdc++.h>
using namespace std;
double recursive(double x,int n)
{
// recursive calls will return the whole value of the program at every calls
if(n==0){return 1;}
// 1 is multiplied when the last value we get as we don't have to multiply further
double store;
store = recursive(x,n/2);
// call the function after the base condtion you have given to it here
if(n%2==0)return store*store;
else
{
return store*store*x;
// odd power we have the perfect square multiply the value;
}
}
// main function or the function for indirect call to recursive function
double myPow(double x, int n) {
if(n==0)return 1;
x = recursive(x,abs(n));
// for negatives powers
if(n<0) return double(1/x);
// else for positves
return x;
}