Bug in boost::math:quadrature::sinh_sinh? - c++

I was searching for a library for numeric quadrature on the whole real line, i.e. (-inf,inf), and I found boost (version 1.70.0). The function I want to use is boost::math::quadrature:sinh_sinh. To test it I copied the example code from the documentation:
https://www.boost.org/doc/libs/1_70_0/libs/math/doc/html/math_toolkit/double_exponential/de_sinh_sinh.html
and came up with this code:
#include <iostream>
#include <boost/math/quadrature/sinh_sinh.hpp>
using namespace boost::math::quadrature;
int main()
{
sinh_sinh<double> integrator;
auto f = [](double x) { return exp(-x*x); };
double error;
double L1;
double Q = integrator.integrate(f, &error, &L1);
std::cout << Q << "\t" << error << "\t" << L1 << std::endl;
int i = 0;
std::cin >> i; // Just to make sure the console does not close automatically
}
Unfortunately this would not compile because in the documentation the second argument for "integrate" is not a pointer to a Real number, but a normal Real number. So I had to change this line:
double Q = integrator.integrate(f, &error, &L1);
into this one:
double Q = integrator.integrate(f , boost::math::tools::root_epsilon<double>() , &error, &L1);
This compiled and gave good results. But I was curious if I could just write
double Q = integrator.integrate(f);
because all arugments except the first one have default values (and are hence optional to my understanding of c++). Unfortunately this will not compile with Visual-Studio-2013. The error is:
error C2783: "T boost::math::tools::root_epsilon(void)": template-Argument für "T" konnte nicht hergeleitet werden. (in english: it was not able to derive the template-argument for "T" )
Occuring at line 33 of pathTo\boost_1_70_0\boost\math\quadrature\sinh_sinh.hpp
As I am not sure if this error is only related to Visual-Studio I wanted to ask all of you.
Now I wanted to use the working code on my function of interest, which is:
auto f = [](double x) {return pow(abs(x), 3) / cosh(x); };
This function looks like this:
https://www.wolframalpha.com/input/?i=plot+abs(x)%5E3%2Fcosh(x)
and the result of the quadrature should be approx. 23.7:
https://www.wolframalpha.com/input/?i=integrate+abs(x)%5E3%2Fcosh(x)+from+-+inf+to+inf
This program compiles with this function but it crashes, i.e. I get the "The program has stopped working" message from Windows. When I compile in debug mode and run it I get the following error message:
So my question is basically why boost::math::quadrature::sinh_sinh is not able to integrate this function. It decays to zero for plus and minus infinity and it has no singularities.
Is it possible that all these errors occur because I am using Visual-Studio?

Unfortunately, Visual studio is not being nice to you. On your second example, I get the more intelligible error message:
terminate called after throwing an instance of 'boost::wrapexcept<boost::math::evaluation_error>'
what(): Error in function boost::math::quadrature::sinh_sinh<double>::integrate: The sinh_sinh quadrature evaluated your function at a singular point, leading to the value nan.
sinh_sinh quadrature cannot handle singularities in the domain.
If you are sure your function has no singularities, please submit a bug against boost.math
I added a bit of diagnostic code to help out:
auto f = [](double x) {
double y = pow(abs(x), 3) / cosh(x);
if (!std::isfinite(y)) {
std::cout << "f(" << x << ") = " << y << "\n";
}
return y;
};
I get:
f(1.79769e+308) = nan
f(-1.79769e+308) = nan
f(2.01977e+137) = nan
f(-2.01977e+137) = nan
f(7.35294e+106) = nan
f(-7.35294e+106) = nan
Most people are very surprised to learn that sinh-sinh quadrature evaluates their function at such huge argument. It also forces them to think about things they don't usually have to, namely:
IEEE arithmetic can't take limits.
For example, you might know that as $x \to \infty$, $x^2/(1+x^4) \to 0$. But in IEEE floating point arithmetic, for sufficiently large $x$, both the numerator and denominator overflow, and what can be done? The only sensible solution is to just make inf/inf a nan.
In your case, you know that cosh(x) grows faster than pow(|x|, 3), but IEEE doesn't. So you need to explicitly tell the function about the limiting behavior as $x->\infty$ via:
#include <iostream>
#include <cmath>
#include <boost/math/quadrature/sinh_sinh.hpp>
using namespace boost::math::quadrature;
int main()
{
sinh_sinh<double> integrator;
auto f = [](double x) {
double numerator = pow(abs(x), 3);
if (!std::isfinite(numerator)) {
return double(0);
}
return numerator / cosh(x);
};
double error;
double L1;
double tolerance = std::sqrt(std::numeric_limits<double>::epsilon());
double Q = integrator.integrate(f, tolerance, &error, &L1);
std::cout << Q << "\t" << error << "\t" << L1 << std::endl;
}
One final comment: Your integrand is even, so you can use exp_sinh quadrature over [0, inf] and double the result.

