Advice on method to integrate Bessel functions in C++ [duplicate] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
How can I integrate an equation including bessel functions numerically from "0" to "infinity" in Fortran or/and C?
I did in matlab, but it's not true for larger inputs and after a specific values , the bessel functions give completely wrong results(there is a restriction in Matlab)

There's a large number of analytic results for various integrals of the Bessel functions (see DLMF, Sect. 10.22), including definite integrals over precisely this range. You'd be much better off, and almost certainly faster and more accurate, trying hard to recast your expression into something that's integrable and using an exact result.

Last time I had to do with such things, it was state of the art to do simple integration of the intervals defined by the zero crossings. That is in most cases relatively stable and if the integrand is approaching zero reasonable fast easy to do.
As a starting point for playing around I´ve included a bit of code. Of course you need to work on the convergence detection and error checking. This is no production code but I thought maybe it provides a starting point for you. Its using gsl.
On my iMac this code takes about 2 µs per iteration. It will not become faster by including a hardcoded table for the intervals.
I hope this is of some use for you.
#include <iostream>
#include <vector>
#include <gsl/gsl_sf_bessel.h>
#include <gsl/gsl_integration.h>
#include <gsl/gsl_sf.h>
double f (double x, void * params) {
double y = 1.0 / (1.0 + x) * gsl_sf_bessel_J0 (x);
return y;
}
int main(int argc, const char * argv[]) {
double sum = 0;
double delta = 0.00001;
int max_steps = 1000;
gsl_integration_workspace * w = gsl_integration_workspace_alloc (max_steps);
gsl_function F;
F.function = &f;
F.params = 0;
double result, error;
double a,b;
for(int n=0; n < max_steps; n++)
{
if(n==0)
{
a = 0.0;
b = gsl_sf_bessel_zero_J0(1);
}
else
{
a = n;
b = gsl_sf_bessel_zero_J0(n+1);
}
gsl_integration_qag (&F, // function
besselj0_intervals[n], // from
besselj0_intervals[n+1], // to
0, // eps absolute
1e-4,// eps relative
max_steps,
GSL_INTEG_GAUSS15,
w,
&result,
&error);
sum += result;
std::cout << n << " " << result << " " << sum << "\n";
if(abs(result) < delta)
break;
}
return 0;
}

You can pretty much google and find lots of Bessel functions implemented in C already.
http://www.atnf.csiro.au/computing/software/gipsy/sub/bessel.c
http://jean-pierre.moreau.pagesperso-orange.fr/c_bessel.html
https://msdn.microsoft.com/en-us/library/h7zkk1bz.aspx
In the end, these use the built in types and will be limited to the ranges they can represent (just as MATLAB is). At best, expect 15 digits of precision using double precision floating point representation. So, for large numbers, they will appear to be rounded. eg. 1237846464123450000000000.00000
And, of course, others on Stack Overflow have looked into it.
C++ Bessel function for complex numbers

Related

