Overload boost::multiprecision::pow with fixed precision - c++

The following code
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/cpp_int.hpp>
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>, boost::multiprecision::et_off> float_50;
int main()
{
float_50 a = boost::multiprecision::pow((float_50)5, (float_50)10); // works
double b = boost::multiprecision::pow((double)5, (double)10); // doesn't work
//double b = boost::multiprecision::pow<double>((double)5, (double)10); // Why can't be overloaded?
return 0;
}
won't compile since boost::multiprecision::pow does not recognised fixed precision type. What is the usual solution for this? I'd rather have a single pow function which accepts both multi and fixed precision types. It is strange to me that boost constants, for instance, have template definitions so
boost::math::constants::pi<double>()
boost::math::constants::pi<float_50>()
work fine. Shouldn't boost::multiprecision::pow also be overloaded?

The solution is to leave off the namespace.
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/cpp_int.hpp>
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>, boost::multiprecision::et_off> float_50;
int main()
{
float_50 a = pow((float_50)5, (float_50)10);
double b = pow(5., 10.);
return 0;
}

There is no way for a single function to handle arguments of different types. You need a separate function for each supported parameter set. The function may be autogenerated from a template—but pow does not seem to be a candidate for a template implementation.

Related

C++ using math.h for sin returns "too many arguments in function call"

The user inputs a number, which is converted from characters to a double (the number is is 0.0 before input where it is updated to any number). I should then be able to convert this and find the sin value. At the moment I get an error "too many arguments in function call". I understand I need to convert the users input into radian but I can't seem to find a work around.
Here is a snippet of the code (my Pi and Logarithm functions work okay)
Using public as the function is accessed from another class.
I've looked at a lot of sources but here are two that helped:
http://www.cplusplus.com/reference/cmath/sin/
http://www.cplusplus.com/forum/beginner/144006/
I know I'm missing something obvious but I can't seem to put my finger on it.
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string>
#include <cmath>
class calculations {
public: double sin()
{
double radian = ((number1 * 180) / 2);
result = sin(radian);
return result;
}
}
Change the call to std::sin(radian). As written it's trying to call your sin function. Yours doesn't take any arguments, and it's being called with one argument, which is what the compiler is complaining about.

Using boost multiprecision with trigonometric function

Consider the following code which creates a multiprecision floating-point number 'a' by using boost.
How do I use boost library to invoke trigonometric functions?
For example, I hope to calculate sin(a).
#include <iostream>
#include "boost/multiprecision/cpp_bin_float.hpp"
using namespace std;
using namespace boost::multiprecision;
typedef number<backends::cpp_bin_float<24, backends::digit_base_2, void, boost::int16_t, -126, 127>, et_off> float32;
int main (void) {
float32 a("0.5");
return 0;
}
It looks like there is a limitation in the library. When the precision is dropped too low, the sin implementation no longer compiles.
Some intermediate calculations are being done in double precision. The assignment into the result type would be lossy and hence doesn't compile.
Your chosen type actually corresponds to cpp_bin_float_single. That doesn't compile.
As soon as you select cpp_bin_float_double (precision 53 binary digits) or higher, you'll be fine.
I suppose this limitation could be viewed as a bug in some respects. You might report it to the library devs, who will be able to judge whether the related code could use single-precision floats there without hurting the convergence of the sin approximation.
#include <boost/multiprecision/cpp_bin_float.hpp>
#include <iostream>
using namespace std;
using namespace boost::multiprecision;
int main() {
cpp_bin_float_100 a = 1;
cout << setprecision(50) << endl;
cout << sin(a) << endl;
return 0;
}
I've verified digits with Wolfram Mathematica and they are correct:

Lambda function generating "ambiguous function call" error despite lack of ambiguity

So I'm trying to deal with a program that can accept a function that either returns a vector of doubles, or just returns a single double.
Unfortunately, when I try to compile this (MSVC2010) I get the following error:
ambiguous call to overloaded function
Is there anything I'm doing that's obviously wrong? I need a way to differentiate between the two, and I'm trying to avoid hackish template metaprogramming.
#include <iostream>
#include <functional>
#include <vector>
std::vector<double> foo(std::function<std::vector<double>(unsigned int) > a){return a(10);}
double foo(std::function<double(unsigned int) > a){return a(11);}
int main(){
foo([](unsigned int)->double{return 12.0;});
return 0;
}
As you can see, my return type is explicitly declared to be a double, yet it can't decide which version of foo to call.
Should I just run back to function pointers?
Thank you very much for your time!

