Can I use a `mpfr_t` as both input and output argument? - c++

The question is very simple and direct, but I could not find an answer on the documentation. If I have
mpfr_t a, b;
Can I do something like
mpfr_add(a, a, b, rnd);
This would compute the sum of a and b and store the result on a. I don't know if this results in an aliasing problem, potentially invalidating the result, or if this is fine.

Never mind, it's in section 4.3 of the linked document.
MPFR allows you to use the same variable for both input and output in the same expression. For example, the main function for floating-point multiplication, mpfr_mul, can be used like this: mpfr_mul (x, x, x, rnd). This computes the square of x with rounding mode rnd and puts the result back in x.

Related

Saving a complex number in a variable

I am trying to perform this computation which results in a complex number. However, C++ gives me "NaN".
double Q, r, Theta;
Q=-0.043543950754930;
r=0.009124131609174;
Theta=acos(r/sqrt(pow(-Q,3)));
// result must be (0.00000000000000 + 0.0911033580003565i)
Yes, by using the std::complex type:
#include <complex>
#include <iostream>
int main()
{
std::complex<double> Q = -0.043543950754930;
std::complex<double> r = 0.009124131609174;
std::complex<double> Theta = std::acos(r / std::sqrt(std::pow(-Q, 3)));
std::cout << Theta << '\n';
}
Note that the complex functions return values in specific ranges. You may have to adjust for this if you are looking for a specific answer.
I am trying to perform this computation which results in a complex number.
All the variables in the posted snippet are of type double, so that the compiler has to use the overloads of std::acos, std::sqrt and std::pow accepting parameters of type double and returning double values.
In particular, the function double std::acos(double arg)[1]:
If a domain error occurs, an implementation-defined value is returned (NaN where supported).
[...]
Domain error occurs if arg is outside the range [-1.0, 1.0].
Given the values of R and Q in the posted example, the value of arg is greater than 1, causing a domain error.
To obtain a complex value, the OP should use (or cast to) variables of type std::complex<double>, so that the "correct" overloads of the mathematical functions are chosen, as well as the expected return type.
They could also implement different numerical algorithms (one for real, one for complex values) and let the program choose the right path based upon the value of some "discriminant" variable. E.g. a cubic equation has three complex solutions in general, but those can either be three different real values or three real values (two coincident) or one real value and two complex conjugate ones. A program might use different methods instead of a single general (all complex) one.
[1] Quotes from https://en.cppreference.com/w/cpp/numeric/math/acos, emphasis mine.

Overcoming an n^2 runtime program