Encoding numbers in BCD (Casio serial interface) [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am attempting to create a device that talks to a Casio fx-9750 calculator through its serial port with an Arduino. I have figured out how to receive values and decode the BCD, but I'm stuck on how to create the required values from a float (to transmit back).
The calculator sends a data packet, which has an exponent value, several data values, and a byte that contains information about negativity, imaginary parts, etc. Each data value is worth one hundredth of the previous one, so the first is the amount of 10s, the next the amount of 0.1s, the next the amount of 0.001s, etc. This continues on until the 0.0000000000001s, though this is out of the range of what I'll really need, so that level of accuracy is not really important to me. The output of my receiving program looks like this:
Exponent: 1
10s: 1
0.1s: 23
0.001s: 40
This represents 12.34.
The general equation I worked out was: (let a=10s, b=0.1s, e=exponent etc)
((a*10)+(b*0.1)+(c*0.001))*10^(E-1)
If the exponent were to change to two:
Exponent: 2
10s: 1
0.1s: 23
0.001s: 40
This would represent 123.4
This method of dropping by hundredths each time is presumably used because they can store two digits in each byte with BCD, so it is most efficient to let each row have two digits as each row is stored as one byte.
I have come up with an equation that can calculate the exponent by counting the amount of digits before the decimal point and subtracting two, however this seems messy as it involves strings. I think a purely mathematical solution would be more elegant, if it is possible.
What is the fastest and simplest way to go from a normal number (e.g. 123.4) into this arrangement?
A solution in Arduino language would be greatly appreciated, but any insight whatsoever into the mathematical process needed would be equally valued.
Edit regarding floats:
I should clarify - I will be dealing with floats in other parts of my program and would like my inputted values to be compatible with numbers of any size (within reason, as stated before). I have no problem with multiplying them to be ints or casting them as other datatypes.
Hah, that was fun!
#include <stdio.h>
#include <assert.h>
#include <math.h>
#include <float.h>
struct num_s {
// exponent
int e;
// v[0] is *10
// v[1] is *0.01
// v[2] is *0.0001
// and so on...
// to increase precision increase array count
int v[6];
};
#define NUM_VALSCNT (sizeof(((struct num_s*)0)->v)/sizeof(((struct num_s*)0)->v[0]))
// creates num_s object from a double
struct num_s num_create(double v) {
struct num_s t;
// find exponent so that v <= 10
t.e = 0;
while (fabs(v) >= 10.0) {
++t.e;
v /= 10.0;
}
// for each output number get the integral part of number
// then multiply the rest by 100 and continue
for (size_t i = 0; i < sizeof(t.v) / sizeof(t.v[0]); ++i) {
const double tmp = fmod(v, 1.0);
t.v[i] = v - tmp;
v = tmp * 100;
}
return t;
}
// converts back from num object to double
double num_get(struct num_s t) {
double denom = 10;
double ret = 0;
for (size_t i = 0; i < sizeof(t.v) / sizeof(t.v[0]); ++i) {
ret += denom * t.v[i];
denom /= 100;
}
return ret * pow(10, t.e - 1);
}
void num_println(struct num_s t) {
printf("%f =", num_get(t));
for (size_t i = 0; i < sizeof(t.v) / sizeof(t.v[0]); ++i) {
printf(" %d", t.v[i]);
}
printf(" %d\n", t.e);
}
// returns the precision of numbers
// the smallest number we can represent in num object
double num_precision(void) {
return pow(0.1, (NUM_VALSCNT - 1) * 2) * 10;
}
int num_unittests(void) {
const double tests[][3] = {
{ 123.49, 123.5, 123.51, }
};
for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) {
const double tmp = num_get(num_create(tests[i][1]));
if (!(tests[i][0] <= tmp && tmp <= tests[i][2])) {
return i + 1;
}
}
return 0;
}
int main() {
num_println(num_create(12.3456789));
num_println(num_create(123.5));
num_println(num_create(12.35));
printf("%d\n", num_unittests());
return 0;
}

Increase precision in SelfAdjointEigenSolver in Eigen

