#include <mc-dec128.h>

#include <cstdio>

#if MONGOCRYPT_HAVE_DECIMAL128_SUPPORT()

#include <stdlib.h>

#include <mc-mlib/check.hpp>
#define CHECK MLIB_CHECK

inline std::ostream &operator<<(std::ostream &out, mc_dec128 d) noexcept {
    auto s = mc_dec128_to_new_decimal_string(d);
    out << s;
    free(s);
    return out;
}

#define OPER(Op, Fn)                                                                                                   \
    inline auto operator Op(mc_dec128 a, mc_dec128 b) noexcept /**/                                                    \
        ->decltype(mc_dec128_##Fn(a, b)) {                                                                             \
        return mc_dec128_##Fn(a, b);                                                                                   \
    }

OPER(+, add)
OPER(-, sub)
OPER(*, mul)
OPER(/, div)
OPER(==, equal)
OPER(>, greater)
OPER(<, less)

int main() {
    mc_dec128 a = MC_DEC128_ZERO;
    CHECK(mc_dec128_is_zero(a));

    mc_dec128 b = MC_DEC128_ZERO;
    mc_dec128 c = a * b;
    CHECK(c == MC_DEC128_ZERO);
    CHECK(mc_dec128_is_zero(c));

    b = MC_DEC128_C(1);
    // 0 + 1 = 1
    c = a + b;
    CHECK(c == MC_DEC128_C(1));

    // 1 + 1 = 2
    c = b + b;
    CHECK(c == MC_DEC128_C(2));

    // 2 * 2 = 4
    c = c * c;
    CHECK(c == MC_DEC128_C(4));

    // (4 + 1) / 2 = 2.5
    c = (c + MC_DEC128_C(1)) / MC_DEC128_C(2);
    CHECK(c == mc_dec128_from_string("2.5"));

    mc_dec128_string s = mc_dec128_to_string(c);
    CHECK(std::string(s.str) == "+25E-1");

    char *str = mc_dec128_to_new_decimal_string(c);
    CHECK(std::string(str) == "2.5");
    free(str);

    mc_dec128 infin = MC_DEC128_POSITIVE_INFINITY;
    CHECK(mc_dec128_is_inf(infin));

    mc_dec128 nan = MC_DEC128_POSITIVE_NAN;
    CHECK(mc_dec128_is_nan(nan));
}

#else

int main() {
    std::puts("@@ctest-skip@@\n Decimal128 support is not enabled\n");
}

#endif