Related

How to set width or precision for seconds with fmt library and chrono

I'm trying to format a duration with fmt's chrono impl and specify the precision for the seconds part.
I'm reading the documentation but think i don't understand how to do it; whatever i try, it either doesn't format as expected or the compiler reports an error.
Here's what i tried so far:
#include <chrono>
#include <ratio>
#define FMT_HEADER_ONLY
#include <fmt/chrono.h>
#include <iostream>
int main() {
std::chrono::duration<std::int64_t, std::nano> const d{3601123456789};
std::cout << fmt::format("1a {:%H:%M:%S}\n", d);
std::cout << fmt::format("1_ {: >15%S} <-- width works; precision won't compile\n", d);
// The fmt docs say that "Precision is valid only for std::chrono::duration types with a floating-point representation type."
// The following format doesn't compile with "d" whose ticks are represented as integer.
// It does with "dd" whose ticks are represented as double, but the result is still not as expected.
std::cout << fmt::format("2_ {:.2%S} <-- this is confusing; precision doesn't work\n", dd);
std::cout << fmt::format("2_ {: >15.2%S} <-- width works; precision doesn't\n", dd);
}
(godbolt link)
Edit:
Just checked with std::format on msvc; the results are the same.
To control the width, include an alignment and width specification as the first thing after the ':'. For example "{:>20..." to say align right with width 20.
To control the precision, alter the units of the input duration. For example to have 3 decimal digits, floor<milliseconds>(d):
std::cout << fmt::format("d: {:>20%H:%M:%S}\n", std::chrono::floor<std::chrono::milliseconds>(d));
Output:
d: 00:02:03.456
If you prefer, you can use {:>20%T} in place of {:>20%H:%M:%S}.
For two fractional digits it would be convenient to create a centiseconds duration:
using centiseconds = std::chrono::duration<std::int64_t, std::centi>;
std::cout << fmt::format("d: {:>20%T}\n", std::chrono::floor<centiseconds>(d));
Getting a little winded from chasing the goalposts here ... ;-)
using centiseconds = chrono::duration<int64_t, centi>;
auto d = 3601123456us;
auto m = floor<minutes>(d);
d -= m;
cout << fmt::format("{}:{:%S}", m/1min, floor<centiseconds>(d)) << '\n';
Output:
60:01.12
I got this working for specifying the precision in the format string, but this exits the chrono-type system completely prior to formatting:
auto d = 3601123456.us;
auto m = floor<minutes>(d);
d -= m;
cout << fmt::format("{}:{:0>5.2f}", m/1min, d/1s) << '\n';
Output:
60:01.12

Cannot make sense of this error (ERROR: endpoints do not enclose a minimum (gsl: fsolver.c:126))

I'm working with this code: https://github.com/UCLA-TMD/Ogata. If performs a fast fourier transform.
It integrates the function test, according to some predefined options that are argument of the FBT - FBT(bessel order,some option that doesnt matter,Number of function calls, estimate value where function has its maximum). So far so good.
This code works fine with that function from test, but that's not the function I actually need to use, so I switched to something like exp(x) just to test it, and I no matter what I do I always get:
(It always compiles okay, but when I run the .o file, it gives me this)
gsl: fsolver.c:126: ERROR: endpoints do not enclose a minimum
Default GSL error handler invoked.
Aborted (core dumped)
At first I thought it could be a problem with the function's maximum value Q in FBT, but whenever I change it, it gives me the same error.
Would really appreciate any help.
double test( double x, double width ){ return x*exp(-x/width);} // test function to transform data allows to send anything else to the function
int main( void )
{
//FBT(Bessel Order nu, option of function (always zero), number of function calls, rough estimate where the maximum of the function f(x) is).
FBT ogata0 = FBT(0.0,0,10,1.0); // Fourier Transform with Jnu, nu=0.0 and N=10
double qT = 1.;
double width = 1.;
//call da ogata 0 para função teste
auto begin = std::chrono::high_resolution_clock::now();
double res = ogata0.fbt(std::bind(test, std::placeholders::_1, width),qT);
auto end = std::chrono::high_resolution_clock::now();
std::cout << std::setprecision(30) << " FT( J0(x*qT) x*exp(-x) ) at qT= " << qT << std::endl;
std::cout << std::setprecision(30) << "Numerical transformed = " << res << std::endl;
auto overhead=std::chrono::duration_cast<std::chrono::nanoseconds>(end-begin).count();
std::cout<<"Calc time: "<<overhead<<" nanoseconds\n";
}

