Boost multiprecision cpp_int

Does boost ignore the parenthesis operator precedence?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>

int main()
{
    const boost::multiprecision::cpp_int max = 6;
    const boost::multiprecision::cpp_int factor = 4;
    const boost::multiprecision::cpp_int result = factor * factor * (max/factor); 
    
    std::cout << max << '/' << factor << " = " << max/factor << std::endl;
    std::cout << result << std::endl;
    
    const boost::multiprecision::cpp_int result2 = 4 * 4 * (6/4);
    
    std::cout << result2 << std::endl;
}
6/4 = 1
24
16

http://coliru.stacked-crooked.com/a/7351f3c2d1af5159

I am curious as to why boost doesn't parse like c++ it should be (afaik):
((4*4)*(6/4))
but instead it seems to be doing
(((4*4)*6)/4)
I mean I guess I could simply put 6/4 on the left and problem solved but I am not understanding why the first version doesn't work. If anyone could explain I would appreciate.

[edit]added link[/edit]
Last edited on
I don't think it has anything to do with operator precedence but that max/factor is returning 1.5, but I've never used boost::multiprecision.
But it is an integer division it should be 1. If you output std::cout << max/factor << std::endl; You get 1.

I'll update the code on original to include that.
Maybe a bug, the fixed precision types produce the correct result.
1
2
3
4
5
6
7
8
9
10
11
12
13
int main()
{
    const boost::multiprecision::int256_t max = 6;
    const boost::multiprecision::int256_t factor = 4;
    const boost::multiprecision::int256_t result = factor * factor * (max / factor);

    std::cout << max << '/' << factor << " = " << (max / factor) << std::endl;
    std::cout << result << std::endl;

    const boost::multiprecision::cpp_int result2 = 4 * 4 * (6 / 4);

    std::cout << result2 << std::endl;
}
With
1
2
const boost::multiprecision::cpp_int max = 6;
const boost::multiprecision::cpp_int factor = 4;

the type of the expressions factor * factor and max/factor is not an integer type.
The documentation states that it is an "an unmentionable expression template type".

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <boost/multiprecision/cpp_int.hpp>

int main()
{
    const boost::multiprecision::cpp_int max = 6;
    const boost::multiprecision::cpp_int factor = 4;

    // type: boost::multiprecision::detail::expression<>
    const auto raw_result_a = factor * factor ;
    const auto raw_result_b = max/factor ;

    // type: boost::multiprecision::number<>
    const boost::multiprecision::cpp_int integer_result_a(raw_result_a) ;
    const boost::multiprecision::cpp_int integer_result_b(raw_result_b) ;

    std::cout << "multiply raw results: " << raw_result_a * raw_result_b << '\n' // 24
              << "multiply int results: " << integer_result_a * integer_result_b << "\n\n" ; // 16

    print_type_name(raw_result_a) ; // boost::multiprecision::detail::expression<...>
    print_type_name(integer_result_a) ; // boost::multiprecision::number<...>
}

To me, this result is clearly unintuitive when both operands are of integer types.

http://coliru.stacked-crooked.com/a/9e51b3beae57fc31

(Note: expression templates are turned off for fixed precision types.)
Thanks JLBorges that explains, I was thinking it would only be cpp_dec_float and not cpp_int to have those results. Also how often do they have that many templates inside of each other? Looks like the coder would get confused.
raw_result_a is of type boost::multiprecision::detail::expression<boost::multiprecision::detail::multiply_immediates, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0u, 0u, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::allocator<unsigned long long> >, (boost::multiprecision::expression_template_option)1>, boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0u, 0u, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::allocator<unsigned long long> >, (boost::multiprecision::expression_template_option)1>, void, void>
> Looks like the coder would get confused.

That is why it is in the nested namespace detail. And the documentation describes it as 'unmentionable'.

A user of the library, in the typical scenario, would not have to read this. Unless a problem arises, and the user wants to investigate further.

You may want to report this as a bug: http://www.boost.org/development/bugs.html
I see thanks and I reported it. Sorry I over read your "an unmentionable expression template type." I am surprised no one else had this problem unless not a lot of people use boost for project euler.
That's weird I hit the new ticket option and filled it out. Not sure if I should fill out another.
> Not sure if I should fill out another.

Yes, you should.

After filling the details, previewing it etc, click on the 'Create Ticket' button.
Oh I see why it didn't get put there the first time. I tried linking this thread for additional details (like I did last time) and it thinks it says "Captcha Error
Submission rejected as potential spam (External links in post found)

Trac thinks your submission might be Spam. To prove otherwise please provide a response to the following." Seems weird there is actually nothing following it. I will have to try and describe it as best I can.
Last edited on
Changed 4 days ago by johnmaddock

Status changed from new to closed
Resolution set to fixed

The result isn't a floating point type: rather the expression templates can radically re-order many operations. However, this is a bug, so I've disabled some reordering operations specifically for integer types: https://github.com/boostorg/multiprecision/commit/9eb732b956803f4999da50e155e757083e89beb3.

https://svn.boost.org/trac/boost/ticket/9802
Topic archived. No new replies allowed.