1use crate::{Float, RoundingMode, BF16, F16, F32, F64};
2use softfloat_sys::float128_t;
3use std::borrow::Borrow;
4
5#[derive(Copy, Clone, Debug)]
7pub struct F128(float128_t);
8
9impl F128 {
10 pub fn from_f32(v: f32) -> Self {
12 F32::from_bits(v.to_bits()).to_f128(RoundingMode::TiesToEven)
13 }
14
15 pub fn from_f64(v: f64) -> Self {
17 F64::from_bits(v.to_bits()).to_f128(RoundingMode::TiesToEven)
18 }
19}
20
21impl Float for F128 {
22 type Payload = u128;
23
24 const EXPONENT_BIT: Self::Payload = 0x7fff;
25 const FRACTION_BIT: Self::Payload = 0xffff_ffff_ffff_ffff_ffff_ffff_ffff;
26 const SIGN_POS: usize = 127;
27 const EXPONENT_POS: usize = 112;
28
29 #[inline]
30 fn set_payload(&mut self, x: Self::Payload) {
31 let x = [x as u64, (x >> 64) as u64];
32 self.0.v = x;
33 }
34
35 #[inline]
36 fn from_bits(v: Self::Payload) -> Self {
37 let v = [v as u64, (v >> 64) as u64];
38 Self(float128_t { v })
39 }
40
41 #[inline]
42 fn to_bits(&self) -> Self::Payload {
43 let mut ret = 0u128;
44 ret |= self.0.v[0] as u128;
45 ret |= (self.0.v[1] as u128) << 64;
46 ret
47 }
48
49 #[inline]
50 fn bits(&self) -> Self::Payload {
51 self.to_bits()
52 }
53
54 fn add<T: Borrow<Self>>(&self, x: T, rnd: RoundingMode) -> Self {
55 rnd.set();
56 let ret = unsafe { softfloat_sys::f128_add(self.0, x.borrow().0) };
57 Self(ret)
58 }
59
60 fn sub<T: Borrow<Self>>(&self, x: T, rnd: RoundingMode) -> Self {
61 rnd.set();
62 let ret = unsafe { softfloat_sys::f128_sub(self.0, x.borrow().0) };
63 Self(ret)
64 }
65
66 fn mul<T: Borrow<Self>>(&self, x: T, rnd: RoundingMode) -> Self {
67 rnd.set();
68 let ret = unsafe { softfloat_sys::f128_mul(self.0, x.borrow().0) };
69 Self(ret)
70 }
71
72 fn fused_mul_add<T: Borrow<Self>>(&self, x: T, y: T, rnd: RoundingMode) -> Self {
73 rnd.set();
74 let ret = unsafe { softfloat_sys::f128_mulAdd(self.0, x.borrow().0, y.borrow().0) };
75 Self(ret)
76 }
77
78 fn div<T: Borrow<Self>>(&self, x: T, rnd: RoundingMode) -> Self {
79 rnd.set();
80 let ret = unsafe { softfloat_sys::f128_div(self.0, x.borrow().0) };
81 Self(ret)
82 }
83
84 fn rem<T: Borrow<Self>>(&self, x: T, rnd: RoundingMode) -> Self {
85 rnd.set();
86 let ret = unsafe { softfloat_sys::f128_rem(self.0, x.borrow().0) };
87 Self(ret)
88 }
89
90 fn sqrt(&self, rnd: RoundingMode) -> Self {
91 rnd.set();
92 let ret = unsafe { softfloat_sys::f128_sqrt(self.0) };
93 Self(ret)
94 }
95
96 fn eq<T: Borrow<Self>>(&self, x: T) -> bool {
97 unsafe { softfloat_sys::f128_eq(self.0, x.borrow().0) }
98 }
99
100 fn lt<T: Borrow<Self>>(&self, x: T) -> bool {
101 unsafe { softfloat_sys::f128_lt(self.0, x.borrow().0) }
102 }
103
104 fn le<T: Borrow<Self>>(&self, x: T) -> bool {
105 unsafe { softfloat_sys::f128_le(self.0, x.borrow().0) }
106 }
107
108 fn lt_quiet<T: Borrow<Self>>(&self, x: T) -> bool {
109 unsafe { softfloat_sys::f128_lt_quiet(self.0, x.borrow().0) }
110 }
111
112 fn le_quiet<T: Borrow<Self>>(&self, x: T) -> bool {
113 unsafe { softfloat_sys::f128_le_quiet(self.0, x.borrow().0) }
114 }
115
116 fn eq_signaling<T: Borrow<Self>>(&self, x: T) -> bool {
117 unsafe { softfloat_sys::f128_eq_signaling(self.0, x.borrow().0) }
118 }
119
120 fn is_signaling_nan(&self) -> bool {
121 unsafe { softfloat_sys::f128_isSignalingNaN(self.0) }
122 }
123
124 fn from_u32(x: u32, rnd: RoundingMode) -> Self {
125 rnd.set();
126 let ret = unsafe { softfloat_sys::ui32_to_f128(x) };
127 Self(ret)
128 }
129
130 fn from_u64(x: u64, rnd: RoundingMode) -> Self {
131 rnd.set();
132 let ret = unsafe { softfloat_sys::ui64_to_f128(x) };
133 Self(ret)
134 }
135
136 fn from_i32(x: i32, rnd: RoundingMode) -> Self {
137 rnd.set();
138 let ret = unsafe { softfloat_sys::i32_to_f128(x) };
139 Self(ret)
140 }
141
142 fn from_i64(x: i64, rnd: RoundingMode) -> Self {
143 rnd.set();
144 let ret = unsafe { softfloat_sys::i64_to_f128(x) };
145 Self(ret)
146 }
147
148 fn to_u32(&self, rnd: RoundingMode, exact: bool) -> u32 {
149 let ret = unsafe { softfloat_sys::f128_to_ui32(self.0, rnd.to_softfloat(), exact) };
150 ret as u32
151 }
152
153 fn to_u64(&self, rnd: RoundingMode, exact: bool) -> u64 {
154 let ret = unsafe { softfloat_sys::f128_to_ui64(self.0, rnd.to_softfloat(), exact) };
155 ret
156 }
157
158 fn to_i32(&self, rnd: RoundingMode, exact: bool) -> i32 {
159 let ret = unsafe { softfloat_sys::f128_to_i32(self.0, rnd.to_softfloat(), exact) };
160 ret as i32
161 }
162
163 fn to_i64(&self, rnd: RoundingMode, exact: bool) -> i64 {
164 let ret = unsafe { softfloat_sys::f128_to_i64(self.0, rnd.to_softfloat(), exact) };
165 ret
166 }
167
168 fn to_f16(&self, rnd: RoundingMode) -> F16 {
169 rnd.set();
170 let ret = unsafe { softfloat_sys::f128_to_f16(self.0) };
171 F16::from_bits(ret.v)
172 }
173
174 fn to_bf16(&self, rnd: RoundingMode) -> BF16 {
175 rnd.set();
176 let ret = unsafe { softfloat_sys::f128_to_f32(self.0) };
177 BF16::from_bits((ret.v >> 16) as u16)
178 }
179
180 fn to_f32(&self, rnd: RoundingMode) -> F32 {
181 rnd.set();
182 let ret = unsafe { softfloat_sys::f128_to_f32(self.0) };
183 F32::from_bits(ret.v)
184 }
185
186 fn to_f64(&self, rnd: RoundingMode) -> F64 {
187 rnd.set();
188 let ret = unsafe { softfloat_sys::f128_to_f64(self.0) };
189 F64::from_bits(ret.v)
190 }
191
192 fn to_f128(&self, _rnd: RoundingMode) -> F128 {
193 Self::from_bits(self.to_bits())
194 }
195
196 fn round_to_integral(&self, rnd: RoundingMode) -> Self {
197 let ret = unsafe { softfloat_sys::f128_roundToInt(self.0, rnd.to_softfloat(), false) };
198 Self(ret)
199 }
200}
201
202#[cfg(test)]
203mod tests {
204 use super::*;
205 use crate::ExceptionFlags;
206 use std::cmp::Ordering;
207
208 #[test]
209 fn f128_add() {
210 let a = 0x12345678ffffffffffffffffffffffff;
211 let b = 0x76546410aaaaaaaaffffffffffffffff;
212 let a0 = F128::from_bits(a);
213 let b0 = F128::from_bits(b);
214 let d0 = a0.add(b0, RoundingMode::TiesToEven);
215 let a1 = simple_soft_float::F128::from_bits(a);
216 let b1 = simple_soft_float::F128::from_bits(b);
217 let d1 = a1.add(&b1, Some(simple_soft_float::RoundingMode::TiesToEven), None);
218 assert_eq!(d0.to_bits(), *d1.bits());
219 }
220
221 #[test]
222 fn f128_sub() {
223 let a = 0x12345678ffffffffffffffffffffffff;
224 let b = 0x76546410aaaaaaaaffffffffffffffff;
225 let a0 = F128::from_bits(a);
226 let b0 = F128::from_bits(b);
227 let d0 = a0.sub(b0, RoundingMode::TiesToEven);
228 let a1 = simple_soft_float::F128::from_bits(a);
229 let b1 = simple_soft_float::F128::from_bits(b);
230 let d1 = a1.sub(&b1, Some(simple_soft_float::RoundingMode::TiesToEven), None);
231 assert_eq!(d0.to_bits(), *d1.bits());
232 }
233
234 #[test]
235 fn f128_mul() {
236 let a = 0x12345678ffffffffffffffffffffffff;
237 let b = 0x76546410aaaaaaaaffffffffffffffff;
238 let a0 = F128::from_bits(a);
239 let b0 = F128::from_bits(b);
240 let d0 = a0.mul(b0, RoundingMode::TiesToEven);
241 let a1 = simple_soft_float::F128::from_bits(a);
242 let b1 = simple_soft_float::F128::from_bits(b);
243 let d1 = a1.mul(&b1, Some(simple_soft_float::RoundingMode::TiesToEven), None);
244 assert_eq!(d0.to_bits(), *d1.bits());
245 }
246
247 #[test]
248 #[ignore]
249 fn f128_fused_mul_add() {
250 let a = 0x12345678ffffffffffffffffffffffff;
251 let b = 0x12345678aaaaaaaaffffffffffffffff;
252 let c = 0x12345678aaaaaaaaffffffffffffffff;
253 let a0 = F128::from_bits(a);
254 let b0 = F128::from_bits(b);
255 let c0 = F128::from_bits(c);
256 let d0 = a0.fused_mul_add(b0, c0, RoundingMode::TiesToEven);
257 let a1 = simple_soft_float::F128::from_bits(a);
258 let b1 = simple_soft_float::F128::from_bits(b);
259 let c1 = simple_soft_float::F128::from_bits(c);
260 let d1 = a1.fused_mul_add(
261 &b1,
262 &c1,
263 Some(simple_soft_float::RoundingMode::TiesToEven),
264 None,
265 );
266 assert_eq!(d0.to_bits(), *d1.bits());
267 }
268
269 #[test]
270 fn f128_div() {
271 let a = 0x76545678ffffffffffffffffffffffff;
272 let b = 0x12346410aaaaaaaaffffffffffffffff;
273 let a0 = F128::from_bits(a);
274 let b0 = F128::from_bits(b);
275 let d0 = a0.div(b0, RoundingMode::TiesToEven);
276 let a1 = simple_soft_float::F128::from_bits(a);
277 let b1 = simple_soft_float::F128::from_bits(b);
278 let d1 = a1.div(&b1, Some(simple_soft_float::RoundingMode::TiesToEven), None);
279 assert_eq!(d0.to_bits(), *d1.bits());
280 }
281
282 #[test]
283 #[ignore]
284 fn f128_rem() {
285 let a = 0x76545678ffffffffffffffffffffffff;
286 let b = 0x12346410aaaaaaaaffffffffffffffff;
287 let a0 = F128::from_bits(a);
288 let b0 = F128::from_bits(b);
289 let d0 = a0.rem(b0, RoundingMode::TiesToEven);
290 let a1 = simple_soft_float::F128::from_bits(a);
291 let b1 = simple_soft_float::F128::from_bits(b);
292 let d1 = a1.ieee754_remainder(&b1, Some(simple_soft_float::RoundingMode::TiesToEven), None);
293 assert_eq!(d0.to_bits(), *d1.bits());
294 }
295
296 #[test]
297 #[ignore]
298 fn f128_sqrt() {
299 let a = 0x76546410aaaaaaaaffffffffffffffff;
300 let a0 = F128::from_bits(a);
301 let d0 = a0.sqrt(RoundingMode::TiesToEven);
302 let a1 = simple_soft_float::F128::from_bits(a);
303 let d1 = a1.sqrt(Some(simple_soft_float::RoundingMode::TiesToEven), None);
304 assert_eq!(d0.to_bits(), *d1.bits());
305 }
306
307 #[test]
308 fn f128_compare() {
309 let a = F128::from_bits(0x76546410ffffffffffffffffffffffff);
310 let b = F128::from_bits(0x12345678aaaaaaaaffffffffffffffff);
311 let d = a.compare(b);
312 assert_eq!(d, Some(Ordering::Greater));
313
314 let a = F128::from_bits(0x12345678ffffffffffffffffffffffff);
315 let b = F128::from_bits(0x76546410aaaaaaaaffffffffffffffff);
316 let d = a.compare(b);
317 assert_eq!(d, Some(Ordering::Less));
318
319 let a = F128::from_bits(0x12345678aaaaaaaaffffffffffffffff);
320 let b = F128::from_bits(0x12345678aaaaaaaaffffffffffffffff);
321 let d = a.compare(b);
322 assert_eq!(d, Some(Ordering::Equal));
323 }
324
325 #[test]
326 fn f128_signaling() {
327 let a = F128::from_bits(0x7fff0000000000000000000000000001);
328 let b = F128::from_bits(0x7fff8000000000000000000000000001);
329 assert_eq!(a.is_signaling_nan(), true);
330 assert_eq!(b.is_signaling_nan(), false);
331
332 let mut flag = ExceptionFlags::default();
333 flag.set();
334 assert_eq!(a.eq(a), false);
335 flag.get();
336 assert_eq!(flag.is_invalid(), true);
337
338 let mut flag = ExceptionFlags::default();
339 flag.set();
340 assert_eq!(b.eq(b), false);
341 flag.get();
342 assert_eq!(flag.is_invalid(), false);
343
344 let mut flag = ExceptionFlags::default();
345 flag.set();
346 assert_eq!(a.eq_signaling(a), false);
347 flag.get();
348 assert_eq!(flag.is_invalid(), true);
349
350 let mut flag = ExceptionFlags::default();
351 flag.set();
352 assert_eq!(b.eq_signaling(b), false);
353 flag.get();
354 assert_eq!(flag.is_invalid(), true);
355 }
356
357 #[test]
358 fn from_f32() {
359 let a = F128::from_f32(0.1);
360 assert_eq!(a.to_bits(), 0x3ffb99999a0000000000000000000000);
361 }
362
363 #[test]
364 fn from_f64() {
365 let a = F128::from_f64(0.1);
366 assert_eq!(a.to_bits(), 0x3ffb999999999999a000000000000000);
367 }
368}