How to convert from boost::multiprecision::cpp_int to cpp_dec_float<0> (rather than to cpp_dec_float_50, etc.)?

As is made clear in the Boost Multiprecision library documentation, it is straightforward to convert from a boost::multiprecision::cpp_int to a boost::multiprecision::cpp_dec_float:
// Some interconversions between number types are completely generic,
// and are always available, albeit the conversions are always explicit:
cpp_int cppi(2);
cpp_dec_float_50 df(cppi); // OK, int to float // <-- But fails with cpp_dec_float<0>!
The ability to convert from a cpp_int to a fixed-width floating-point type (i.e., a cpp_dec_float_50) gives one hope that it might be possible to convert from a cpp_int to an arbitrary-width floating-point type in the library - i.e., a cpp_dec_float<0>. However, this doesn't work; the conversion fails for me in Visual Studio 2013, as the following simple example program demonstrates:
#include <boost/multiprecision/number.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
int main()
{
boost::multiprecision::cpp_int n{ 0 };
boost::multiprecision::cpp_dec_float<0> f{ n }; // Compile error in MSVC 2013
}
It does succeed to convert to cpp_dec_float_50, as expected, but as noted, I am hoping to convert to an arbitrary precision floating point type: cpp_dec_float<0>.
The error appear in the following snippet of code from the internal Boost Multiprecision code, in the file <boost/multiprecision/detail/default_ops.hpp>:
template <class R, class T>
inline bool check_in_range(const T& t)
{
// Can t fit in an R?
if(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded
&& (t > (std::numeric_limits<R>::max)()))
return true;
return false;
}
The error message is:
error C2784:
'enable_if::result_type,detail::expression::result_type>,bool>::type
boost::multiprecision::operator >(const
boost::multiprecision::detail::expression
&,const
boost::multiprecision::detail::expression &)' :
could not deduce template argument for 'const
boost::multiprecision::detail::expression &'
from 'const next_type'
Might it be possible to convert a boost::multiprecision::cpp_int to a boost::multiprecision::cpp_dec_float<0> (rather than converting to a floating-point type with a fixed decimal precision, as in cpp_dec_float_50)?
(Note that in my program, only one instance of the floating-point number is instantiated at any time, and it is updated infrequently, so I am fine with having this one instance take up lots of memory and take a long time to support really huge numbers.)
Thanks!
I don't have much experience with Boost Multiprecision, but it seems to me that the template class cpp_dec_float<> is what they call a backend, and you need to wrap it in a number<> adaptor in order to use it as an arithmetic type.
Here's my take on it: Live On Coliru
#include <boost/multiprecision/number.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <iostream>
namespace mp = boost::multiprecision;
int main()
{
using Int = mp::cpp_int;
// let's think of a nice large number
Int n = 1;
for (Int f = 42; f>0; --f)
n *= f;
std::cout << n << "\n\n"; // print it for vanity
// let's convert it to cpp_dec_float
// and... do something with it
using Dec = mp::number<mp::cpp_dec_float<0> >;
std::cout << n.convert_to<Dec>();
}
Output:
1405006117752879898543142606244511569936384000000000
1.40501e+51
If convert_to<> is allowed, then the explicit conversion constructor will also work, I expect:
Dec decfloat(n);

Change all the int type to another type using #define for large program

I want to change all my int type in my program to support arbitrary position integer. I chose to use GMP.
I am thinking about is it possible to do a #define to replace all int to mpz_class.
I start by a small program
#include <iostream>
#define int long long int
using namespace std;
int main(){
// .... code
}
The compiler is already complaining about main have to return an int type.
Is it possible to add exception to #define? or this is a really bad idea to do so?
Redefining a keyword is prohibited iff you include any standard headers. Here, you included <iostream> so your program is ill-formed.
Otherwise, knock yourself out! Wait, no, don't, because this would still be really silly.
Instead, refactor your code to use some new type called, say, my_integer (but with a much better name):
typedef int my_integer;
Then, when you want to change from int to mpz_class, you just change the definition of my_integer:
typedef mpz_class my_integer;
use main without int like this:
#include <iostream>
#define int long long int
using namespace std;
main(){
// .... code
}
The simple answer: although technically possible you are not allowed to #define any of the reserved identifiers.