Machine Epsilon Calculation Error in C++

I am trying to find the precision and error for the Machine Epsilon. Without using std::numeric_limits. I was given the following formula by my professor y = 1-x/2^n, n > 1. I am assuming that y is the Machine Epsilon, x is 1.0, and n should be the precision.
Here is my header file macEpsFloat.hpp:
class MacEpsFloat
{
public:
int precision(int n);
private:
float e = 1.0; //error
float x = 1.0; //variable
float y = 0.0; //variable
int prec = 0;
};
Here is my macEpsFloat.cpp file
int MacEpsFloat::precision(int n)
{
y = 1 - (x/(1<<n));
if (y == 1.0)
{
prec = n-1;
}
else
{
float error = std::abs(e - y);
std::cout << "Error: " << error << std::endl;
++n;
precision(n);
}
return prec;
}
Here is main.cpp
#include <iostream>
#include "macEpsFloat.hpp"
int main()
{
MacEpsFloat a;
std::cout << "Precision Float: " << a.precision(1) << std::endl;
std::cout << std::endl;
}
The variable y is set equal to 1.0, e is set equal to 1.0, and n is set equal to 1.
I get the following output:
error: 0.5
error: 0.25
error: 0.125
error: 0.0625
error: 0.03125
error: 0.015625
error: 0.0078125
error: 0.00390625
error: 0.00195312
error: 0.000976562
error: 0.000488281
error: 0.000244141
error: 0.00012207
error: 6.10352e-05
error: 3.05176e-05
error: 1.52588e-05
error: 7.62939e-06
error: 3.8147e-06
error: 1.90735e-06
error: 9.53674e-07
error: 4.76837e-07
error: 2.38419e-07
error: 1.19209e-07
error: 5.96046e-08
Precision Float: 24
On the Wiki there are 2 answers for Floats. The first is 1.19209e-07 with a precision of 23, and the other is 5.96046e-08 with a precision of 24.
I see both answers right there, so I know I am on the right track. However, I do not understand why my recursive algorithm divides the problem one more time. I believe the answer I am looking for is 5.96046e-08, or 1.19209e-07 if I multiply it by 2. However, I am not sure what is wrong with my code on why it is executing one more time.
The other issue I am having is this piece of code does not work with doubles for any reason. So I would like to know why that is. Is it better to just throw this into a while loop and see if anything changes? Or do I have the formula wrong for Machine Epsilon?
Any help would be appreciated.
Edit: added compiled code.
EDIT 2: I solved my initial problem, the error was still being calculated, I simply threw the piece of code into the else statement and now it calculates floating points just fine. However, when I change all the types to doubles, it seg faults, I have no idea why it does that.
I found the answer to my problem.
I changed my function to calculate the error inside of the else statement. That way it would give me the error currently rather than after.
I solved the Seg Fault with the Double variable because I did not realize that (1 << n) could only be shifted 32 times due the the size, or actual architecture of my machine. So after the 32 iteration of the recursion, it would throw out random numbers, eventually dividing by zero causing a Segmentation Fault. The code now looks like this:
int MacEpsFloat::precision(int n)
{
y = 1 - (x/(std::pow(2,n)));
if (y == 1.0)
{
prec = n-1;
}
else
{
double error = std::abs(e - y);
std::cout << "Error: " << error << std::endl;
++n;
precision(n);
}
return prec;
}
I did not realize that I could only bit shift so far. Thank you for everyone who helped out!

Casting float to int inconsistent across MinGw and Clang

Using C++, I'm trying to cast a float value to an int using these instructions :
#include <iostream>
int main() {
float NbrToCast = 1.8f;
int TmpNbr = NbrToCast * 10;
std::cout << TmpNbr << "\n";
}
I understand the value 1.8 cannot be precisely represented as a float and is actually stored as 1.79999995.
Thus, I would expect that multiplying this value by ten, would result to 17.99999995 and then casting it to an int would give 17.
When compiling and running this code with MinGW (v4.9.2 32bits) on Windows 7, I get the expected result (17).
When compiling and running this code with CLang (v600.0.57) on my Mac (OS X 10.11), I get 18as a result, which is not what I was expecting but which seems more correct in a mathematical way !
Why do I get this difference ?
Is there a way to have a consistent behavior no matter the OS or the compiler ?
Like Yuushi said in the comments, I guess the rounding rules may differ for each compiler. Having a portable solution on such a topic probably means you need to write your own rounding method.
So in your case you probably need to check the value of the digit after 7 and increment the value or not. Let's say something like:
int main() {
float NbrToCast = 1.8f;
float TmpNbr = NbrToCast * 10;
std::cout << RoundingFloatToInt(TmpNbr) << "\n";
}
int RoundingFloatToInt(const float &val)
{
float intPart, fractPart;
fractpart = modf (val, &intpart);
int result = intPart;
if (fractpart > 0.5)
{
result++;
}
return result;
}
(code not tested at all but you have the idea)
If you need performance, it's probably not great but I think it should be portable.

