Boost::multiprecision and cardinal_cubic_b_spline - c++

I'm new using the boost::multiprecision library and tried to use it combination with boost::math::interpolators::cardinal_cubic_b_spline however I can't compile the program.
The example code is
#include <boost/math/interpolators/cardinal_cubic_b_spline.hpp>
#include <iostream>
#include <boost/multiprecision/gmp.hpp>
using boost::multiprecision::mpf_float_50;
int main() {
std::vector<mpf_float_50> v(10);
mpf_float_50 step(0.01);
for (size_t i = 0; i < v.size(); ++i) {
v.at(i) = sin(i*step);
}
mpf_float_50 leftPoint(0.0);
boost::math::interpolators::cardinal_cubic_b_spline<mpf_float_50> spline(v.begin(), v.end(), leftPoint, step);
mpf_float_50 x(3.1);
mpf_float_50 tmpVal = spline(x);
std::cout << tmpVal << std::endl;
return 0;
}
When change the type of variables to boost::multiprecision::cpp_bin_float_50 the program is working. Also, boost::multiprecision::mpf_float_50 is working in all other examples I have tried.
The error I get is:
/home/..../main.cpp:19:31: required from here
/usr/include/boost/math/interpolators/detail/cardinal_cubic_b_spline_detail.hpp:50:10: error: conversion from ‘expression<boost::multiprecision::detail::function,boost::multiprecision::detail::abs_funct<boost::multiprecision::backends::gmp_float<50> >,boost::multiprecision::detail::expression<boost::multiprecision::detail::subtract_immediates, boost::multiprecision::number<boost::multiprecision::backends::gmp_float<50> >, long unsigned int, void, void>,[...],[...]>’ to non-scalar type ‘expression<boost::multiprecision::detail::subtract_immediates,boost::multiprecision::number<boost::multiprecision::backends::gmp_float<50> >,long unsigned int,[...],[...]>’ requested
The same error appeared for cpp_dec_float_50, mpfr_float_50 etc. I'm not sure what I'm doing wrong.

