roots.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. //! Benchmark sqrt and cbrt
  2. #![feature(test)]
  3. extern crate num_integer;
  4. extern crate num_traits;
  5. extern crate test;
  6. use num_integer::Integer;
  7. use num_traits::checked_pow;
  8. use num_traits::{AsPrimitive, PrimInt, WrappingAdd, WrappingMul};
  9. use test::{black_box, Bencher};
  10. trait BenchInteger: Integer + PrimInt + WrappingAdd + WrappingMul + 'static {}
  11. impl<T> BenchInteger for T where T: Integer + PrimInt + WrappingAdd + WrappingMul + 'static {}
  12. fn bench<T, F>(b: &mut Bencher, v: &[T], f: F, n: u32)
  13. where
  14. T: BenchInteger,
  15. F: Fn(&T) -> T,
  16. {
  17. // Pre-validate the results...
  18. for i in v {
  19. let rt = f(i);
  20. if *i >= T::zero() {
  21. let rt1 = rt + T::one();
  22. assert!(rt.pow(n) <= *i);
  23. if let Some(x) = checked_pow(rt1, n as usize) {
  24. assert!(*i < x);
  25. }
  26. } else {
  27. let rt1 = rt - T::one();
  28. assert!(rt < T::zero());
  29. assert!(*i <= rt.pow(n));
  30. if let Some(x) = checked_pow(rt1, n as usize) {
  31. assert!(x < *i);
  32. }
  33. };
  34. }
  35. // Now just run as fast as we can!
  36. b.iter(|| {
  37. for i in v {
  38. black_box(f(i));
  39. }
  40. });
  41. }
  42. // Simple PRNG so we don't have to worry about rand compatibility
  43. fn lcg<T>(x: T) -> T
  44. where
  45. u32: AsPrimitive<T>,
  46. T: BenchInteger,
  47. {
  48. // LCG parameters from Numerical Recipes
  49. // (but we're applying it to arbitrary sizes)
  50. const LCG_A: u32 = 1664525;
  51. const LCG_C: u32 = 1013904223;
  52. x.wrapping_mul(&LCG_A.as_()).wrapping_add(&LCG_C.as_())
  53. }
  54. fn bench_rand<T, F>(b: &mut Bencher, f: F, n: u32)
  55. where
  56. u32: AsPrimitive<T>,
  57. T: BenchInteger,
  58. F: Fn(&T) -> T,
  59. {
  60. let mut x: T = 3u32.as_();
  61. let v: Vec<T> = (0..1000)
  62. .map(|_| {
  63. x = lcg(x);
  64. x
  65. })
  66. .collect();
  67. bench(b, &v, f, n);
  68. }
  69. fn bench_rand_pos<T, F>(b: &mut Bencher, f: F, n: u32)
  70. where
  71. u32: AsPrimitive<T>,
  72. T: BenchInteger,
  73. F: Fn(&T) -> T,
  74. {
  75. let mut x: T = 3u32.as_();
  76. let v: Vec<T> = (0..1000)
  77. .map(|_| {
  78. x = lcg(x);
  79. while x < T::zero() {
  80. x = lcg(x);
  81. }
  82. x
  83. })
  84. .collect();
  85. bench(b, &v, f, n);
  86. }
  87. fn bench_small<T, F>(b: &mut Bencher, f: F, n: u32)
  88. where
  89. u32: AsPrimitive<T>,
  90. T: BenchInteger,
  91. F: Fn(&T) -> T,
  92. {
  93. let v: Vec<T> = (0..1000).map(|i| i.as_()).collect();
  94. bench(b, &v, f, n);
  95. }
  96. fn bench_small_pos<T, F>(b: &mut Bencher, f: F, n: u32)
  97. where
  98. u32: AsPrimitive<T>,
  99. T: BenchInteger,
  100. F: Fn(&T) -> T,
  101. {
  102. let v: Vec<T> = (0..1000)
  103. .map(|i| i.as_().mod_floor(&T::max_value()))
  104. .collect();
  105. bench(b, &v, f, n);
  106. }
  107. macro_rules! bench_roots {
  108. ($($T:ident),*) => {$(
  109. mod $T {
  110. use test::Bencher;
  111. use num_integer::Roots;
  112. #[bench]
  113. fn sqrt_rand(b: &mut Bencher) {
  114. ::bench_rand_pos(b, $T::sqrt, 2);
  115. }
  116. #[bench]
  117. fn sqrt_small(b: &mut Bencher) {
  118. ::bench_small_pos(b, $T::sqrt, 2);
  119. }
  120. #[bench]
  121. fn cbrt_rand(b: &mut Bencher) {
  122. ::bench_rand(b, $T::cbrt, 3);
  123. }
  124. #[bench]
  125. fn cbrt_small(b: &mut Bencher) {
  126. ::bench_small(b, $T::cbrt, 3);
  127. }
  128. #[bench]
  129. fn fourth_root_rand(b: &mut Bencher) {
  130. ::bench_rand_pos(b, |x: &$T| x.nth_root(4), 4);
  131. }
  132. #[bench]
  133. fn fourth_root_small(b: &mut Bencher) {
  134. ::bench_small_pos(b, |x: &$T| x.nth_root(4), 4);
  135. }
  136. #[bench]
  137. fn fifth_root_rand(b: &mut Bencher) {
  138. ::bench_rand(b, |x: &$T| x.nth_root(5), 5);
  139. }
  140. #[bench]
  141. fn fifth_root_small(b: &mut Bencher) {
  142. ::bench_small(b, |x: &$T| x.nth_root(5), 5);
  143. }
  144. }
  145. )*}
  146. }
  147. bench_roots!(i8, i16, i32, i64, i128);
  148. bench_roots!(u8, u16, u32, u64, u128);