1use crate::{Float, RoundingMode, F16, F32, F64};
2use softfloat_sys_riscv::float128_t;
3use std::borrow::Borrow;
4use std::cmp::Ordering;
5
6#[derive(Copy, Clone, Debug)]
8pub struct F128(float128_t);
9
10impl Float for F128 {
11 type Payload = u128;
12
13 const EXPONENT_BIT: Self::Payload = 0x7fff;
14 const FRACTION_BIT: Self::Payload = 0xffff_ffff_ffff_ffff_ffff_ffff_ffff;
15 const SIGN_POS: usize = 127;
16 const EXPONENT_POS: usize = 112;
17
18 #[inline]
19 fn set_payload(&mut self, x: Self::Payload) {
20 let x = [x as u64, (x >> 64) as u64];
21 self.0.v = x;
22 }
23
24 #[inline]
25 fn from_bits(v: Self::Payload) -> Self {
26 let v = [v as u64, (v >> 64) as u64];
27 Self(float128_t { v })
28 }
29
30 #[inline]
31 fn bits(&self) -> Self::Payload {
32 let mut ret = 0u128;
33 ret |= self.0.v[0] as u128;
34 ret |= (self.0.v[1] as u128) << 64;
35 ret
36 }
37
38 fn add<T: Borrow<Self>>(&self, x: T, rnd: RoundingMode) -> Self {
39 rnd.set();
40 let ret = unsafe { softfloat_sys_riscv::f128_add(self.0, x.borrow().0) };
41 Self(ret)
42 }
43
44 fn sub<T: Borrow<Self>>(&self, x: T, rnd: RoundingMode) -> Self {
45 rnd.set();
46 let ret = unsafe { softfloat_sys_riscv::f128_sub(self.0, x.borrow().0) };
47 Self(ret)
48 }
49
50 fn mul<T: Borrow<Self>>(&self, x: T, rnd: RoundingMode) -> Self {
51 rnd.set();
52 let ret = unsafe { softfloat_sys_riscv::f128_mul(self.0, x.borrow().0) };
53 Self(ret)
54 }
55
56 fn fused_mul_add<T: Borrow<Self>>(&self, x: T, y: T, rnd: RoundingMode) -> Self {
57 rnd.set();
58 let ret = unsafe { softfloat_sys_riscv::f128_mulAdd(self.0, x.borrow().0, y.borrow().0) };
59 Self(ret)
60 }
61
62 fn div<T: Borrow<Self>>(&self, x: T, rnd: RoundingMode) -> Self {
63 rnd.set();
64 let ret = unsafe { softfloat_sys_riscv::f128_div(self.0, x.borrow().0) };
65 Self(ret)
66 }
67
68 fn rem<T: Borrow<Self>>(&self, x: T, rnd: RoundingMode) -> Self {
69 rnd.set();
70 let ret = unsafe { softfloat_sys_riscv::f128_rem(self.0, x.borrow().0) };
71 Self(ret)
72 }
73
74 fn sqrt(&self, rnd: RoundingMode) -> Self {
75 rnd.set();
76 let ret = unsafe { softfloat_sys_riscv::f128_sqrt(self.0) };
77 Self(ret)
78 }
79
80 fn compare<T: Borrow<Self>>(&self, x: T) -> Option<Ordering> {
81 let eq = unsafe { softfloat_sys_riscv::f128_eq(self.0, x.borrow().0) };
82 let lt = unsafe { softfloat_sys_riscv::f128_lt(self.0, x.borrow().0) };
83 if self.is_nan() || x.borrow().is_nan() {
84 None
85 } else if eq {
86 Some(Ordering::Equal)
87 } else if lt {
88 Some(Ordering::Less)
89 } else {
90 Some(Ordering::Greater)
91 }
92 }
93
94 fn from_u32(x: u32, rnd: RoundingMode) -> Self {
95 rnd.set();
96 let ret = unsafe { softfloat_sys_riscv::ui32_to_f128(x) };
97 Self(ret)
98 }
99
100 fn from_u64(x: u64, rnd: RoundingMode) -> Self {
101 rnd.set();
102 let ret = unsafe { softfloat_sys_riscv::ui64_to_f128(x) };
103 Self(ret)
104 }
105
106 fn from_i32(x: i32, rnd: RoundingMode) -> Self {
107 rnd.set();
108 let ret = unsafe { softfloat_sys_riscv::i32_to_f128(x) };
109 Self(ret)
110 }
111
112 fn from_i64(x: i64, rnd: RoundingMode) -> Self {
113 rnd.set();
114 let ret = unsafe { softfloat_sys_riscv::i64_to_f128(x) };
115 Self(ret)
116 }
117
118 fn to_u32(&self, rnd: RoundingMode) -> u32 {
119 let ret = unsafe { softfloat_sys_riscv::f128_to_ui32(self.0, rnd.to_softfloat(), false) };
120 ret as u32
121 }
122
123 fn to_u64(&self, rnd: RoundingMode) -> u64 {
124 let ret = unsafe { softfloat_sys_riscv::f128_to_ui64(self.0, rnd.to_softfloat(), false) };
125 ret
126 }
127
128 fn to_i32(&self, rnd: RoundingMode) -> i32 {
129 let ret = unsafe { softfloat_sys_riscv::f128_to_i32(self.0, rnd.to_softfloat(), false) };
130 ret as i32
131 }
132
133 fn to_i64(&self, rnd: RoundingMode) -> i64 {
134 let ret = unsafe { softfloat_sys_riscv::f128_to_i64(self.0, rnd.to_softfloat(), false) };
135 ret
136 }
137
138 fn to_f16(&self, rnd: RoundingMode) -> F16 {
139 rnd.set();
140 let ret = unsafe { softfloat_sys_riscv::f128_to_f16(self.0) };
141 F16::from_bits(ret.v)
142 }
143
144 fn to_f32(&self, rnd: RoundingMode) -> F32 {
145 rnd.set();
146 let ret = unsafe { softfloat_sys_riscv::f128_to_f32(self.0) };
147 F32::from_bits(ret.v)
148 }
149
150 fn to_f64(&self, rnd: RoundingMode) -> F64 {
151 rnd.set();
152 let ret = unsafe { softfloat_sys_riscv::f128_to_f64(self.0) };
153 F64::from_bits(ret.v)
154 }
155
156 fn to_f128(&self, _rnd: RoundingMode) -> F128 {
157 Self::from_bits(self.bits())
158 }
159
160 fn round_to_integral(&self, rnd: RoundingMode) -> Self {
161 let ret = unsafe { softfloat_sys_riscv::f128_roundToInt(self.0, rnd.to_softfloat(), false) };
162 Self(ret)
163 }
164}
165
166#[cfg(test)]
167mod tests {
168 use super::*;
169
170 #[test]
171 fn f128_add() {
172 let a = 0x12345678ffffffffffffffffffffffff;
173 let b = 0x76546410aaaaaaaaffffffffffffffff;
174 let a0 = F128::from_bits(a);
175 let b0 = F128::from_bits(b);
176 let d0 = a0.add(b0, RoundingMode::TiesToEven);
177 let a1 = simple_soft_float::F128::from_bits(a);
178 let b1 = simple_soft_float::F128::from_bits(b);
179 let d1 = a1.add(&b1, Some(simple_soft_float::RoundingMode::TiesToEven), None);
180 assert_eq!(d0.bits(), *d1.bits());
181 }
182
183 #[test]
184 fn f128_sub() {
185 let a = 0x12345678ffffffffffffffffffffffff;
186 let b = 0x76546410aaaaaaaaffffffffffffffff;
187 let a0 = F128::from_bits(a);
188 let b0 = F128::from_bits(b);
189 let d0 = a0.sub(b0, RoundingMode::TiesToEven);
190 let a1 = simple_soft_float::F128::from_bits(a);
191 let b1 = simple_soft_float::F128::from_bits(b);
192 let d1 = a1.sub(&b1, Some(simple_soft_float::RoundingMode::TiesToEven), None);
193 assert_eq!(d0.bits(), *d1.bits());
194 }
195
196 #[test]
197 fn f128_mul() {
198 let a = 0x12345678ffffffffffffffffffffffff;
199 let b = 0x76546410aaaaaaaaffffffffffffffff;
200 let a0 = F128::from_bits(a);
201 let b0 = F128::from_bits(b);
202 let d0 = a0.mul(b0, RoundingMode::TiesToEven);
203 let a1 = simple_soft_float::F128::from_bits(a);
204 let b1 = simple_soft_float::F128::from_bits(b);
205 let d1 = a1.mul(&b1, Some(simple_soft_float::RoundingMode::TiesToEven), None);
206 assert_eq!(d0.bits(), *d1.bits());
207 }
208
209 #[test]
210 #[ignore]
211 fn f128_fused_mul_add() {
212 let a = 0x12345678ffffffffffffffffffffffff;
213 let b = 0x12345678aaaaaaaaffffffffffffffff;
214 let c = 0x12345678aaaaaaaaffffffffffffffff;
215 let a0 = F128::from_bits(a);
216 let b0 = F128::from_bits(b);
217 let c0 = F128::from_bits(c);
218 let d0 = a0.fused_mul_add(b0, c0, RoundingMode::TiesToEven);
219 let a1 = simple_soft_float::F128::from_bits(a);
220 let b1 = simple_soft_float::F128::from_bits(b);
221 let c1 = simple_soft_float::F128::from_bits(c);
222 let d1 = a1.fused_mul_add(
223 &b1,
224 &c1,
225 Some(simple_soft_float::RoundingMode::TiesToEven),
226 None,
227 );
228 assert_eq!(d0.bits(), *d1.bits());
229 }
230
231 #[test]
232 fn f128_div() {
233 let a = 0x76545678ffffffffffffffffffffffff;
234 let b = 0x12346410aaaaaaaaffffffffffffffff;
235 let a0 = F128::from_bits(a);
236 let b0 = F128::from_bits(b);
237 let d0 = a0.div(b0, RoundingMode::TiesToEven);
238 let a1 = simple_soft_float::F128::from_bits(a);
239 let b1 = simple_soft_float::F128::from_bits(b);
240 let d1 = a1.div(&b1, Some(simple_soft_float::RoundingMode::TiesToEven), None);
241 assert_eq!(d0.bits(), *d1.bits());
242 }
243
244 #[test]
245 #[ignore]
246 fn f128_rem() {
247 let a = 0x76545678ffffffffffffffffffffffff;
248 let b = 0x12346410aaaaaaaaffffffffffffffff;
249 let a0 = F128::from_bits(a);
250 let b0 = F128::from_bits(b);
251 let d0 = a0.rem(b0, RoundingMode::TiesToEven);
252 let a1 = simple_soft_float::F128::from_bits(a);
253 let b1 = simple_soft_float::F128::from_bits(b);
254 let d1 = a1.ieee754_remainder(&b1, Some(simple_soft_float::RoundingMode::TiesToEven), None);
255 assert_eq!(d0.bits(), *d1.bits());
256 }
257
258 #[test]
259 #[ignore]
260 fn f128_sqrt() {
261 let a = 0x76546410aaaaaaaaffffffffffffffff;
262 let a0 = F128::from_bits(a);
263 let d0 = a0.sqrt(RoundingMode::TiesToEven);
264 let a1 = simple_soft_float::F128::from_bits(a);
265 let d1 = a1.sqrt(Some(simple_soft_float::RoundingMode::TiesToEven), None);
266 assert_eq!(d0.bits(), *d1.bits());
267 }
268
269 #[test]
270 fn f128_compare() {
271 let a = F128::from_bits(0x76546410ffffffffffffffffffffffff);
272 let b = F128::from_bits(0x12345678aaaaaaaaffffffffffffffff);
273 let d = a.compare(b);
274 assert_eq!(d, Some(Ordering::Greater));
275
276 let a = F128::from_bits(0x12345678ffffffffffffffffffffffff);
277 let b = F128::from_bits(0x76546410aaaaaaaaffffffffffffffff);
278 let d = a.compare(b);
279 assert_eq!(d, Some(Ordering::Less));
280
281 let a = F128::from_bits(0x12345678aaaaaaaaffffffffffffffff);
282 let b = F128::from_bits(0x12345678aaaaaaaaffffffffffffffff);
283 let d = a.compare(b);
284 assert_eq!(d, Some(Ordering::Equal));
285 }
286}