How does the cout statement affect the O/P of the code written?

#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
int main() {
int t;
double n;
cin>>t;
while(t--)
{
cin>>n;
double x;
for(int i=1;i<=10000;i++)
{
x=n*i;
if(x==ceilf(x))
{
cout<<i<<endl;
break;
}
}
}
return 0;
}
For I/P:
3
5
2.98
3.16
O/P:
1
If my code is:
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
int main() {
int t;
double n;
cin>>t;
while(t--)
{
cin>>n;
double x;
for(int i=1;i<=10000;i++)
{
x=n*i;
cout<<"";//only this statement is added;
if(x==ceilf(x))
{
cout<<i<<endl;
break;
}
}
}
return 0;
}
For the same input O/P is:
1
50
25
The only extra line added in 2nd code is: cout<<"";
Can anyone please help in finding why there is such a difference in output just because of the cout statement added in the 2nd code?
Well this is a veritable Heisenbug. I've tried to strip your code down to a minimal replicating example, and ended up with this (http://ideone.com/mFgs0S):
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
float n;
cin >> n; // this input is needed to reproduce, but the value doesn't matter
n = 2.98; // overwrite the input value
cout << ""; // comment this out => y = z = 149
float x = n * 50; // 149
float y = ceilf(x); // 150
cout << ""; // comment this out => y = z = 150
float z = ceilf(x); // 149
cout << "x:" << x << " y:" << y << " z:" << z << endl;
}
The behaviour of ceilf appears to depend on the particular sequence of iostream operations that occur around it. Unfortunately I don't have the means to debug in any more detail at the moment, but maybe this will help someone else to figure out what's going on. Regardless, it seems almost certain that it's a bug in gcc-4.9.2 and gcc-5.1. (You can check on ideone that you don't get this behaviour in gcc-4.3.2.)
You're probably getting an issue with floating point representations - which is to say that computers cannot perfectly represent all fractions. So while you see 50, the result is probably something closer to 50.00000000001. This is a pretty common problem you'll run across when dealing with doubles and floats.
A common way to deal with it is to define a very small constant (in mathematical terms this is Epsilon, a number which is simply "small enough")
const double EPSILON = 0.000000001;
And then your comparison will change from
if (x==ceilf(x))
to something like
double difference = fabs(x - ceilf(x));
if (difference < EPSILON)
This will smooth out those tiny inaccuracies in your doubles.
"Comparing for equality
Floating point math is not exact. Simple values like 0.2 cannot be precisely represented using binary floating point numbers, and the limited precision of floating point numbers means that slight changes in the order of operations can change the result. Different compilers and CPU architectures store temporary results at different precisions, so results will differ depending on the details of your environment. If you do a calculation and then compare the results against some expected value it is highly unlikely that you will get exactly the result you intended.
In other words, if you do a calculation and then do this comparison:
if (result == expectedResult)
then it is unlikely that the comparison will be true. If the comparison is true then it is probably unstable – tiny changes in the input values, compiler, or CPU may change the result and make the comparison be false."
From http://www.cygnus-software.com/papers/comparingfloats/Comparing%20floating%20point%20numbers.htm
Hope this answers your question.
Also you had a problem with
if(x==ceilf(x))
ceilf() returns a float value and x you have declared as a double.
Refer to problems in floating point comparison as to why that wont work.
change x to float and the program runs fine,
I made a plain try on my laptop and even online compilers.
g++ (4.9.2-10) gave the desired output (3 outputs), along with online compiler at geeksforgeeks.org. However, ideone, codechef did not gave the right output.
All I can infer is that online compilers name their compiler as "C++(gcc)" and give wrong output. While, geeksforgeeks.org, which names the compiler as "C++" runs perfectly, along with g++ (as tested on Linux).
So, we could arrive at a hypothesis that they use gcc to compile C++ code as a method suggested at this link. :)