Home > Software design >  Boost::multiprecision and cardinal_cubic_b_spline
Boost::multiprecision and cardinal_cubic_b_spline

Time:12-04

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.

CodePudding user response:

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

CodePudding user response:

It looks like the cardinal_cubic_b_spline class expects the type of the elements in the input vector to have the operator- and abs functions defined. The mpf_float_50 type from the boost::multiprecision::gmp library does not have these functions defined. You can fix this by using the cpp_bin_float_50 type, which does have these functions defined. Alternatively, you can define the operator- and abs functions for the mpf_float_50 type yourself.

  • Related