The selected type. is the GMP backend. To give it the usual operators, it is wrapped in the frontend template number<>:
Live On Coliru
using F = boost::multiprecision::mpf_float_50;
int main() {
F a = 3, b = 2;
F c = b - a;
std::cout << "a:" << a << ", b:" << b << ", c:" << c << std::endl;
b = abs(b - a);
std::cout << "a:" << a << ", b:" << b << ", c:" << c << std::endl;
}
Prints
a:3, b:2, c:-1
a:3, b:1, c:-1
However, the number<> enables expression templates by default. That means, typeof(F{} - F{}) is not necessarily F, but something like:
namespace mp = boost::multiprecision;
using F = mp::mpf_float_50;
int main() {
F a = 3, b = 2;
mp::detail::expression<mp::detail::subtract_immediates, F, F> //
c = b - a;
Template expressions can greatly optimize some code, e.g. by simplifying evaluation of complicated expressions.
However, some generic code doesn't deal well with the expression templates. Therefore you can turn them off:
namespace mp = boost::multiprecision;
using F = mp::number<mp::gmp_float<50>, mp::et_off>;
Now it all compiles, and probably works as it should.
Live On Coliru
#include <boost/math/interpolators/cardinal_cubic_b_spline.hpp>
#include <iostream>
#include <boost/multiprecision/gmp.hpp>
namespace mp = boost::multiprecision;
using F = mp::number<mp::gmp_float<50>, mp::et_off>;
int main() {
std::vector<F> v(10);
F step(0.01);
for (size_t i = 0; i < v.size(); ++i) {
v.at(i) = sin(i * step);
}
F leftPoint(0.0);
boost::math::interpolators::cardinal_cubic_b_spline<F> spline(v.begin(), v.end(), leftPoint, step);
F x(3.1);
F tmpVal = spline(x);
std::cout << tmpVal << std::endl;
}
Now printing:
0.0449663

Related

When using variant but error-invoke, could errors happens in compiling time instead of bad_variant_access in running time

If I have a map like
const std::map<int, std::variant<int, std::string>> m ={{1,1},{2,"asd"}};
But if i invoke std::get<string>(m[1]) by mistake instead of std::get<int>(m[1]), it will raise bad_variant_access.
But it is just a typo of codes, so could it be detected by IDE, or some form of static_assert could work because m is a constant(or what if m is not a constant) , or raise only compile errors?
If it is always constant, you don't need a map. You can dispatch that at compile time:
#include <iostream>
template <int i>
constexpr auto m()
{
if constexpr (i == 1) {
return 1;
} else if constexpr (i == 2) {
return "hello";
}
}
int main()
{
std::cout << m<1>() << '\n';
std::cout << m<2>() << '\n';
}
Or, just use a tuple:
#include <iostream>
#include <tuple>
int main()
{
std::tuple tuple { 1, "hello world" };
std::cout << std::get<0>(tuple) << '\n';
std::cout << std::get<1>(tuple) << '\n';
}

Problem compiling a function from Boost Library

I'm trying to use the function norm_2_vector from boost.
But I'm getting the error ‘norm_2_square’ was not declared in this scope.
To compile I used the command below, where testNormSquare is the name of the program:
g++ -o testNorm2Square testNorm2Square.cpp
Question: Is there anything I'm missing? What should I do to make the code compilable?
A toy example that is not working is given below.
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/io.hpp>
int main () {
using namespace boost::numeric::ublas;
vector<double> v (3);
for (unsigned i = 0; i < v.size (); ++ i)
v(i) = i;
std::cout << 2.0 * v << std::endl;
std::cout << v * 2.0 << std::endl;
std::cout << norm_2_square(v);
}
The error message is the following:
testNorm2Square.cpp:12:18: error: ‘norm_2_square’ was not declared in this scope
Another problem happens if I specify explicitly that norm_2_square belongs to boost::numeric::ublas:
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/io.hpp>
int main () {
using namespace boost::numeric::ublas;
vector<double> v (3);
for (unsigned i = 0; i < v.size (); ++ i)
v(i) = i;
std::cout << 2.0 * v << std::endl;
std::cout << v * 2.0 << std::endl;
std::cout << boost::numeric::ublas::norm_2_square(v);
}
In this case the error message is:
testNorm2SquareV2.cpp:12:41: error: ‘norm_2_square’ is not a member of ‘boost::numeric::ublas’

How to return std::tuple from a std::async task

How can I launch a member function as a std::async task, which returns a std::tuple.
Sample code:
#include <iostream>
#include <future>
#include <tuple>
#include <numeric>
class Foo {
bool calc;
public:
Foo(bool b) : calc(b)
{}
std::tuple<long, double> calc(std::vector<int> a) {
long sum = 0;
double avg = 0.0;
if ((*this).calc) {
long sum = std::accumulate(a.begin(), a.end(), 0);
double avg = sum / a.size();
}
return std::make_tuple(sum, avg);
}
void call_calc(std::vector<int> i) {
auto handle = std::async(&Foo::calc, this, i);
auto resultTuple = handle.get();
std::cout << "Sum = " << std::get<0>(resultTuple) << " Average = " << std::get<1>(resultTuple) << std::endl;
}
};
int main() {
std::vector<int> a{ 2, 5, 6, 7, 3 };
Foo foo(true);
foo.call_calc(a);
}
In this example, without the member variable, code works fine.
The above code is throwing compilation error for following lines:
auto handle = std::async(&Foo::calc, this, i);
Error: No instance of overloaded function 'std::async' matches the argument list.
std::cout << "Sum = " << std::get<0>(resultTuple) << " Average = " << std::get<1>(resultTuple) << std::endl;
Error: No instance of overloaded function 'std::get' matches the argument list.
The problem seems to be that you have both a data member and a member function named calc. Renaming one solves the issue.
[Live example]

Using auto with initializer list

I have question regarding interaction between auto and initializer list. Example code:
#include <iostream>
int main()
{
auto a{ 1 };
auto b = { 1 };
auto c = 1;
std::cout << typeid(a).name() << std::endl;
std::cout << typeid(b).name() << std::endl;
std::cout << typeid(c).name() << std::endl;
return 0;
}
Gives output:
int
class std::initializer_list<int>
int
Which is kind of confusing. I'm posting this question as a followup to this. What should happen? I've did some research and it seems that auto c = 1; is illegal now, and it seems that it works because compilers allow this as a backwards compatibility patch. Does this apply also to auto a{1}?

private and public operator overloading

I tried to implement the method of Horner and faced a problem:
root#host:~# cat | g++ -x c++ -std=gnu++11 - && ./a.out
#include <iostream>
#include <iomanip>
#include <iterator>
#include <vector>
#include <numeric>
#include <algorithm>
#include <random>
#include <chrono>
#include <cstdlib>
template< typename F >
class horner
{
public :
typedef std::vector< F > V;
horner(F const & x_, V const & c_)
: x(x_)
, c(c_)
, y(0.0L)
{ ; }
operator F const () const
{
return std::accumulate(c.rbegin(), c.rend(), *this).y;
}
private :
friend horner std::accumulate< typename V::const_reverse_iterator, horner >(typename V::const_reverse_iterator, typename V::const_reverse_iterator, horner);
void operator = (F const & rhs)
{
y = rhs;
}
operator F ()
{
y *= x;
return y;
}
F const & x;
V const & c;
F y;
};
#define N_COEFF_PARABOLA 3
int main()
{
typedef double F;
typedef typename horner< F >::V V;
V c;
unsigned seed(std::chrono::system_clock::now().time_since_epoch().count());
std::cout << "seed = 0x"
<< std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(seed) * 2)
<< seed << std::endl;
std::mt19937 generator(seed);
std::generate_n(std::back_inserter(c), N_COEFF_PARABOLA, generator);
std::cout << "coefficients: ";
std::copy(c.begin(), c.end(), std::ostream_iterator< F >(std::cout, " "));
std::cout << ';' << std::endl;
F const x(generator());
F const y(horner< F >(x, c));
std::cout << "y(" << x << ") = " << y << std::endl;
// naive
F xx(1.0L);
F yy(0.0L);
for (typename V::size_type i(0); i < c.size(); ++i) {
yy += c[i] * xx;
xx *= x;
}
std::cout << "y'(" << x << ") = " << yy << std::endl;
return EXIT_SUCCESS;
}
// press ^D
<stdin>: In function ‘int main()’:
<stdin>:39:5: error: ‘horner<F>::operator F() [with F = double]’ is private
<stdin>:71:32: error: within this context
root#host:~#
In my view the problem should not arise, since main() only sees operator F const & () const version of the type conversion operator. But it is.
What is the reason of the error?
The concepts of visibility and accessibility are completely orthogonal in C++. If a method is visible, but not accessible, the compiler may select it in overload resolution and produce a hard error because it can't use it. This is done on purpose so code does not change semantics silently when it gains or looses access.