I am trying to determine the eigenvalues and eigenvectors of a sparse array in Eigen. Since I need to compute all the eigenvectors and eigenvalues, and I could not get this done using the unsupported ArpackSupport module working, I chose to convert the system to a dense matrix and compute the eigensystem using SelfAdjointEigenSolver (I know my matrix is real and has real eigenvalues). This works well until I have matrices of size 1024*1024 but then I start getting deviations from the expected results.
In the documentation of this module (https://eigen.tuxfamily.org/dox/classEigen_1_1SelfAdjointEigenSolver.html) from what I understood it is possible to change the number of max iterations:
const int m_maxIterations
static
Maximum number of iterations.
The algorithm terminates if it does not converge within m_maxIterations * n iterations, where n denotes the size of the matrix. This value is currently set to 30 (copied from LAPACK).
However, I do not understand how do you implement this, using their examples:
SelfAdjointEigenSolver<Matrix4f> es;
Matrix4f X = Matrix4f::Random(4,4);
Matrix4f A = X + X.transpose();
es.compute(A);
cout << "The eigenvalues of A are: " << es.eigenvalues().transpose() << endl;
es.compute(A + Matrix4f::Identity(4,4)); // re-use es to compute eigenvalues of A+I
cout << "The eigenvalues of A+I are: " << es.eigenvalues().transpose() << endl
How would you modify it in order to change the maximum number of iterations?
Additionally, will this solve my problem or should I try to find an alternative function or algorithm to solve the eigensystem?
My thanks in advance.
Increasing the number of iterations is unlikely to help. On the other hand, moving from float to double will help a lot!
If that does not help, please, be more specific on "deviations from the expected results".
m_maxIterations is a static const int variable, and as such it can be considered an intrinsic property of the type. Changing such a type property usually would be done via a specific template parameter. In this case, however, it is set to the constant number 30, so it's not possible.
Therefore, you're only choice is to change the value in the header file and recompile your program.
However, before doing that, I would try the Singular Value Decomposition. According to the homepage, its accuracy is "Excellent-Proven". Moreover, it can overcome problems due to numerically not completely symmetric matrices.
I solved the problem by writing the Jacobi algorithm adapted from the Book Numerical Recipes:
void ROTATy(MatrixXd &a, int i, int j, int k, int l, double s, double tau)
{
double g,h;
g=a(i,j);
h=a(k,l);
a(i,j)=g-s*(h+g*tau);
a(k,l)=h+s*(g-h*tau);
}
void jacoby(int n, MatrixXd &a, MatrixXd &v, VectorXd &d )
{
int j,iq,ip,i;
double tresh,theta,tau,t,sm,s,h,g,c;
VectorXd b(n);
VectorXd z(n);
v.setIdentity();
z.setZero();
for (ip=0;ip<n;ip++)
{
d(ip)=a(ip,ip);
b(ip)=d(ip);
}
for (i=0;i<50;i++)
{
sm=0.0;
for (ip=0;ip<n-1;ip++)
{
for (iq=ip+1;iq<n;iq++)
sm += fabs(a(ip,iq));
}
if (sm == 0.0) {
break;
}
if (i < 3)
tresh=0.2*sm/(n*n);
else
tresh=0.0;
for (ip=0;ip<n-1;ip++)
{
for (iq=ip+1;iq<n;iq++)
{
g=100.0*fabs(a(ip,iq));
if (i > 3 && (fabs(d(ip))+g) == fabs(d[ip]) && (fabs(d[iq])+g) == fabs(d[iq]))
a(ip,iq)=0.0;
else if (fabs(a(ip,iq)) > tresh)
{
h=d(iq)-d(ip);
if ((fabs(h)+g) == fabs(h))
{
t=(a(ip,iq))/h;
}
else
{
theta=0.5*h/(a(ip,iq));
t=1.0/(fabs(theta)+sqrt(1.0+theta*theta));
if (theta < 0.0)
{
t = -t;
}
c=1.0/sqrt(1+t*t);
s=t*c;
tau=s/(1.0+c);
h=t*a(ip,iq);
z(ip)=z(ip)-h;
z(iq)=z(iq)+h;
d(ip)=d(ip)- h;
d(iq)=d(iq) + h;
a(ip,iq)=0.0;
for (j=0;j<ip;j++)
ROTATy(a,j,ip,j,iq,s,tau);
for (j=ip+1;j<iq;j++)
ROTATy(a,ip,j,j,iq,s,tau);
for (j=iq+1;j<n;j++)
ROTATy(a,ip,j,iq,j,s,tau);
for (j=0;j<n;j++)
ROTATy(v,j,ip,j,iq,s,tau);
}
}
}
}
}
}
the function jacoby receives the size of of the square matrix n, the matrix we want to calculate the we want to solve (a) and a matrix that will receive the eigenvectors in each column and a vector that is going to receive the eigenvalues. It is a bit slower so I tried to parallelize it with OpenMp (see: Parallelization of Jacobi algorithm using eigen c++ using openmp) but for 4096x4096 sized matrices what I did not mean an improvement in computation time, unfortunately.

sqrt Matlab and C++ numerical differences

I witness numerical differences between Matlab and C++ code. Discrepancy seems to stem from different output for sqrt method in Matlab and C++. For very small numbers (< 10-5) it seems that relative difference is quite big.
Which approach would you suggest to
make sure differences come from sqrt
tune the cpp code as to replicate to float precision the Matlab code
EDIT
I add more precision about the code.
float* buttonVar = new float[nBut];
for (int_T ibut = 0; ibut < nBut; ibut++)
{
for (int_T id = start_idx; id <= stop_idx; id++)
{
inputArray[id - start_idx] = arr[ibut * nDepth + id];
}
reduceVector(inputArray, reducedArray, inputarray_size, d1, d2);
buttonMean[ibut] = 0;
buttonVar[ibut] = 0;
for (int_T id = 0; id < min(nd, nDepth); id++)
{
buttonMean[ibut] += reducedArray[id] / float(nd);
}
for (int_T id = 0; id < min(nd, nDepth); id++)
{
buttonVar[ibut] += (reducedArray[id] - buttonMean[ibut])
*(reducedArray[id] - buttonMean[ibut]);
}
buttonVar[ibut] = sqrtf(buttonVar[ibut] / float(nd));
}
In Matlab, I am converting to single the number to be sqrt. Discrepancy in the code appears in buttonVar.
Final results that are compared in Google Tests are results from several more operations with no other call to mathematics functions. These additional operations are in methods which were thouroughly Google Tested, and there is perfect match to float precision of outputs for these tests.
Numerical difference in buttonVar is up to 15% relative difference (=100*abs(cpp_res - matlab_res)/matlab_res. Significant relative difference occurs when buttonVar his of order of magnitude 10e-6.
Converting to double in C++ inside the computation solves the difference problem. We reach a very satisfactory match after converting to double.

I was trying to write a Greedy Algorithm in C [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Does this make any sense?
I got stuck in here with 4 errors and it is because I didn't declared the ints q,d,n,p. But if I do so it'll keep sending me more errors.
There might be something about having mixed ints and floats.
#include <cs50.h>
#include <stdio.h>
int main(void)
{
{
printf("O hai! ");
}
float valueTotal, quarter, valueQuarter, dime, valueDime,nickel, valueNickel, penny, valuePenny;
do
{
printf("How much change is owed?\n");
valueTotal = GetFloat();
}
while (valueTotal <= 0);
for (float quarter = 0; valueTotal >= 0.25; quarter--)
{
valueQuarter = valueTotal - ( q * 0.25);
}
for (float dime = 0; valueQuarter >= 0.10; dime--)
{
valueDime = valueQuarter - ( d * 0.10);
}
for (float nickel = 0; valueDime >= 0.05; nickel--)
{
valueNickel = valueDime - ( n * 0.05);
}
for (float penny = 0; valueNickel >= 0.01; penny--)
{
valuePenny = valueNickel - ( p * 0.01);
}
printf("q+d+n+p\n");
}
I didn't declared the ints q,d,n,p.
This is exactly your problem - at least one of them, anyways. If these variables are undeclared, how in the world is the program/code supposed to evaluate something like q * 0.25 ? If I said "Hey man, what is x times 0.25?" You'd have absolutely no idea, or tell me that the answer depends on x. The same goes with this code.
You said:
But if I do so it'll keep sending me more errors.
I'm assuming you also need to initialize them (or, in layman's terms, set them equal to something ie. q = 0)
Also, none of your loop conditions are actually changing.... meaning they're infinitely looping. Make sure that the code inside your loop is actually helping you reach the goal of satisfying the loop condition; for example:
for (float quarter = 0; valueTotal >= 0.25; quarter--)
{
valueQuarter = valueTotal - ( q * 0.25);
}
valueTotal is ALWAYS going to be greater than 0.25 (if it is less than 0.25 to begin with) since you are never changing it at all.

Generating random reals uniformly using Boost [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 9 years ago.
Improve this question
I am trying to generate some uniform real numbers for a Monte Carlo integration but the routine I build was returning some really strange values. Upon closer inspection I notices that Boost was returning some crazy looking random numbers e.g.:
temp = -0.185276
temp = -0.864523
temp = -0.0942081
temp = -0.164991
temp = -0.873013
temp = -0.0311322
temp = -0.0866241
temp = -0.778966
temp = -0.367641
temp = -0.691833
temp = 5.66499e-310
temp = 9.42007e-311
temp = 6.29821e-310
temp = 5.80603e-310
temp = 8.82973e-311
temp = 6.73679e-310
temp = 6.35094e-310
temp = 1.53691e-310
temp = 4.39696e-310
temp = 2.14277e-310
Whilst these numbers are technically still reals generated between the bounds -1 and 1 I would prefer it if they weren't quite so small!
My implementation of the call to boost is in a function which is called multiple times (for different bounding values) as follows:
// Define Boost typedefs
typedef boost::mt19937 Engine;
typedef boost::uniform_real<double> Distribution;
typedef boost::variate_generator <Engine, Distribution> Generator;
int main (void) {
...
Integral = MCRecursion(...);
...
return 0;
}
double MCRecursion (int Count, double Lower, double Upper, double (*Integrand)(double)) {
// Define Boost objects
Engine Eng;
Distribution Dist (Lower, Upper);
Generator RandomGen (Eng, Dist);
Eng.seed(time(0));
// Variables for Monte Carlo sample sums
double Sum = 0.0;
double temp;
for (int i = 0; i < Count; i++) {
temp = RandomGen();
std::cout << " temp = " << temp << std::endl;
Sum += Integrand(temp);
}
return (Upper - Lower) * Sum / Count;
}
I assume the problem is something with my implementation but I can't find any errors. Any and all help appreciated!
Cheers,
Jack
EDIT
Code for calling MCRecursion:
The Code I am writting runs a Monte Carlo on the entire domain I am interested in [Lower, Upper] and then looks again at the left half of the whole domain and the right half of the domain.
e.g. if we were integrating f(x) between -a and a I calculate the full integral using:
double FullDomain = MCRecursion (1e5, LowerBound, UpperBound, f);
double Centre = (Upper + Lower) / 2.0;
double LeftHalf = MCRecursion (1e5, LowerBound, Centre, f);
double RightHalf = MCRecursion (1e5, Centre, UpperBound, f);
and I then look at the uncertainty by calculating:
double difference = fabs(FullDomain - LeftHalf - Righthalf);
to see if more samples is 'worth it' in some sense
Jack
Based on the pastebin the questioner posted in the comments:
This is not a problem with the random library but rather a simple programming error. Compiling the code throws the warning:
../src/Test.cpp: In function ‘double AdaptiveMCRecursion(double, double, double, double, int, double, double (*)(double))’:
../src/Test.cpp:100:72: warning: ‘Right’ is used uninitialized in this function [-Wuninitialized]
double Right = MCSample (Count, Central, Right, Integrand);
So all the behaviour from that line on is basically undefined. Especially it results in calling the function MCSample with an undetermined Upper parameter. So your result is not unexpected. You are actually lucky the program runs at all.