mirror of
https://github.com/luxfi/intx.git
synced 2026-10-30 16:22:26 +00:00
128 lines
3.0 KiB
C++
128 lines
3.0 KiB
C++
// intx: extended precision integer library.
|
|
// Copyright 2019 Pawel Bylica.
|
|
// Licensed under the Apache License, Version 2.0.
|
|
|
|
#include "../utils/gmp.hpp"
|
|
#include <intx/intx.hpp>
|
|
#include <cstring>
|
|
|
|
using namespace intx;
|
|
|
|
enum class op : uint8_t
|
|
{
|
|
divrem = 0x00,
|
|
mul = 0x01,
|
|
shl = 0x02,
|
|
lsr = 0x03,
|
|
add = 0x04,
|
|
sub = 0x05,
|
|
sdivrem = 0x06,
|
|
cmp = 0x07,
|
|
};
|
|
|
|
template <typename T>
|
|
inline void expect_eq(const T& x, const T& y) noexcept
|
|
{
|
|
if (x != y)
|
|
__builtin_trap();
|
|
}
|
|
|
|
template <typename T>
|
|
inline void test_op(const uint8_t* data, size_t data_size) noexcept
|
|
{
|
|
static constexpr auto arg_size = sizeof(T);
|
|
if (data_size != 2 * arg_size + 1)
|
|
return;
|
|
|
|
// Load 2 values. BE for easier extracting tests from corpus.
|
|
const auto a = be::unsafe::load<T>(&data[1]);
|
|
const auto b = be::unsafe::load<T>(&data[1 + arg_size]);
|
|
|
|
switch (static_cast<op>(data[0]))
|
|
{
|
|
case op::divrem:
|
|
if (b != 0)
|
|
{
|
|
auto x = udivrem(a, b);
|
|
auto y = gmp::udivrem(a, b);
|
|
expect_eq(x.quot, y.quot);
|
|
expect_eq(x.rem, y.rem);
|
|
}
|
|
break;
|
|
case op::sdivrem:
|
|
if (b != 0)
|
|
{
|
|
auto x = sdivrem(a, b);
|
|
auto y = gmp::sdivrem(a, b);
|
|
expect_eq(x.quot, y.quot);
|
|
expect_eq(x.rem, y.rem);
|
|
}
|
|
break;
|
|
case op::mul:
|
|
{
|
|
auto x = a * b;
|
|
auto y = gmp::mul(a, b);
|
|
expect_eq(x, y);
|
|
break;
|
|
}
|
|
case op::shl:
|
|
{
|
|
auto x = a << b;
|
|
auto s = T(1) << b;
|
|
auto y = a * s;
|
|
expect_eq(x, y);
|
|
break;
|
|
}
|
|
case op::lsr:
|
|
{
|
|
auto x = a >> b;
|
|
auto s = T(1) << b;
|
|
auto y = (s != 0) ? a / s : 0;
|
|
expect_eq(x, y);
|
|
break;
|
|
}
|
|
case op::add:
|
|
expect_eq(a + b, gmp::add(a, b));
|
|
break;
|
|
|
|
case op::sub:
|
|
{
|
|
const auto s = a - b;
|
|
expect_eq(s, gmp::sub(a, b));
|
|
expect_eq(s, a + -b);
|
|
expect_eq(s, a + (~b + 1));
|
|
break;
|
|
}
|
|
case op::cmp:
|
|
{
|
|
auto aa = to_big_endian(a);
|
|
auto bb = to_big_endian(b);
|
|
auto m = std::memcmp(&aa, &bb, sizeof(aa));
|
|
expect_eq(a < b, m < 0);
|
|
expect_eq(a <= b, m <= 0);
|
|
expect_eq(a > b, m > 0);
|
|
expect_eq(a >= b, m >= 0);
|
|
expect_eq(a == b, m == 0);
|
|
expect_eq(a != b, m != 0);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t data_size) noexcept
|
|
{
|
|
test_op<intx::uint<4096>>(data, data_size);
|
|
test_op<intx::uint<2048>>(data, data_size);
|
|
test_op<intx::uint<1024>>(data, data_size);
|
|
test_op<intx::uint<512>>(data, data_size);
|
|
test_op<intx::uint<384>>(data, data_size);
|
|
test_op<intx::uint<320>>(data, data_size);
|
|
test_op<intx::uint<256>>(data, data_size);
|
|
test_op<intx::uint<192>>(data, data_size);
|
|
test_op<intx::uint<128>>(data, data_size);
|
|
return 0;
|
|
}
|