1#![no_std]
97
98#[cfg(feature = "serde")]
99use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
100
101pub mod checkers;
102mod float_impl;
103pub mod types;
104
105pub mod prelude {
112 pub use crate::types::*;
113
114 #[doc(no_inline)]
115 pub use num_traits::Float;
116}
117
118use core::{fmt, marker::PhantomData};
119use num_traits::Float;
120
121pub trait FloatChecker<F> {
125 fn check(value: F) -> bool;
131
132 fn assert(value: F);
136}
137
138#[repr(transparent)]
153pub struct NoisyFloat<F: Float, C: FloatChecker<F>> {
154 value: F,
155 checker: PhantomData<C>,
156}
157
158impl<F: Float, C: FloatChecker<F>> NoisyFloat<F, C> {
159 #[inline]
163 pub fn new(value: F) -> Self {
164 C::assert(value);
165 Self::unchecked_new_generic(value)
166 }
167
168 #[inline]
169 fn unchecked_new_generic(value: F) -> Self {
170 NoisyFloat {
171 value,
172 checker: PhantomData,
173 }
174 }
175
176 #[inline]
180 pub fn try_new(value: F) -> Option<Self> {
181 if C::check(value) {
182 Some(NoisyFloat {
183 value,
184 checker: PhantomData,
185 })
186 } else {
187 None
188 }
189 }
190
191 #[inline]
195 pub fn borrowed(value: &F) -> &Self {
196 C::assert(*value);
197 Self::unchecked_borrowed(value)
198 }
199
200 #[inline]
201 fn unchecked_borrowed(value: &F) -> &Self {
202 unsafe { &*(value as *const F as *const Self) }
205 }
206
207 #[inline]
211 pub fn try_borrowed(value: &F) -> Option<&Self> {
212 if C::check(*value) {
213 Some(Self::unchecked_borrowed(value))
214 } else {
215 None
216 }
217 }
218
219 #[inline]
223 pub fn borrowed_mut(value: &mut F) -> &mut Self {
224 C::assert(*value);
225 Self::unchecked_borrowed_mut(value)
226 }
227
228 #[inline]
229 fn unchecked_borrowed_mut(value: &mut F) -> &mut Self {
230 unsafe { &mut *(value as *mut F as *mut Self) }
233 }
234
235 #[inline]
239 pub fn try_borrowed_mut(value: &mut F) -> Option<&mut Self> {
240 if C::check(*value) {
241 Some(Self::unchecked_borrowed_mut(value))
242 } else {
243 None
244 }
245 }
246
247 #[inline]
253 pub fn from_f32(value: f32) -> Self {
254 Self::new(F::from(value).unwrap())
255 }
256
257 #[inline]
263 pub fn from_f64(value: f64) -> Self {
264 Self::new(F::from(value).unwrap())
265 }
266
267 #[inline]
269 pub fn raw(self) -> F {
270 self.value
271 }
272
273 #[inline]
277 pub fn min(self, other: Self) -> Self {
278 Ord::min(self, other)
279 }
280
281 #[inline]
285 pub fn max(self, other: Self) -> Self {
286 Ord::max(self, other)
287 }
288}
289
290impl<F: Float + Default, C: FloatChecker<F>> Default for NoisyFloat<F, C> {
291 #[inline]
292 fn default() -> Self {
293 Self::new(F::default())
294 }
295}
296
297impl<F: Float + fmt::Debug, C: FloatChecker<F>> fmt::Debug for NoisyFloat<F, C> {
298 #[inline]
299 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
300 fmt::Debug::fmt(&self.value, f)
301 }
302}
303
304impl<F: Float + fmt::Display, C: FloatChecker<F>> fmt::Display for NoisyFloat<F, C> {
305 #[inline]
306 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
307 fmt::Display::fmt(&self.value, f)
308 }
309}
310
311impl<F: Float + fmt::LowerExp, C: FloatChecker<F>> fmt::LowerExp for NoisyFloat<F, C> {
312 #[inline]
313 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
314 fmt::LowerExp::fmt(&self.value, f)
315 }
316}
317
318impl<F: Float + fmt::UpperExp, C: FloatChecker<F>> fmt::UpperExp for NoisyFloat<F, C> {
319 #[inline]
320 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
321 fmt::UpperExp::fmt(&self.value, f)
322 }
323}
324
325#[cfg(feature = "serde")]
326impl<F: Float + Serialize, C: FloatChecker<F>> Serialize for NoisyFloat<F, C> {
327 fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
328 self.value.serialize(ser)
329 }
330}
331
332#[cfg(feature = "serde")]
333impl<'de, F: Float + Deserialize<'de>, C: FloatChecker<F>> Deserialize<'de> for NoisyFloat<F, C> {
334 fn deserialize<D: Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
335 let value = F::deserialize(de)?;
336 Self::try_new(value).ok_or_else(|| D::Error::custom("invalid NoisyFloat"))
337 }
338}
339
340#[cfg(test)]
341mod tests {
342 extern crate std;
343 use std::prelude::v1::*;
344
345 use crate::prelude::*;
346 #[cfg(feature = "serde")]
347 use serde_derive::{Deserialize, Serialize};
348 #[cfg(feature = "serde")]
349 use serde_json;
350 use std::{
351 f32,
352 f64::{self, consts},
353 hash::{Hash, Hasher},
354 mem::{align_of, size_of},
355 };
356
357 #[test]
358 fn smoke_test() {
359 assert_eq!(n64(1.0) + 2.0, 3.0);
360 assert_ne!(n64(3.0), n64(2.9));
361 assert!(r64(1.0) < 2.0);
362 let mut value = n64(18.0);
363 value %= n64(5.0);
364 assert_eq!(-value, n64(-3.0));
365 assert_eq!(r64(1.0).exp(), consts::E);
366 assert_eq!((N64::try_new(1.0).unwrap() / N64::infinity()), 0.0);
367 assert_eq!(N64::from_f32(f32::INFINITY), N64::from_f64(f64::INFINITY));
368 assert_eq!(R64::try_new(f64::NEG_INFINITY), None);
369 assert_eq!(N64::try_new(f64::NAN), None);
370 assert_eq!(R64::try_new(f64::NAN), None);
371 assert_eq!(N64::try_borrowed(&f64::NAN), None);
372 let mut nan = f64::NAN;
373 assert_eq!(N64::try_borrowed_mut(&mut nan), None);
374 }
375
376 #[test]
377 fn ensure_layout() {
378 assert_eq!(size_of::<N32>(), size_of::<f32>());
379 assert_eq!(align_of::<N32>(), align_of::<f32>());
380
381 assert_eq!(size_of::<N64>(), size_of::<f64>());
382 assert_eq!(align_of::<N64>(), align_of::<f64>());
383 }
384
385 #[test]
386 fn borrowed_casts() {
387 assert_eq!(R64::borrowed(&3.14), &3.14);
388 assert_eq!(N64::borrowed(&[f64::INFINITY; 2][0]), &f64::INFINITY);
389 assert_eq!(N64::borrowed_mut(&mut 2.72), &mut 2.72);
390 }
391
392 #[test]
393 fn test_convert() {
394 assert_eq!(f32::from(r32(3.0)), 3.0f32);
395 assert_eq!(f64::from(r32(5.0)), 5.0f64);
396 assert_eq!(f64::from(r64(7.0)), 7.0f64);
397 }
398
399 #[test]
400 #[cfg(debug_assertions)]
401 #[should_panic]
402 fn n64_nan() {
403 let _ = n64(0.0) / n64(0.0);
404 }
405
406 #[test]
407 #[cfg(debug_assertions)]
408 #[should_panic]
409 fn r64_nan() {
410 let _ = r64(0.0) / r64(0.0);
411 }
412
413 #[test]
414 #[cfg(debug_assertions)]
415 #[should_panic]
416 fn r64_infinity() {
417 let _ = r64(1.0) / r64(0.0);
418 }
419
420 #[test]
421 fn resolves_min_max() {
422 assert_eq!(r64(1.0).min(r64(3.0)), r64(1.0));
423 assert_eq!(r64(1.0).max(r64(3.0)), r64(3.0));
424 }
425
426 #[test]
427 fn epsilon() {
428 assert_eq!(R32::epsilon(), f32::EPSILON);
429 assert_eq!(R64::epsilon(), f64::EPSILON);
430 }
431
432 #[test]
433 fn test_try_into() {
434 use std::convert::{TryFrom, TryInto};
435 let _: R64 = 1.0.try_into().unwrap();
436 let _ = R64::try_from(f64::INFINITY).unwrap_err();
437 }
438
439 struct TestHasher {
440 bytes: Vec<u8>,
441 }
442
443 impl Hasher for TestHasher {
444 fn finish(&self) -> u64 {
445 panic!("unexpected Hasher.finish invocation")
446 }
447 fn write(&mut self, bytes: &[u8]) {
448 self.bytes.extend_from_slice(bytes)
449 }
450 }
451
452 fn hash_bytes<T: Hash>(value: T) -> Vec<u8> {
453 let mut hasher = TestHasher { bytes: Vec::new() };
454 value.hash(&mut hasher);
455 hasher.bytes
456 }
457
458 #[test]
459 fn test_hash() {
460 assert_eq!(hash_bytes(r64(10.3)), hash_bytes(10.3f64.to_bits()));
461 assert_ne!(hash_bytes(r64(10.3)), hash_bytes(10.4f64.to_bits()));
462 assert_eq!(hash_bytes(r32(10.3)), hash_bytes(10.3f32.to_bits()));
463 assert_ne!(hash_bytes(r32(10.3)), hash_bytes(10.4f32.to_bits()));
464
465 assert_eq!(
466 hash_bytes(N64::infinity()),
467 hash_bytes(f64::INFINITY.to_bits())
468 );
469 assert_eq!(
470 hash_bytes(N64::neg_infinity()),
471 hash_bytes(f64::NEG_INFINITY.to_bits())
472 );
473
474 assert_eq!(hash_bytes(r64(0.0)), hash_bytes(0.0f64.to_bits()));
476 assert_eq!(hash_bytes(r64(-0.0)), hash_bytes(0.0f64.to_bits()));
477 assert_eq!(hash_bytes(r32(0.0)), hash_bytes(0.0f32.to_bits()));
478 assert_eq!(hash_bytes(r32(-0.0)), hash_bytes(0.0f32.to_bits()));
479 }
480
481 #[cfg(feature = "serde")]
482 #[test]
483 fn serialize_transparently_as_float() {
484 let num = R32::new(3.14);
485 let should_be = "3.14";
486
487 let got = serde_json::to_string(&num).unwrap();
488 assert_eq!(got, should_be);
489 }
490
491 #[cfg(feature = "serde")]
492 #[test]
493 fn deserialize_transparently_as_float() {
494 let src = "3.14";
495 let should_be = R32::new(3.14);
496
497 let got: R32 = serde_json::from_str(src).unwrap();
498 assert_eq!(got, should_be);
499 }
500
501 #[cfg(feature = "serde")]
502 #[test]
503 fn deserialize_invalid_float() {
504 use crate::{FloatChecker, NoisyFloat};
505 struct PositiveChecker;
506 impl FloatChecker<f64> for PositiveChecker {
507 fn check(value: f64) -> bool {
508 value > 0.
509 }
510 fn assert(value: f64) {
511 debug_assert!(Self::check(value))
512 }
513 }
514
515 let src = "-1.0";
516 let got: Result<NoisyFloat<f64, PositiveChecker>, _> = serde_json::from_str(src);
517 assert!(got.is_err());
518 }
519
520 #[cfg(feature = "serde")]
522 #[derive(Debug, PartialEq, Serialize, Deserialize)]
523 struct Dummy {
524 value: N64,
525 }
526
527 #[cfg(feature = "serde")]
528 #[test]
529 fn deserialize_struct_containing_n64() {
530 let src = r#"{ "value": 3.14 }"#;
531 let should_be = Dummy { value: n64(3.14) };
532
533 let got: Dummy = serde_json::from_str(src).unwrap();
534 assert_eq!(got, should_be);
535 }
536
537 #[cfg(feature = "serde")]
538 #[test]
539 fn serialize_struct_containing_n64() {
540 let src = Dummy { value: n64(3.14) };
541 let should_be = r#"{"value":3.14}"#;
542
543 let got = serde_json::to_string(&src).unwrap();
544 assert_eq!(got, should_be);
545 }
546
547 #[cfg(feature = "approx")]
548 #[test]
549 fn approx_assert_eq() {
550 use approx::{assert_abs_diff_eq, assert_relative_eq, assert_ulps_eq};
551
552 let lhs = r64(0.1000000000000001);
553 let rhs = r64(0.1);
554
555 assert_abs_diff_eq!(lhs, rhs);
556 assert_relative_eq!(lhs, rhs);
557 assert_ulps_eq!(lhs, rhs);
558 }
559
560 #[test]
561 fn const_functions() {
562 const A: N32 = N32::unchecked_new(1.0);
563 const B: N64 = N64::unchecked_new(2.0);
564 const C: R32 = R32::unchecked_new(3.0);
565 const D: R64 = R64::unchecked_new(4.0);
566
567 const A_RAW: f32 = A.const_raw();
568 const B_RAW: f64 = B.const_raw();
569 const C_RAW: f32 = C.const_raw();
570 const D_RAW: f64 = D.const_raw();
571
572 assert_eq!(A_RAW, 1.0);
573 assert_eq!(B_RAW, 2.0);
574 assert_eq!(C_RAW, 3.0);
575 assert_eq!(D_RAW, 4.0);
576 }
577}