1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use core::cmp::Ordering;

use elrond_wasm::api::{BigFloatApi, Handle, Sign};

extern "C" {
    fn bigFloatNewFromParts(integralPart: i32, fractionalPart: i32, exponent: i32) -> i32;
    fn bigFloatNewFromFrac(numerator: i64, denominator: i64) -> i32;
    fn bigFloatNewFromSci(significand: i64, exponent: i64) -> i32;

    fn bigFloatAdd(dest: i32, x: i32, y: i32);
    fn bigFloatSub(dest: i32, x: i32, y: i32);
    fn bigFloatMul(dest: i32, x: i32, y: i32);
    fn bigFloatDiv(dest: i32, x: i32, y: i32);

    fn bigFloatAbs(dest: i32, x: i32);
    fn bigFloatNeg(dest: i32, x: i32);
    fn bigFloatCmp(x: i32, y: i32) -> i32;
    fn bigFloatSign(x: i32) -> i32;
    fn bigFloatClone(dest: i32, x: i32);
    fn bigFloatSqrt(dest: i32, x: i32);
    fn bigFloatPow(dest: i32, x: i32, exponent: i32);

    fn bigFloatFloor(dest: i32, x: i32);
    fn bigFloatCeil(dest: i32, x: i32);
    fn bigFloatTruncate(dest: i32, x: i32);

    fn bigFloatIsInt(x: i32) -> i32;
    fn bigFloatSetInt64(dest: i32, x: i64);
    fn bigFloatSetBigInt(dest: i32, x: i32);

    fn bigFloatGetConstPi(dest: i32);
    fn bigFloatGetConstE(dest: i32);
}

macro_rules! binary_op_wrapper {
    ($method_name:ident, $hook_name:ident) => {
        fn $method_name(&self, dest: Handle, x: Handle, y: Handle) {
            unsafe {
                $hook_name(dest, x, y);
            }
        }
    };
}

macro_rules! unary_op_wrapper {
    ($method_name:ident, $hook_name:ident) => {
        fn $method_name(&self, dest: Handle, x: Handle) {
            unsafe {
                $hook_name(dest, x);
            }
        }
    };
}

impl BigFloatApi for crate::VmApiImpl {
    #[inline]
    fn bf_from_parts(
        &self,
        integral_part_value: i32,
        fractional_part_value: i32,
        exponent_value: i32,
    ) -> Handle {
        unsafe { bigFloatNewFromParts(integral_part_value, fractional_part_value, exponent_value) }
    }

    #[inline]
    fn bf_from_frac(&self, numerator_value: i64, denominator_value: i64) -> Handle {
        unsafe { bigFloatNewFromFrac(numerator_value, denominator_value) }
    }

    #[inline]
    fn bf_from_sci(&self, significand_value: i64, exponent_value: i64) -> Handle {
        unsafe { bigFloatNewFromSci(significand_value, exponent_value) }
    }

    binary_op_wrapper! {bf_add, bigFloatAdd}
    binary_op_wrapper! {bf_sub, bigFloatSub}
    binary_op_wrapper! {bf_mul, bigFloatMul}
    binary_op_wrapper! {bf_div, bigFloatDiv}

    unary_op_wrapper! {bf_neg, bigFloatNeg}
    unary_op_wrapper! {bf_abs, bigFloatAbs}

    #[inline]
    fn bf_cmp(&self, x: Handle, y: Handle) -> Ordering {
        unsafe { bigFloatCmp(x, y).cmp(&0) }
    }

    fn bf_sign(&self, x: Handle) -> Sign {
        unsafe {
            match bigFloatSign(x).cmp(&0) {
                Ordering::Greater => Sign::Plus,
                Ordering::Equal => Sign::NoSign,
                Ordering::Less => Sign::Minus,
            }
        }
    }

    unary_op_wrapper! {bf_clone, bigFloatClone}
    unary_op_wrapper! {bf_sqrt, bigFloatSqrt}
    binary_op_wrapper! {bf_pow, bigFloatPow}

    unary_op_wrapper! {bf_floor , bigFloatFloor}
    unary_op_wrapper! {bf_ceil , bigFloatCeil}
    unary_op_wrapper! {bf_trunc , bigFloatTruncate}

    #[inline]
    fn bf_is_bi(&self, x: Handle) -> bool {
        unsafe { 1 == bigFloatIsInt(x) }
    }

    #[inline]
    fn bf_set_i64(&self, dest: Handle, value: i64) {
        unsafe {
            bigFloatSetInt64(dest, value);
        }
    }

    unary_op_wrapper! {bf_set_bi, bigFloatSetBigInt}

    #[inline]
    fn bf_get_const_e(&self, dest: Handle) {
        unsafe { bigFloatGetConstE(dest) }
    }

    #[inline]
    fn bf_get_const_pi(&self, dest: Handle) {
        unsafe { bigFloatGetConstPi(dest) }
    }
}