test.rs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. #![allow(clippy::float_cmp, clippy::eq_op, clippy::op_ref)]
  2. extern crate num_traits;
  3. extern crate ordered_float;
  4. #[cfg(not(feature = "std"))]
  5. pub use num_traits::float::FloatCore as Float;
  6. #[cfg(feature = "std")]
  7. pub use num_traits::Float;
  8. pub use num_traits::{Bounded, FromPrimitive, Num, One, Signed, ToPrimitive, Zero};
  9. pub use ordered_float::*;
  10. pub use std::cmp::Ordering::*;
  11. pub use std::convert::TryFrom;
  12. pub use std::{f32, f64, panic};
  13. pub use std::collections::hash_map::RandomState;
  14. pub use std::collections::HashSet;
  15. pub use std::hash::*;
  16. fn not_nan<T: Float>(x: T) -> NotNan<T> {
  17. NotNan::new(x).unwrap()
  18. }
  19. #[test]
  20. fn ordered_f32_compare_regular_floats() {
  21. assert_eq!(OrderedFloat(7.0f32).cmp(&OrderedFloat(7.0)), Equal);
  22. assert_eq!(OrderedFloat(8.0f32).cmp(&OrderedFloat(7.0)), Greater);
  23. assert_eq!(OrderedFloat(4.0f32).cmp(&OrderedFloat(7.0)), Less);
  24. }
  25. #[test]
  26. fn ordered_f32_compare_regular_floats_op() {
  27. assert!(OrderedFloat(7.0f32) == OrderedFloat(7.0));
  28. assert!(OrderedFloat(7.0f32) <= OrderedFloat(7.0));
  29. assert!(OrderedFloat(7.0f32) >= OrderedFloat(7.0));
  30. assert!(OrderedFloat(8.0f32) > OrderedFloat(7.0));
  31. assert!(OrderedFloat(8.0f32) >= OrderedFloat(7.0));
  32. assert!(OrderedFloat(4.0f32) < OrderedFloat(7.0));
  33. assert!(OrderedFloat(4.0f32) <= OrderedFloat(7.0));
  34. }
  35. #[test]
  36. fn ordered_f32_compare_nan() {
  37. let f32_nan: f32 = Float::nan();
  38. assert_eq!(
  39. OrderedFloat(f32_nan).cmp(&OrderedFloat(Float::nan())),
  40. Equal
  41. );
  42. assert_eq!(
  43. OrderedFloat(f32_nan).cmp(&OrderedFloat(-100000.0f32)),
  44. Greater
  45. );
  46. assert_eq!(
  47. OrderedFloat(-100.0f32).cmp(&OrderedFloat(Float::nan())),
  48. Less
  49. );
  50. }
  51. #[test]
  52. fn ordered_f32_compare_nan_op() {
  53. let f32_nan: OrderedFloat<f32> = OrderedFloat(Float::nan());
  54. assert!(f32_nan == f32_nan);
  55. assert!(f32_nan <= f32_nan);
  56. assert!(f32_nan >= f32_nan);
  57. assert!(f32_nan > OrderedFloat(-100000.0f32));
  58. assert!(f32_nan >= OrderedFloat(-100000.0f32));
  59. assert!(OrderedFloat(-100.0f32) < f32_nan);
  60. assert!(OrderedFloat(-100.0f32) <= f32_nan);
  61. assert!(f32_nan > OrderedFloat(Float::infinity()));
  62. assert!(f32_nan >= OrderedFloat(Float::infinity()));
  63. assert!(f32_nan > OrderedFloat(Float::neg_infinity()));
  64. assert!(f32_nan >= OrderedFloat(Float::neg_infinity()));
  65. }
  66. #[test]
  67. fn ordered_f64_compare_regular_floats() {
  68. assert_eq!(OrderedFloat(7.0f64).cmp(&OrderedFloat(7.0)), Equal);
  69. assert_eq!(OrderedFloat(8.0f64).cmp(&OrderedFloat(7.0)), Greater);
  70. assert_eq!(OrderedFloat(4.0f64).cmp(&OrderedFloat(7.0)), Less);
  71. }
  72. #[test]
  73. fn not_nan32_zero() {
  74. assert_eq!(NotNan::<f32>::zero(), 0.0f32);
  75. assert!(NotNan::<f32>::zero().is_zero());
  76. }
  77. #[test]
  78. fn not_nan32_one() {
  79. assert_eq!(NotNan::<f32>::one(), 1.0f32)
  80. }
  81. #[test]
  82. fn not_nan32_bounded() {
  83. assert_eq!(NotNan::<f32>::min_value(), <f32 as Bounded>::min_value());
  84. assert_eq!(NotNan::<f32>::max_value(), <f32 as Bounded>::max_value());
  85. }
  86. #[test]
  87. fn not_nan32_from_primitive() {
  88. assert_eq!(NotNan::<f32>::from_i8(42i8), Some(not_nan(42.0)));
  89. assert_eq!(NotNan::<f32>::from_u8(42u8), Some(not_nan(42.0)));
  90. assert_eq!(NotNan::<f32>::from_i16(42i16), Some(not_nan(42.0)));
  91. assert_eq!(NotNan::<f32>::from_u16(42u16), Some(not_nan(42.0)));
  92. assert_eq!(NotNan::<f32>::from_i32(42i32), Some(not_nan(42.0)));
  93. assert_eq!(NotNan::<f32>::from_u32(42u32), Some(not_nan(42.0)));
  94. assert_eq!(NotNan::<f32>::from_i64(42i64), Some(not_nan(42.0)));
  95. assert_eq!(NotNan::<f32>::from_u64(42u64), Some(not_nan(42.0)));
  96. assert_eq!(NotNan::<f32>::from_isize(42isize), Some(not_nan(42.0)));
  97. assert_eq!(NotNan::<f32>::from_usize(42usize), Some(not_nan(42.0)));
  98. assert_eq!(NotNan::<f32>::from_f32(42f32), Some(not_nan(42.0)));
  99. assert_eq!(NotNan::<f32>::from_f32(42f32), Some(not_nan(42.0)));
  100. assert_eq!(NotNan::<f32>::from_f64(42f64), Some(not_nan(42.0)));
  101. assert_eq!(NotNan::<f32>::from_f64(42f64), Some(not_nan(42.0)));
  102. assert_eq!(NotNan::<f32>::from_f32(Float::nan()), None);
  103. assert_eq!(NotNan::<f32>::from_f64(Float::nan()), None);
  104. }
  105. #[test]
  106. fn not_nan32_to_primitive() {
  107. let x = not_nan(42.0f32);
  108. assert_eq!(x.to_u8(), Some(42u8));
  109. assert_eq!(x.to_i8(), Some(42i8));
  110. assert_eq!(x.to_u16(), Some(42u16));
  111. assert_eq!(x.to_i16(), Some(42i16));
  112. assert_eq!(x.to_u32(), Some(42u32));
  113. assert_eq!(x.to_i32(), Some(42i32));
  114. assert_eq!(x.to_u64(), Some(42u64));
  115. assert_eq!(x.to_i64(), Some(42i64));
  116. assert_eq!(x.to_usize(), Some(42usize));
  117. assert_eq!(x.to_isize(), Some(42isize));
  118. assert_eq!(x.to_f32(), Some(42f32));
  119. assert_eq!(x.to_f32(), Some(42f32));
  120. assert_eq!(x.to_f64(), Some(42f64));
  121. assert_eq!(x.to_f64(), Some(42f64));
  122. }
  123. #[test]
  124. fn not_nan32_num() {
  125. assert_eq!(NotNan::<f32>::from_str_radix("42.0", 10).unwrap(), 42.0f32);
  126. assert!(NotNan::<f32>::from_str_radix("NaN", 10).is_err());
  127. }
  128. #[test]
  129. fn not_nan32_signed() {
  130. assert_eq!(not_nan(42f32).abs(), 42f32);
  131. assert_eq!(not_nan(-42f32).abs(), 42f32);
  132. assert_eq!(not_nan(50f32).abs_sub(&not_nan(8f32)), 42f32);
  133. assert_eq!(not_nan(8f32).abs_sub(&not_nan(50f32)), 0f32);
  134. }
  135. #[test]
  136. fn not_nan32_num_cast() {
  137. assert_eq!(
  138. <NotNan<f32> as num_traits::NumCast>::from(42).unwrap(),
  139. 42f32
  140. );
  141. assert_eq!(<NotNan<f32> as num_traits::NumCast>::from(f32::nan()), None);
  142. }
  143. #[test]
  144. fn ordered_f64_compare_nan() {
  145. let f64_nan: f64 = Float::nan();
  146. assert_eq!(
  147. OrderedFloat(f64_nan).cmp(&OrderedFloat(Float::nan())),
  148. Equal
  149. );
  150. assert_eq!(
  151. OrderedFloat(f64_nan).cmp(&OrderedFloat(-100000.0f64)),
  152. Greater
  153. );
  154. assert_eq!(
  155. OrderedFloat(-100.0f64).cmp(&OrderedFloat(Float::nan())),
  156. Less
  157. );
  158. }
  159. #[test]
  160. fn ordered_f64_compare_regular_floats_op() {
  161. assert!(OrderedFloat(7.0) == OrderedFloat(7.0));
  162. assert!(OrderedFloat(7.0) <= OrderedFloat(7.0));
  163. assert!(OrderedFloat(7.0) >= OrderedFloat(7.0));
  164. assert!(OrderedFloat(8.0) > OrderedFloat(7.0));
  165. assert!(OrderedFloat(8.0) >= OrderedFloat(7.0));
  166. assert!(OrderedFloat(4.0) < OrderedFloat(7.0));
  167. assert!(OrderedFloat(4.0) <= OrderedFloat(7.0));
  168. }
  169. #[test]
  170. fn ordered_f64_compare_nan_op() {
  171. let f64_nan: OrderedFloat<f64> = OrderedFloat(Float::nan());
  172. assert!(f64_nan == f64_nan);
  173. assert!(f64_nan <= f64_nan);
  174. assert!(f64_nan >= f64_nan);
  175. assert!(f64_nan > OrderedFloat(-100000.0));
  176. assert!(f64_nan >= OrderedFloat(-100000.0));
  177. assert!(OrderedFloat(-100.0) < f64_nan);
  178. assert!(OrderedFloat(-100.0) <= f64_nan);
  179. assert!(f64_nan > OrderedFloat(Float::infinity()));
  180. assert!(f64_nan >= OrderedFloat(Float::infinity()));
  181. assert!(f64_nan > OrderedFloat(Float::neg_infinity()));
  182. assert!(f64_nan >= OrderedFloat(Float::neg_infinity()));
  183. }
  184. #[test]
  185. fn not_nan32_compare_regular_floats() {
  186. assert_eq!(not_nan(7.0f32).cmp(&not_nan(7.0)), Equal);
  187. assert_eq!(not_nan(8.0f32).cmp(&not_nan(7.0)), Greater);
  188. assert_eq!(not_nan(4.0f32).cmp(&not_nan(7.0)), Less);
  189. }
  190. #[test]
  191. fn not_nan32_fail_when_constructing_with_nan() {
  192. let f32_nan: f32 = Float::nan();
  193. assert!(NotNan::new(f32_nan).is_err());
  194. }
  195. #[test]
  196. fn not_nan32_calculate_correctly() {
  197. assert_eq!(*(not_nan(5.0f32) + not_nan(4.0f32)), 5.0f32 + 4.0f32);
  198. assert_eq!(*(not_nan(5.0f32) + 4.0f32), 5.0f32 + 4.0f32);
  199. assert_eq!(*(not_nan(5.0f32) - not_nan(4.0f32)), 5.0f32 - 4.0f32);
  200. assert_eq!(*(not_nan(5.0f32) - 4.0f32), 5.0f32 - 4.0f32);
  201. assert_eq!(*(not_nan(5.0f32) * not_nan(4.0f32)), 5.0f32 * 4.0f32);
  202. assert_eq!(*(not_nan(5.0f32) * 4.0f32), 5.0f32 * 4.0f32);
  203. assert_eq!(*(not_nan(8.0f32) / not_nan(4.0f32)), 8.0f32 / 4.0f32);
  204. assert_eq!(*(not_nan(8.0f32) / 4.0f32), 8.0f32 / 4.0f32);
  205. assert_eq!(*(not_nan(8.0f32) % not_nan(4.0f32)), 8.0f32 % 4.0f32);
  206. assert_eq!(*(not_nan(8.0f32) % 4.0f32), 8.0f32 % 4.0f32);
  207. assert_eq!(*(-not_nan(1.0f32)), -1.0f32);
  208. assert!(panic::catch_unwind(|| not_nan(0.0f32) + f32::NAN).is_err());
  209. assert!(panic::catch_unwind(|| not_nan(0.0f32) - f32::NAN).is_err());
  210. assert!(panic::catch_unwind(|| not_nan(0.0f32) * f32::NAN).is_err());
  211. assert!(panic::catch_unwind(|| not_nan(0.0f32) / f32::NAN).is_err());
  212. assert!(panic::catch_unwind(|| not_nan(0.0f32) % f32::NAN).is_err());
  213. let mut number = not_nan(5.0f32);
  214. number += not_nan(4.0f32);
  215. assert_eq!(*number, 9.0f32);
  216. number -= not_nan(4.0f32);
  217. assert_eq!(*number, 5.0f32);
  218. number *= not_nan(4.0f32);
  219. assert_eq!(*number, 20.0f32);
  220. number /= not_nan(4.0f32);
  221. assert_eq!(*number, 5.0f32);
  222. number %= not_nan(4.0f32);
  223. assert_eq!(*number, 1.0f32);
  224. number = not_nan(5.0f32);
  225. number += 4.0f32;
  226. assert_eq!(*number, 9.0f32);
  227. number -= 4.0f32;
  228. assert_eq!(*number, 5.0f32);
  229. number *= 4.0f32;
  230. assert_eq!(*number, 20.0f32);
  231. number /= 4.0f32;
  232. assert_eq!(*number, 5.0f32);
  233. number %= 4.0f32;
  234. assert_eq!(*number, 1.0f32);
  235. assert!(panic::catch_unwind(|| {
  236. let mut tmp = not_nan(0.0f32);
  237. tmp += f32::NAN;
  238. })
  239. .is_err());
  240. assert!(panic::catch_unwind(|| {
  241. let mut tmp = not_nan(0.0f32);
  242. tmp -= f32::NAN;
  243. })
  244. .is_err());
  245. assert!(panic::catch_unwind(|| {
  246. let mut tmp = not_nan(0.0f32);
  247. tmp *= f32::NAN;
  248. })
  249. .is_err());
  250. assert!(panic::catch_unwind(|| {
  251. let mut tmp = not_nan(0.0f32);
  252. tmp /= f32::NAN;
  253. })
  254. .is_err());
  255. assert!(panic::catch_unwind(|| {
  256. let mut tmp = not_nan(0.0f32);
  257. tmp %= f32::NAN;
  258. })
  259. .is_err());
  260. }
  261. #[test]
  262. fn not_nan64_compare_regular_floats() {
  263. assert_eq!(not_nan(7.0f64).cmp(&not_nan(7.0)), Equal);
  264. assert_eq!(not_nan(8.0f64).cmp(&not_nan(7.0)), Greater);
  265. assert_eq!(not_nan(4.0f64).cmp(&not_nan(7.0)), Less);
  266. }
  267. #[test]
  268. fn not_nan64_fail_when_constructing_with_nan() {
  269. let f64_nan: f64 = Float::nan();
  270. assert!(NotNan::new(f64_nan).is_err());
  271. }
  272. #[test]
  273. fn not_nan64_calculate_correctly() {
  274. assert_eq!(*(not_nan(5.0f64) + not_nan(4.0f64)), 5.0f64 + 4.0f64);
  275. assert_eq!(*(not_nan(5.0f64) + 4.0f64), 5.0f64 + 4.0f64);
  276. assert_eq!(*(not_nan(5.0f64) - not_nan(4.0f64)), 5.0f64 - 4.0f64);
  277. assert_eq!(*(not_nan(5.0f64) - 4.0f64), 5.0f64 - 4.0f64);
  278. assert_eq!(*(not_nan(5.0f64) * not_nan(4.0f64)), 5.0f64 * 4.0f64);
  279. assert_eq!(*(not_nan(5.0f64) * 4.0f64), 5.0f64 * 4.0f64);
  280. assert_eq!(*(not_nan(8.0f64) / not_nan(4.0f64)), 8.0f64 / 4.0f64);
  281. assert_eq!(*(not_nan(8.0f64) / 4.0f64), 8.0f64 / 4.0f64);
  282. assert_eq!(*(not_nan(8.0f64) % not_nan(4.0f64)), 8.0f64 % 4.0f64);
  283. assert_eq!(*(not_nan(8.0f64) % 4.0f64), 8.0f64 % 4.0f64);
  284. assert_eq!(*(-not_nan(1.0f64)), -1.0f64);
  285. assert!(panic::catch_unwind(|| not_nan(0.0f64) + f64::NAN).is_err());
  286. assert!(panic::catch_unwind(|| not_nan(0.0f64) - f64::NAN).is_err());
  287. assert!(panic::catch_unwind(|| not_nan(0.0f64) * f64::NAN).is_err());
  288. assert!(panic::catch_unwind(|| not_nan(0.0f64) / f64::NAN).is_err());
  289. assert!(panic::catch_unwind(|| not_nan(0.0f64) % f64::NAN).is_err());
  290. let mut number = not_nan(5.0f64);
  291. number += not_nan(4.0f64);
  292. assert_eq!(*number, 9.0f64);
  293. number -= not_nan(4.0f64);
  294. assert_eq!(*number, 5.0f64);
  295. number *= not_nan(4.0f64);
  296. assert_eq!(*number, 20.0f64);
  297. number /= not_nan(4.0f64);
  298. assert_eq!(*number, 5.0f64);
  299. number %= not_nan(4.0f64);
  300. assert_eq!(*number, 1.0f64);
  301. number = not_nan(5.0f64);
  302. number += 4.0f64;
  303. assert_eq!(*number, 9.0f64);
  304. number -= 4.0f64;
  305. assert_eq!(*number, 5.0f64);
  306. number *= 4.0f64;
  307. assert_eq!(*number, 20.0f64);
  308. number /= 4.0f64;
  309. assert_eq!(*number, 5.0f64);
  310. number %= 4.0f64;
  311. assert_eq!(*number, 1.0f64);
  312. assert!(panic::catch_unwind(|| {
  313. let mut tmp = not_nan(0.0f64);
  314. tmp += f64::NAN;
  315. })
  316. .is_err());
  317. assert!(panic::catch_unwind(|| {
  318. let mut tmp = not_nan(0.0f64);
  319. tmp -= f64::NAN;
  320. })
  321. .is_err());
  322. assert!(panic::catch_unwind(|| {
  323. let mut tmp = not_nan(0.0f64);
  324. tmp *= f64::NAN;
  325. })
  326. .is_err());
  327. assert!(panic::catch_unwind(|| {
  328. let mut tmp = not_nan(0.0f64);
  329. tmp /= f64::NAN;
  330. })
  331. .is_err());
  332. assert!(panic::catch_unwind(|| {
  333. let mut tmp = not_nan(0.0f64);
  334. tmp %= f64::NAN;
  335. })
  336. .is_err());
  337. }
  338. #[test]
  339. fn not_nan64_zero() {
  340. assert_eq!(NotNan::<f64>::zero(), not_nan(0.0f64));
  341. assert!(NotNan::<f64>::zero().is_zero());
  342. }
  343. #[test]
  344. fn not_nan64_one() {
  345. assert_eq!(NotNan::<f64>::one(), not_nan(1.0f64))
  346. }
  347. #[test]
  348. fn not_nan64_bounded() {
  349. assert_eq!(NotNan::<f64>::min_value(), <f64 as Bounded>::min_value());
  350. assert_eq!(NotNan::<f64>::max_value(), <f64 as Bounded>::max_value());
  351. }
  352. #[test]
  353. fn not_nan64_from_primitive() {
  354. assert_eq!(NotNan::<f64>::from_i8(42i8), Some(not_nan(42.0)));
  355. assert_eq!(NotNan::<f64>::from_u8(42u8), Some(not_nan(42.0)));
  356. assert_eq!(NotNan::<f64>::from_i16(42i16), Some(not_nan(42.0)));
  357. assert_eq!(NotNan::<f64>::from_u16(42u16), Some(not_nan(42.0)));
  358. assert_eq!(NotNan::<f64>::from_i32(42i32), Some(not_nan(42.0)));
  359. assert_eq!(NotNan::<f64>::from_u32(42u32), Some(not_nan(42.0)));
  360. assert_eq!(NotNan::<f64>::from_i64(42i64), Some(not_nan(42.0)));
  361. assert_eq!(NotNan::<f64>::from_u64(42u64), Some(not_nan(42.0)));
  362. assert_eq!(NotNan::<f64>::from_isize(42isize), Some(not_nan(42.0)));
  363. assert_eq!(NotNan::<f64>::from_usize(42usize), Some(not_nan(42.0)));
  364. assert_eq!(NotNan::<f64>::from_f64(42f64), Some(not_nan(42.0)));
  365. assert_eq!(NotNan::<f64>::from_f64(42f64), Some(not_nan(42.0)));
  366. assert_eq!(NotNan::<f64>::from_f64(42f64), Some(not_nan(42.0)));
  367. assert_eq!(NotNan::<f64>::from_f64(42f64), Some(not_nan(42.0)));
  368. assert_eq!(NotNan::<f64>::from_f64(Float::nan()), None);
  369. assert_eq!(NotNan::<f64>::from_f64(Float::nan()), None);
  370. }
  371. #[test]
  372. fn not_nan64_to_primitive() {
  373. let x = not_nan(42.0f64);
  374. assert_eq!(x.to_u8(), Some(42u8));
  375. assert_eq!(x.to_i8(), Some(42i8));
  376. assert_eq!(x.to_u16(), Some(42u16));
  377. assert_eq!(x.to_i16(), Some(42i16));
  378. assert_eq!(x.to_u32(), Some(42u32));
  379. assert_eq!(x.to_i32(), Some(42i32));
  380. assert_eq!(x.to_u64(), Some(42u64));
  381. assert_eq!(x.to_i64(), Some(42i64));
  382. assert_eq!(x.to_usize(), Some(42usize));
  383. assert_eq!(x.to_isize(), Some(42isize));
  384. assert_eq!(x.to_f64(), Some(42f64));
  385. assert_eq!(x.to_f64(), Some(42f64));
  386. assert_eq!(x.to_f64(), Some(42f64));
  387. assert_eq!(x.to_f64(), Some(42f64));
  388. }
  389. #[test]
  390. fn not_nan64_num() {
  391. assert_eq!(
  392. NotNan::<f64>::from_str_radix("42.0", 10).unwrap(),
  393. not_nan(42.0f64)
  394. );
  395. assert!(NotNan::<f64>::from_str_radix("NaN", 10).is_err());
  396. }
  397. #[test]
  398. fn not_nan64_signed() {
  399. assert_eq!(not_nan(42f64).abs(), not_nan(42f64));
  400. assert_eq!(not_nan(-42f64).abs(), not_nan(42f64));
  401. assert_eq!(not_nan(50f64).abs_sub(&not_nan(8f64)), not_nan(42f64));
  402. assert_eq!(not_nan(8f64).abs_sub(&not_nan(50f64)), not_nan(0f64));
  403. }
  404. #[test]
  405. fn not_nan64_num_cast() {
  406. assert_eq!(
  407. <NotNan<f64> as num_traits::NumCast>::from(42),
  408. Some(not_nan(42f64))
  409. );
  410. assert_eq!(<NotNan<f64> as num_traits::NumCast>::from(f64::nan()), None);
  411. }
  412. #[test]
  413. fn hash_zero_and_neg_zero_to_the_same_hc() {
  414. let state = RandomState::new();
  415. let mut h1 = state.build_hasher();
  416. let mut h2 = state.build_hasher();
  417. OrderedFloat::from(0f64).hash(&mut h1);
  418. OrderedFloat::from(-0f64).hash(&mut h2);
  419. assert_eq!(h1.finish(), h2.finish());
  420. }
  421. #[test]
  422. fn hash_inf_and_neg_inf_to_different_hcs() {
  423. let state = RandomState::new();
  424. let mut h1 = state.build_hasher();
  425. let mut h2 = state.build_hasher();
  426. OrderedFloat::from(f64::INFINITY).hash(&mut h1);
  427. OrderedFloat::from(f64::NEG_INFINITY).hash(&mut h2);
  428. assert!(h1.finish() != h2.finish());
  429. }
  430. #[test]
  431. fn hash_is_good_for_whole_numbers() {
  432. let state = RandomState::new();
  433. let limit = 10000;
  434. let mut set = ::std::collections::HashSet::with_capacity(limit);
  435. for i in 0..limit {
  436. let mut h = state.build_hasher();
  437. OrderedFloat::from(i as f64).hash(&mut h);
  438. set.insert(h.finish());
  439. }
  440. // This allows 100 collisions, which is far too
  441. // many, but should guard against transient issues
  442. // that will result from using RandomState
  443. let pct_unique = set.len() as f64 / limit as f64;
  444. assert!(0.99f64 < pct_unique, "percent-unique={}", pct_unique);
  445. }
  446. #[test]
  447. fn hash_is_good_for_fractional_numbers() {
  448. let state = RandomState::new();
  449. let limit = 10000;
  450. let mut set = ::std::collections::HashSet::with_capacity(limit);
  451. for i in 0..limit {
  452. let mut h = state.build_hasher();
  453. OrderedFloat::from(i as f64 * (1f64 / limit as f64)).hash(&mut h);
  454. set.insert(h.finish());
  455. }
  456. // This allows 100 collisions, which is far too
  457. // many, but should guard against transient issues
  458. // that will result from using RandomState
  459. let pct_unique = set.len() as f64 / limit as f64;
  460. assert!(0.99f64 < pct_unique, "percent-unique={}", pct_unique);
  461. }
  462. #[test]
  463. #[should_panic]
  464. fn test_add_fails_on_nan() {
  465. let a = not_nan(std::f32::INFINITY);
  466. let b = not_nan(std::f32::NEG_INFINITY);
  467. let _c = a + b;
  468. }
  469. #[test]
  470. #[should_panic]
  471. fn test_add_fails_on_nan_ref() {
  472. let a = not_nan(std::f32::INFINITY);
  473. let b = not_nan(std::f32::NEG_INFINITY);
  474. let _c = a + &b;
  475. }
  476. #[test]
  477. #[should_panic]
  478. fn test_add_fails_on_nan_ref_ref() {
  479. let a = not_nan(std::f32::INFINITY);
  480. let b = not_nan(std::f32::NEG_INFINITY);
  481. let _c = &a + &b;
  482. }
  483. #[test]
  484. #[should_panic]
  485. fn test_add_fails_on_nan_t_ref() {
  486. let a = not_nan(std::f32::INFINITY);
  487. let b = std::f32::NEG_INFINITY;
  488. let _c = a + &b;
  489. }
  490. #[test]
  491. #[should_panic]
  492. fn test_add_fails_on_nan_ref_t_ref() {
  493. let a = not_nan(std::f32::INFINITY);
  494. let b = std::f32::NEG_INFINITY;
  495. let _c = &a + &b;
  496. }
  497. #[test]
  498. #[should_panic]
  499. fn test_add_fails_on_nan_ref_t() {
  500. let a = not_nan(std::f32::INFINITY);
  501. let b = std::f32::NEG_INFINITY;
  502. let _c = &a + b;
  503. }
  504. #[test]
  505. #[should_panic]
  506. fn test_add_assign_fails_on_nan_ref() {
  507. let mut a = not_nan(std::f32::INFINITY);
  508. let b = not_nan(std::f32::NEG_INFINITY);
  509. a += &b;
  510. }
  511. #[test]
  512. #[should_panic]
  513. fn test_add_assign_fails_on_nan_t_ref() {
  514. let mut a = not_nan(std::f32::INFINITY);
  515. let b = std::f32::NEG_INFINITY;
  516. a += &b;
  517. }
  518. #[test]
  519. #[should_panic]
  520. fn test_add_assign_fails_on_nan_t() {
  521. let mut a = not_nan(std::f32::INFINITY);
  522. let b = std::f32::NEG_INFINITY;
  523. a += b;
  524. }
  525. #[test]
  526. fn add() {
  527. assert_eq!(not_nan(0.0) + not_nan(0.0), 0.0);
  528. assert_eq!(not_nan(0.0) + &not_nan(0.0), 0.0);
  529. assert_eq!(&not_nan(0.0) + not_nan(0.0), 0.0);
  530. assert_eq!(&not_nan(0.0) + &not_nan(0.0), 0.0);
  531. assert_eq!(not_nan(0.0) + 0.0, 0.0);
  532. assert_eq!(not_nan(0.0) + &0.0, 0.0);
  533. assert_eq!(&not_nan(0.0) + 0.0, 0.0);
  534. assert_eq!(&not_nan(0.0) + &0.0, 0.0);
  535. assert_eq!(OrderedFloat(0.0) + OrderedFloat(0.0), 0.0);
  536. assert_eq!(OrderedFloat(0.0) + &OrderedFloat(0.0), 0.0);
  537. assert_eq!(&OrderedFloat(0.0) + OrderedFloat(0.0), 0.0);
  538. assert_eq!(&OrderedFloat(0.0) + &OrderedFloat(0.0), 0.0);
  539. assert_eq!(OrderedFloat(0.0) + 0.0, 0.0);
  540. assert_eq!(OrderedFloat(0.0) + &0.0, 0.0);
  541. assert_eq!(&OrderedFloat(0.0) + 0.0, 0.0);
  542. assert_eq!(&OrderedFloat(0.0) + &0.0, 0.0);
  543. }
  544. #[test]
  545. fn ordered_f32_neg() {
  546. assert_eq!(OrderedFloat(-7.0f32), -OrderedFloat(7.0f32));
  547. }
  548. #[test]
  549. fn ordered_f64_neg() {
  550. assert_eq!(OrderedFloat(-7.0f64), -OrderedFloat(7.0f64));
  551. }
  552. #[test]
  553. #[should_panic]
  554. fn test_sum_fails_on_nan() {
  555. let a = not_nan(std::f32::INFINITY);
  556. let b = not_nan(std::f32::NEG_INFINITY);
  557. let _c: NotNan<_> = [a, b].iter().sum();
  558. }
  559. #[test]
  560. #[should_panic]
  561. fn test_product_fails_on_nan() {
  562. let a = not_nan(std::f32::INFINITY);
  563. let b = not_nan(0f32);
  564. let _c: NotNan<_> = [a, b].iter().product();
  565. }
  566. #[test]
  567. fn not_nan64_sum_product() {
  568. let a = not_nan(2138.1237);
  569. let b = not_nan(132f64);
  570. let c = not_nan(5.1);
  571. assert_eq!(
  572. std::iter::empty::<NotNan<f64>>().sum::<NotNan<_>>(),
  573. NotNan::new(0f64).unwrap()
  574. );
  575. assert_eq!([a].iter().sum::<NotNan<_>>(), a);
  576. assert_eq!([a, b].iter().sum::<NotNan<_>>(), a + b);
  577. assert_eq!([a, b, c].iter().sum::<NotNan<_>>(), a + b + c);
  578. assert_eq!(
  579. std::iter::empty::<NotNan<f64>>().product::<NotNan<_>>(),
  580. NotNan::new(1f64).unwrap()
  581. );
  582. assert_eq!([a].iter().product::<NotNan<_>>(), a);
  583. assert_eq!([a, b].iter().product::<NotNan<_>>(), a * b);
  584. assert_eq!([a, b, c].iter().product::<NotNan<_>>(), a * b * c);
  585. }
  586. #[test]
  587. fn not_nan_usage_in_const_context() {
  588. const A: NotNan<f32> = unsafe { NotNan::new_unchecked(111f32) };
  589. assert_eq!(A, NotNan::new(111f32).unwrap());
  590. }
  591. #[test]
  592. fn not_nan_panic_safety() {
  593. let catch_op = |mut num, op: fn(&mut NotNan<_>)| {
  594. let mut num_ref = panic::AssertUnwindSafe(&mut num);
  595. let _ = panic::catch_unwind(move || op(&mut *num_ref));
  596. num
  597. };
  598. assert!(!catch_op(not_nan(f32::INFINITY), |a| *a += f32::NEG_INFINITY).is_nan());
  599. assert!(!catch_op(not_nan(f32::INFINITY), |a| *a -= f32::INFINITY).is_nan());
  600. assert!(!catch_op(not_nan(0.0), |a| *a *= f32::INFINITY).is_nan());
  601. assert!(!catch_op(not_nan(0.0), |a| *a /= 0.0).is_nan());
  602. assert!(!catch_op(not_nan(0.0), |a| *a %= 0.0).is_nan());
  603. }
  604. #[test]
  605. fn from_ref() {
  606. let f = 1.0f32;
  607. let o: &OrderedFloat<f32> = (&f).into();
  608. assert_eq!(*o, 1.0f32);
  609. let mut f = 1.0f64;
  610. let o: &OrderedFloat<f64> = (&f).into();
  611. assert_eq!(*o, 1.0f64);
  612. let o: &mut OrderedFloat<f64> = (&mut f).into();
  613. assert_eq!(*o, 1.0f64);
  614. *o = OrderedFloat(2.0);
  615. assert_eq!(*o, 2.0f64);
  616. assert_eq!(f, 2.0f64);
  617. }
  618. #[cfg(feature = "arbitrary")]
  619. mod arbitrary_test {
  620. use super::{NotNan, OrderedFloat};
  621. use arbitrary::{Arbitrary, Unstructured};
  622. #[test]
  623. fn exhaustive() {
  624. // Exhaustively search all patterns of sign and exponent bits plus a few mantissa bits.
  625. for high_bytes in 0..=u16::MAX {
  626. let [h1, h2] = high_bytes.to_be_bytes();
  627. // Each of these should not
  628. // * panic,
  629. // * return an error, or
  630. // * need more bytes than given.
  631. let n32: NotNan<f32> = Unstructured::new(&[h1, h2, h1, h2])
  632. .arbitrary()
  633. .expect("NotNan<f32> failure");
  634. let n64: NotNan<f64> = Unstructured::new(&[h1, h2, h1, h2, h1, h2, h1, h2])
  635. .arbitrary()
  636. .expect("NotNan<f64> failure");
  637. let _: OrderedFloat<f32> = Unstructured::new(&[h1, h2, h1, h2])
  638. .arbitrary()
  639. .expect("OrderedFloat<f32> failure");
  640. let _: OrderedFloat<f64> = Unstructured::new(&[h1, h2, h1, h2, h1, h2, h1, h2])
  641. .arbitrary()
  642. .expect("OrderedFloat<f64> failure");
  643. // Check for violation of NotNan's property of never containing a NaN.
  644. assert!(!n32.into_inner().is_nan());
  645. assert!(!n64.into_inner().is_nan());
  646. }
  647. }
  648. #[test]
  649. fn size_hints() {
  650. assert_eq!(NotNan::<f32>::size_hint(0), (4, Some(4)));
  651. assert_eq!(NotNan::<f64>::size_hint(0), (8, Some(8)));
  652. assert_eq!(OrderedFloat::<f32>::size_hint(0), (4, Some(4)));
  653. assert_eq!(OrderedFloat::<f64>::size_hint(0), (8, Some(8)));
  654. }
  655. }