misc.rs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // makes configuration easier
  2. #![allow(unused_macros)]
  3. use compiler_builtins::float::Float;
  4. use testcrate::*;
  5. /// Make sure that the the edge case tester and randomized tester don't break, and list examples of
  6. /// fuzz values for documentation purposes.
  7. #[test]
  8. fn fuzz_values() {
  9. const VALS: [u16; 47] = [
  10. 0b0, // edge cases
  11. 0b1111111111111111,
  12. 0b1111111111111110,
  13. 0b1111111111111100,
  14. 0b1111111110000000,
  15. 0b1111111100000000,
  16. 0b1110000000000000,
  17. 0b1100000000000000,
  18. 0b1000000000000000,
  19. 0b111111111111111,
  20. 0b111111111111110,
  21. 0b111111111111100,
  22. 0b111111110000000,
  23. 0b111111100000000,
  24. 0b110000000000000,
  25. 0b100000000000000,
  26. 0b11111111111111,
  27. 0b11111111111110,
  28. 0b11111111111100,
  29. 0b11111110000000,
  30. 0b11111100000000,
  31. 0b10000000000000,
  32. 0b111111111,
  33. 0b111111110,
  34. 0b111111100,
  35. 0b110000000,
  36. 0b100000000,
  37. 0b11111111,
  38. 0b11111110,
  39. 0b11111100,
  40. 0b10000000,
  41. 0b111,
  42. 0b110,
  43. 0b100,
  44. 0b11,
  45. 0b10,
  46. 0b1,
  47. 0b1010110100000, // beginning of random fuzzing
  48. 0b1100011001011010,
  49. 0b1001100101001111,
  50. 0b1101010100011010,
  51. 0b100010001,
  52. 0b1000000000000000,
  53. 0b1100000000000101,
  54. 0b1100111101010101,
  55. 0b1100010111111111,
  56. 0b1111110101111111,
  57. ];
  58. let mut i = 0;
  59. fuzz(10, |x: u16| {
  60. assert_eq!(x, VALS[i]);
  61. i += 1;
  62. });
  63. }
  64. #[test]
  65. fn leading_zeros() {
  66. use compiler_builtins::int::__clzsi2;
  67. use compiler_builtins::int::leading_zeros::{
  68. usize_leading_zeros_default, usize_leading_zeros_riscv,
  69. };
  70. fuzz(N, |x: usize| {
  71. let lz = x.leading_zeros() as usize;
  72. let lz0 = __clzsi2(x);
  73. let lz1 = usize_leading_zeros_default(x);
  74. let lz2 = usize_leading_zeros_riscv(x);
  75. if lz0 != lz {
  76. panic!("__clzsi2({}): std: {}, builtins: {}", x, lz, lz0);
  77. }
  78. if lz1 != lz {
  79. panic!(
  80. "usize_leading_zeros_default({}): std: {}, builtins: {}",
  81. x, lz, lz1
  82. );
  83. }
  84. if lz2 != lz {
  85. panic!(
  86. "usize_leading_zeros_riscv({}): std: {}, builtins: {}",
  87. x, lz, lz2
  88. );
  89. }
  90. })
  91. }
  92. macro_rules! extend {
  93. ($fX:ident, $fD:ident, $fn:ident) => {
  94. fuzz_float(N, |x: $fX| {
  95. let tmp0 = x as $fD;
  96. let tmp1: $fD = $fn(x);
  97. if !Float::eq_repr(tmp0, tmp1) {
  98. panic!(
  99. "{}({}): std: {}, builtins: {}",
  100. stringify!($fn),
  101. x,
  102. tmp0,
  103. tmp1
  104. );
  105. }
  106. });
  107. };
  108. }
  109. // PowerPC tests are failing on LLVM 13: https://github.com/rust-lang/rust/issues/88520
  110. #[cfg(not(target_arch = "powerpc64"))]
  111. #[test]
  112. fn float_extend() {
  113. use compiler_builtins::float::extend::__extendsfdf2;
  114. extend!(f32, f64, __extendsfdf2);
  115. }
  116. #[cfg(target_arch = "arm")]
  117. #[test]
  118. fn float_extend_arm() {
  119. use compiler_builtins::float::extend::__extendsfdf2vfp;
  120. extend!(f32, f64, __extendsfdf2vfp);
  121. }
  122. // This is approximate because of issues related to
  123. // https://github.com/rust-lang/rust/issues/73920.
  124. // TODO how do we resolve this indeterminacy?
  125. macro_rules! pow {
  126. ($($f:ty, $tolerance:expr, $fn:ident);*;) => {
  127. $(
  128. fuzz_float_2(N, |x: $f, y: $f| {
  129. if !(Float::is_subnormal(x) || Float::is_subnormal(y) || x.is_nan()) {
  130. let n = y.to_bits() & !<$f as Float>::SIGNIFICAND_MASK;
  131. let n = (n as <$f as Float>::SignedInt) >> <$f as Float>::SIGNIFICAND_BITS;
  132. let n = n as i32;
  133. let tmp0: $f = x.powi(n);
  134. let tmp1: $f = $fn(x, n);
  135. let (a, b) = if tmp0 < tmp1 {
  136. (tmp0, tmp1)
  137. } else {
  138. (tmp1, tmp0)
  139. };
  140. let good = {
  141. if a == b {
  142. // handles infinity equality
  143. true
  144. } else if a < $tolerance {
  145. b < $tolerance
  146. } else {
  147. let quo = b / a;
  148. (quo < (1. + $tolerance)) && (quo > (1. - $tolerance))
  149. }
  150. };
  151. if !good {
  152. panic!(
  153. "{}({}, {}): std: {}, builtins: {}",
  154. stringify!($fn), x, n, tmp0, tmp1
  155. );
  156. }
  157. }
  158. });
  159. )*
  160. };
  161. }
  162. #[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))]
  163. #[test]
  164. fn float_pow() {
  165. use compiler_builtins::float::pow::{__powidf2, __powisf2};
  166. pow!(
  167. f32, 1e-4, __powisf2;
  168. f64, 1e-12, __powidf2;
  169. );
  170. }
  171. macro_rules! trunc {
  172. ($fX:ident, $fD:ident, $fn:ident) => {
  173. fuzz_float(N, |x: $fX| {
  174. let tmp0 = x as $fD;
  175. let tmp1: $fD = $fn(x);
  176. if !Float::eq_repr(tmp0, tmp1) {
  177. panic!(
  178. "{}({}): std: {}, builtins: {}",
  179. stringify!($fn),
  180. x,
  181. tmp0,
  182. tmp1
  183. );
  184. }
  185. });
  186. };
  187. }
  188. #[test]
  189. fn float_trunc() {
  190. use compiler_builtins::float::trunc::__truncdfsf2;
  191. trunc!(f64, f32, __truncdfsf2);
  192. }
  193. #[cfg(target_arch = "arm")]
  194. #[test]
  195. fn float_trunc_arm() {
  196. use compiler_builtins::float::trunc::__truncdfsf2vfp;
  197. trunc!(f64, f32, __truncdfsf2vfp);
  198. }