@@ -6,10 +6,10 @@ extern crate num_integer;
66extern crate num_traits;
77extern crate test;
88
9- use std:: cmp:: { min, max} ;
10- use std:: fmt:: Debug ;
119use num_integer:: Integer ;
1210use num_traits:: { AsPrimitive , PrimInt , WrappingAdd , WrappingMul } ;
11+ use std:: cmp:: { max, min} ;
12+ use std:: fmt:: Debug ;
1313use test:: { black_box, Bencher } ;
1414
1515// --- Utilities for RNG ----------------------------------------------------
@@ -66,15 +66,15 @@ macro_rules! naive_average {
6666 }
6767 }
6868 fn naive_average_ceil( & self , other: & $T) -> $T {
69- match self . checked_add( * other) . and_then ( |x| x . checked_add ( 1 ) ) {
69+ match self . checked_add( * other) {
7070 Some ( z) => z. div_ceil( & 2 ) ,
7171 None => {
7272 if self > other {
7373 let diff = self - other;
74- self - diff / 2
74+ self - diff. div_floor ( & 2 )
7575 } else {
7676 let diff = other - self ;
77- other - diff / 2
77+ other - diff. div_floor ( & 2 )
7878 }
7979 }
8080 }
@@ -102,7 +102,7 @@ macro_rules! modulo_average {
102102 fn modulo_average_ceil( & self , other: & $T) -> $T {
103103 let ( q1, r1) = self . div_mod_floor( & 2 ) ;
104104 let ( q2, r2) = other. div_mod_floor( & 2 ) ;
105- q1 + q2 + ( r1 * r2)
105+ q1 + q2 + ( r1 | r2)
106106 }
107107 fn modulo_average_floor( & self , other: & $T) -> $T {
108108 let ( q1, r1) = self . div_mod_floor( & 2 ) ;
@@ -135,10 +135,21 @@ where
135135 for & ( i, j) in v {
136136 let rt = f ( & i, & j) ;
137137 let ( a, b) = ( min ( i, j) , max ( i, j) ) ;
138- if ( b - a) . is_even ( ) {
139- assert_eq ! ( rt - a, b - rt) ;
138+ println ! ( "( {:?} + {:?} )/ 2 = {:?}" , a, b, rt) ;
139+ // if both number are the same sign, check rt is in the middle
140+ if ( a < T :: zero ( ) ) == ( b < T :: zero ( ) ) {
141+ if ( b - a) . is_even ( ) {
142+ assert_eq ! ( rt - a, b - rt) ;
143+ } else {
144+ assert_eq ! ( rt - a, b - rt + T :: one( ) ) ;
145+ }
146+ // if both number have a different sign,
140147 } else {
141- assert_eq ! ( rt - a, b - rt + T :: one( ) ) ;
148+ if ( a + b) . is_even ( ) {
149+ assert_eq ! ( rt, ( a + b) / ( T :: one( ) + T :: one( ) ) )
150+ } else {
151+ assert_eq ! ( rt, ( a + b + T :: one( ) ) / ( T :: one( ) + T :: one( ) ) )
152+ }
142153 }
143154 }
144155 bench_unchecked ( b, v, f) ;
@@ -211,6 +222,99 @@ macro_rules! bench_average {
211222 . collect( )
212223 }
213224
225+ mod ceil {
226+
227+ use super :: * ;
228+
229+ mod small {
230+
231+ use super :: * ;
232+
233+ #[ bench]
234+ fn optimized( b: & mut Bencher ) {
235+ let v = small( ) ;
236+ bench_ceil( b, & v, |x: & $T, y: & $T| x. average_ceil( y) ) ;
237+ }
238+
239+ #[ bench]
240+ fn naive( b: & mut Bencher ) {
241+ let v = small( ) ;
242+ bench_ceil( b, & v, |x: & $T, y: & $T| x. naive_average_ceil( y) ) ;
243+ }
244+
245+ #[ bench]
246+ fn unchecked( b: & mut Bencher ) {
247+ let v = small( ) ;
248+ bench_unchecked( b, & v, |x: & $T, y: & $T| x. unchecked_average_ceil( y) ) ;
249+ }
250+
251+ #[ bench]
252+ fn modulo( b: & mut Bencher ) {
253+ let v = small( ) ;
254+ bench_ceil( b, & v, |x: & $T, y: & $T| x. modulo_average_ceil( y) ) ;
255+ }
256+ }
257+
258+ mod overflowing {
259+
260+ use super :: * ;
261+
262+ #[ bench]
263+ fn optimized( b: & mut Bencher ) {
264+ let v = overflowing( ) ;
265+ bench_ceil( b, & v, |x: & $T, y: & $T| x. average_ceil( y) ) ;
266+ }
267+
268+ #[ bench]
269+ fn naive( b: & mut Bencher ) {
270+ let v = overflowing( ) ;
271+ bench_ceil( b, & v, |x: & $T, y: & $T| x. naive_average_ceil( y) ) ;
272+ }
273+
274+ #[ bench]
275+ fn unchecked( b: & mut Bencher ) {
276+ let v = overflowing( ) ;
277+ bench_unchecked( b, & v, |x: & $T, y: & $T| x. unchecked_average_ceil( y) ) ;
278+ }
279+
280+ #[ bench]
281+ fn modulo( b: & mut Bencher ) {
282+ let v = overflowing( ) ;
283+ bench_ceil( b, & v, |x: & $T, y: & $T| x. modulo_average_ceil( y) ) ;
284+ }
285+ }
286+
287+ mod rand {
288+
289+ use super :: * ;
290+
291+ #[ bench]
292+ fn optimized( b: & mut Bencher ) {
293+ let v = rand( ) ;
294+ bench_ceil( b, & v, |x: & $T, y: & $T| x. average_ceil( y) ) ;
295+ }
296+
297+ #[ bench]
298+ fn naive( b: & mut Bencher ) {
299+ let v = rand( ) ;
300+ bench_ceil( b, & v, |x: & $T, y: & $T| x. naive_average_ceil( y) ) ;
301+ }
302+
303+ #[ bench]
304+ fn unchecked( b: & mut Bencher ) {
305+ let v = rand( ) ;
306+ bench_unchecked( b, & v, |x: & $T, y: & $T| x. unchecked_average_ceil( y) ) ;
307+ }
308+
309+ #[ bench]
310+ fn modulo( b: & mut Bencher ) {
311+ let v = rand( ) ;
312+ bench_ceil( b, & v, |x: & $T, y: & $T| x. modulo_average_ceil( y) ) ;
313+ }
314+ }
315+
316+ }
317+
214318 mod floor {
215319
216320 use super :: * ;
0 commit comments