1macro_rules! from_signed_int {
22 ($t:ty, $cx:expr, $n:expr) => {
23 __from_int!($t, i32, $cx, $n)
24 };
25}
26
27macro_rules! from_unsigned_int {
29 ($t:ty, $cx:expr, $n:expr) => {
30 __from_int!($t, u32, $cx, $n)
31 };
32}
33
34macro_rules! __from_int {
35 ($t:ty, $l:ty, $cx:expr, $n:expr) => {{
36 let n = $n.to_be_bytes();
37 assert!(
38 n.len() % 4 == 0 && n.len() >= 4,
39 "from_int requires size of integer to be a multiple of 32"
40 );
41
42 let mut d = <$t>::from(<$l>::from_be_bytes(n[..4].try_into().unwrap()));
46 for i in (4..n.len()).step_by(4) {
47 d = $cx.mul(d, <$t>::TWO_POW_32);
48 let n = <$t>::from(u32::from_be_bytes(n[i..i + 4].try_into().unwrap()));
49 d = $cx.add(d, n);
50 }
51
52 d
53 }};
54}
55
56macro_rules! decimal_from_signed_int {
57 ($cx:expr, $n:expr) => {
58 __decimal_from_int!(i32, $cx, $n)
59 };
60}
61
62macro_rules! decimal_from_unsigned_int {
63 ($cx:expr, $n:expr) => {
64 __decimal_from_int!(u32, $cx, $n)
65 };
66}
67
68macro_rules! __decimal_from_int {
70 ($l:ty, $cx:expr, $n:expr) => {{
71 let n = $n.to_be_bytes();
72 assert!(
73 n.len() % 4 == 0 && n.len() >= 4,
74 "from_int requires size of integer to be a multiple of 32"
75 );
76 let two_pow_32 = Decimal::<N>::two_pow_32();
77
78 let mut d = Decimal::<N>::from(<$l>::from_be_bytes(n[..4].try_into().unwrap()));
79 for i in (4..n.len()).step_by(4) {
80 $cx.mul(&mut d, &two_pow_32);
81 let n = Decimal::<N>::from(u32::from_be_bytes(n[i..i + 4].try_into().unwrap()));
82 $cx.add(&mut d, &n);
83 }
84
85 d
86 }};
87}
88
89macro_rules! dpd2char {
91 ($dpd:expr, $digits:expr, $digits_idx:expr) => {{
92 let mut u = [0u8; 4];
93 let bin_idx = (unsafe { decnumber_sys::DPD2BIN[$dpd] } as usize) << 2;
94 u.copy_from_slice(unsafe { &decnumber_sys::BIN2CHAR[bin_idx..bin_idx + 4] });
95 if $digits_idx > 0 {
96 $digits[$digits_idx..$digits_idx + 3].copy_from_slice(&u[1..4]);
97 $digits_idx += 3;
98 } else if u[0] > 0 {
99 let d = (4 - u[0]) as usize;
101 $digits[$digits_idx..$digits_idx + u[0] as usize].copy_from_slice(&u[d..4]);
102 $digits_idx += u[0] as usize;
103 }
104 }};
105}
106
107macro_rules! stringify_digits {
109 ($s:expr, $digits:expr, $digits_idx:expr) => {{
110 if $digits_idx == 0 {
111 $digits[0] = b'0';
112 $digits_idx = 1;
113 }
114
115 let e = $s.exponent();
116 if e >= 0 {
117 let mut s = String::with_capacity($digits_idx + e as usize + 1);
118 if $s.is_negative() {
119 s.push('-');
120 }
121 s.push_str(unsafe { std::str::from_utf8_unchecked(&$digits[..$digits_idx]) });
122 if $digits[0] != b'0' {
123 for _ in 0..e {
124 s.push('0');
125 }
126 }
127 s
128 } else if $digits_idx as i32 > -e {
129 let mut s = String::with_capacity($digits_idx + 2);
130 if $s.is_negative() {
131 s.push('-');
132 }
133 let e = ($digits_idx as i32 + e) as usize;
134 for d in &$digits[..e] {
135 s.push(char::from(*d));
136 }
137 s.push('.');
138 for d in &$digits[e..$digits_idx] {
139 s.push(char::from(*d));
140 }
141 s
142 } else {
143 let d = usize::try_from(-e).unwrap() - $digits_idx;
144 let mut s = String::with_capacity($digits_idx + d + 3);
145 if $s.is_negative() {
146 s.push('-');
147 }
148 s.push_str("0.");
150 for _ in 0..d {
151 s.push('0');
152 }
153 for d in &$digits[..$digits_idx] {
154 s.push(char::from(*d));
155 }
156 s
157 }
158 }};
159}