Is there a way to overcome a nested loop recursion in C++11? My program has a slow runtime. Or rather, is there a more efficient way to solve for the following formula z=|a-b|*|x-y|,with a, b, x and y being elements in a 10000 integer array?
Here is the code:
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;
ifstream in("int.in");
int main()
{
long long n, n1, z, x, y, in2=0;
in>>n
long long l[n], p[n];
for(x=0;x!=n;x++)
in>>l[x]>>p[x];
for(x=0;x!=n;x++)
{
for(y=x+1;y<n;y++)
{
ineq+=(abs(l[x]-l[y])*abs(p[x]-p[y]))); //executes slow
/*n1=l[x]-l[y]; //Alternative algorithm
if(n1<0)
n1*=-1;
z=p[x]-p[y];
if(z<0)
z*=-1;
in2+=n1*z;*/
}
}
cout<<in2<<"\n";
}
I tried to change the data types to short int, long, long long and unsigned, but it either dumps garbage values or executes ``Segmentation Core Fault` errors.
For the absolute value formula, I originally tried using a hard-coded approach (commented out), but it seemingly outputs garbage values. I've also tried to optimize the abs solution with the abs() function ineq+=abs(l[x]-l[y])*abs(p[x]-p[y]));, but it seems to execute slower. I do not know of any other optimizations I can implement, so please do recommend some.
Linux-friendly solution preferred. Thank you.
Side Note: the values of a, b, x and y are all within the range 1<=a,b,x,y<=10000.
Side Note: this program reads from a file "int.in", takes the first integer (the number of items) and reads each new line by pair (l[x] and p[x] are pairs).
Side Note: I also tried using only a multidimensional array, but I read somewhere that a one dimension array is in the CPU cache, while multidimensions are scattered in the memory and is slower.
The problem can be drawn in another way: you're looking for c and d (both positive) in the equation z=c*d (of course c is |a-b| and d is |x-y|).
So first order your arrays. Then look for solution of z=c*d then find which a and b make c == a - b true and x and y that make d == x - y true.
Once it's done you've got all the values that makes your equation true since abs(a-b) is the same as abs(b-a)

Function of a letter in C++

I have the following expression:
A = cos(5x),
where x is a letter indicating a generic parameter.
In my program I have to work on A, and after some calculations I must have a result that must still be a function of x , explicitly.
In order to do that, what kind of variable should A (and I guess all the other variables that I use for my calculations) be?
Many thanks to whom will answer
I'm guessing you need precision. In which case, double is probably what you want.
You can also use float if you need to operate on a lot of floating-point numbers (think in the order of thousands or more) and analysis of the algorithm has shown that the reduced range and accuracy don't pose a problem.
If you need more range or accuracy than double, long double can also be used.
To define function A(x) = cos(5 * x)
You may do:
Regular function:
double A(double x) { return std::cos(5 * x); }
Lambda:
auto A = [](double x) { return std::cos(5 * x); };
And then just call it as any callable object.
A(4.); // cos(20.)
It sounds like you're trying to do a symbolic calculation, ie
A = magic(cos(5 x))
B = acos(A)
print B
> 5 x
If so, there isn't a simple datatype that will do this for you, unless you're programming in Mathematica.
The most general answer is "A will be an Expression in some AST representation for which you have a general algebraic solver."
However, if you really want to end up with a C++ function you can call (instead of a symbolic representation you can print as well as evaluating), you can just use function composition. In that case, A would be a
std::function<double (double )>
or something similar.

Is this reinterpret_cast OK to do

I am a EE, not a code expert, so please bear with me here.
I am using Embarcadero C++ Builder (XE3).
I have an FFT algorithm which does a fair number of operations on complex numbers. I found out that if I bypass Embarcadero's complex math library, and do all the calculations in my own code, my FFT will run about 4.5 times faster. The 4 operations shown here all require an inordinate amount of time.
#include <dinkumware\complex>
#define ComplexD std::complex<double>
ComplexD X, Y, Z, FFTInput[1024];
double x, y;
Z = X * Y;
x = X.real();
y = X.imag();
Z = ComplexD(x,y);
Replacing the multiplication with my own cross multiply cut my execution times in half. My concern however is with the way I am accessing the real and imaginary parts of the input array. I am doing this:
double *Input;
Input = reinterpret_cast<double *>(FFTInput);
// Then these statements are equivalent.
x = FFTInput[n].real();
y = FFTInput[n].imag();
x = Input[2*n];
y = Input[2*n+1];
Doing this cut my execution times in half again, but I don't know if this reinterpret_cast is a wise thing to do. I could change the input array to two doubles instead of a complex, but I am using this FFT in numerous programs and don't want to rewrite everything.
Is this reinterpret_cast OK, or will I have memory problems? Also, is there a way to get the Embarcadero complex math functions to run faster? And finally, although its not terribly important to me, is this reinterpret_cast portable?
This is allowed. Whilst this isn't a standard quote, cppreference has this to say:
For any pointer to an element of an array of complex numbers p and any
valid array index i, reinterpret_cast<T*>(p)[2*i] is the real part of
the complex number p[i], and reinterpret_cast<T*>(p)[2*i + 1] is the
imaginary part of the complex number p[i].
I will look for the quote from the actual standard soon.
From here it says at the bottom of the page:
For any complex number z, reinterpret_cast<T(&)[2]>(z)[0] is the real part of z and reinterpret_cast<T(&)[2]>(z)[1] is the imaginary part of z.
For any pointer to an element of an array of complex numbers p and any valid array index i, reinterpret_cast<T*>(p)[2*i] is the real part of the complex number p[i], and reinterpret_cast<T*>(p)[2*i + 1] is the imaginary part of the complex number p[i]. (Since C++11)
These requirements essentially limit implementation of each of the three specializations of std::complex to declaring two and only two non-static data members, of type value_type, with the same member access, which hold the real and the imaginary components, respectively.
So what you are doing is guaranteed to work in C++11, but not before that. It may still work with your library's implementation, but you need to check that your library's implementation does not define any more non-static data members as per the third paragraph.

out put of the cross product

i am trying to get the 'cross product' of two vectors. these two vectors represent two planes. so, my vectors are as a1,b1,-1 and a2,b2,-1. (I used, my plane equation as ax+by-z+d=0).
this was my defined function to get the cross product;
vector<double> cross_vector(vector<double> plane1,vector<double> plane2){
vector<double> cross_product;
double a1=plane1.at(0); double a2=plane2.at(0);
double b1=plane1.at(1); double b2=plane2.at(1);
int c1,c2=-1;
double cross_a=(b1*c2)-(b2*c1);
double cross_b=(a2*c1)-(a1*c2);
double cross_c=(a1*b2)-(a2*b1);
cross_product.push_back(cross_a);
cross_product.push_back(cross_;
cross_product.push_back(cross_c);
return cross_product;
}
for the result i got as below result for different plane combinations;
523554 -1.3713e+006 -0.00160687
556340 -1.43908e+006 0.00027957
-568368 1.46225e+006 -0.00034963
143455 -380017 -0.00027957
i can't understand the values like 1.46225e+006? is there any wrong with my function?
i know, my resultant cross vector should be directed exactly horizontal. So, could you also tell me how can i check whether my cross-vector is horizontal or not?
hope your advices.
int c1,c2=-1;
This leaves c1 uninitialized. Use:
int c1=-1, c2=-1;
The math looks correct. Placing a quick A = <1,0,0> and B = <0, 1, 0> gave a reasonable result on the backside of <0, 0, 1>. The e notatin represent the number times 10 to the power after the e. So those might be reasonable as well, but it's hard to say as from your example I can't tell what your input values were. I wouldn't personnaly return the value directly though - I'd prefer to return as a reference or pointer to prevent needless copying. Also, as the above poster mentioned, you do have an initialized var.