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