Integer arithmetic

Integer arithmetic#

Preliminaries#

Let us load the mp++ runtime, include the headers and import the user-defined literals:

#pragma cling add_include_path("$CONDA_PREFIX/include")
#pragma cling add_library_path("$CONDA_PREFIX/lib")
#pragma cling load("mp++")

#include <mp++/integer.hpp>
#include <mp++/exceptions.hpp>

using namespace mppp::literals;

Let us also include a few useful bits from the standard library:

#include <iostream>

Basic arithmetic#

Multiprecision integers support the basic arithmetic operators:

1_z1 + 1_z1
2
3_z1 - 5_z1
-2
21_z1 * 2_z1
42

Integral division truncates:

41_z1 / 3_z1
13

Integral division by zero raises an exception:

try {
    41_z1 / 0_z1;
} catch (const mppp::zero_division_error &zde) {
    std::cerr << zde.what() << '\n';
}
Integer division by zero

Modulo:

41_z1 % 3_z1
2

Mixed-mode operations with other types:

1_z1 + 4
5
11ull - 6_z1
5
21_z1 * 2.5f
52.5000f
41_z1 / 3.
13.666667
13 % 4_z1
1

In-place arithmetic (with multiprecision integers both on the left and on the right):

{
    auto n = 45_z1;
    n += 4_z1;
    std::cout << n << '\n';
}
49
{
    auto n = 45_z1;
    n -= 4.5;
    std::cout << n << '\n';
}
40
{
    auto n = 2;
    n *= 45_z1;
    std::cout << n << '\n';
}
90
{
    auto n = 88;
    n /= 2.f;
    std::cout << n << '\n';
}
44

Increment/decrement operators:

{
    auto n = 88_z1;
    std::cout << ++n << '\n';
    std::cout << n++ << '\n';
    std::cout << --n << '\n';
    std::cout << n-- << '\n';
}
89
89
89
89

The identity and negation operators:

{
    auto n = 345_z1;
    std::cout << +n << '\n';
    std::cout << -n << '\n';
}
345
-345

Bit-shifting operators (including the in-place variants):

123_z1 << 512
1649160375382939443247605074779319073679961995932864385459998057577776975699046278146630538674529121605873918556937784255011727585869428103411338827748343808
(43_z1 >> 2) == (43_z1 / 4)
true

Absolute value:

abs(-123_z1)
123

Optimised in-place fused multiply-add/sub primitives:

{
    auto n1 = 3_z1;
    addmul(n1, 4_z1, 5_z1);
    std::cout << "3 + (4 * 5) == " << n1 << '\n';
    
    auto n2 = 6_z1;
    submul(n2, 7_z1, 8_z1);
    std::cout << "6 - (7 * 8) == " << n2 << '\n';
}
3 + (4 * 5) == 23
6 - (7 * 8) == -50

Squaring and modular squaring:

sqr(12_z1)
144
sqrm(3_z1, 4_z1) // (3**2) mod 4 == 1
1

Besides what has been shown so far, mp++ provides a rich set of additional arithmetic functions for multiprecision integers, including member functions variants, lower-level higher-performance primitives, additional division functions, etc.

Be sure to check them out in the mp++ docs.