11use crate :: gmp_ffi as gmp;
22use crate :: node:: Node ;
3+ use crate :: number_traits:: NumberTraits ;
4+ #[ cfg( test) ]
5+ use crate :: number_traits:: TestNumberTraits ;
36use core:: mem:: MaybeUninit ;
47use std:: cmp:: Ordering ;
58use std:: cmp:: PartialOrd ;
@@ -8,9 +11,6 @@ use std::ops::Drop;
811use std:: ops:: {
912 AddAssign , BitAndAssign , BitOrAssign , BitXorAssign , MulAssign , Not , Shl , Shr , SubAssign ,
1013} ;
11- use crate :: number_traits:: NumberTraits ;
12- #[ cfg( test) ]
13- use crate :: number_traits:: TestNumberTraits ;
1414
1515#[ allow( clippy:: enum_variant_names) ]
1616#[ derive( PartialEq ) ]
@@ -60,6 +60,49 @@ impl NumberTraits for Number {
6060 ret
6161 }
6262
63+ fn to_signed_bytes ( & self ) -> Vec < u8 > {
64+ let size = ( self . bits ( ) + 7 ) / 8 ;
65+ let mut ret: Vec < u8 > = Vec :: new ( ) ;
66+ if size == 0 {
67+ return ret;
68+ }
69+ ret. resize ( size + 1 , 0 ) ;
70+ let sign = self . sign ( ) ;
71+ let mut out_size: usize = size;
72+ unsafe {
73+ gmp:: mpz_export (
74+ ret. as_mut_slice ( ) [ 1 ..] . as_mut_ptr ( ) as * mut c_void ,
75+ & mut out_size,
76+ 1 ,
77+ 1 ,
78+ 0 ,
79+ 0 ,
80+ & self . v ,
81+ ) ;
82+ }
83+ // apparently mpz_export prints 0 bytes to the buffer if the value is 0
84+ // hence the special case in the assert below.
85+ assert ! ( out_size == ret. len( ) - 1 ) ;
86+ if sign == Sign :: Minus {
87+ // If the value is negative, we need to convert it to two's
88+ // complement. We can't do that in-place.
89+ let mut carry = true ;
90+ for digit in & mut ret. iter_mut ( ) . rev ( ) {
91+ let res = ( !* digit) . overflowing_add ( carry as u8 ) ;
92+ * digit = res. 0 ;
93+ carry = res. 1 ;
94+ }
95+ assert ! ( !carry) ;
96+ assert ! ( ret[ 0 ] & 0x80 != 0 ) ;
97+ if ( ret[ 1 ] & 0x80 ) != 0 {
98+ ret. remove ( 0 ) ;
99+ }
100+ } else if ret[ 1 ] & 0x80 == 0 {
101+ ret. remove ( 0 ) ;
102+ }
103+ ret
104+ }
105+
63106 fn zero ( ) -> Number {
64107 let mut v = MaybeUninit :: < gmp:: mpz_t > :: uninit ( ) ;
65108 unsafe {
@@ -74,8 +117,8 @@ impl NumberTraits for Number {
74117 Number :: from_signed_bytes_be ( v)
75118 }
76119
77- fn to_u64 ( n : & Number ) -> u64 {
78- n . into ( )
120+ fn to_u64 ( & self ) -> u64 {
121+ u64 :: from ( self )
79122 }
80123
81124 // returns the quotient and remained, from dividing self with denominator
@@ -95,6 +138,18 @@ impl NumberTraits for Number {
95138 }
96139 r
97140 }
141+
142+ fn equal ( & self , other : i64 ) -> bool {
143+ self == & other
144+ }
145+
146+ fn not_equal ( & self , other : i64 ) -> bool {
147+ self != & other
148+ }
149+
150+ fn greater_than ( & self , other : u64 ) -> bool {
151+ self > & other
152+ }
98153}
99154
100155impl Number {
@@ -128,49 +183,6 @@ impl Number {
128183 ret
129184 }
130185
131- pub fn to_signed_bytes_be ( & self ) -> Vec < u8 > {
132- let size = ( self . bits ( ) + 7 ) / 8 ;
133- let mut ret: Vec < u8 > = Vec :: new ( ) ;
134- if size == 0 {
135- return ret;
136- }
137- ret. resize ( size + 1 , 0 ) ;
138- let sign = self . sign ( ) ;
139- let mut out_size: usize = size;
140- unsafe {
141- gmp:: mpz_export (
142- ret. as_mut_slice ( ) [ 1 ..] . as_mut_ptr ( ) as * mut c_void ,
143- & mut out_size,
144- 1 ,
145- 1 ,
146- 0 ,
147- 0 ,
148- & self . v ,
149- ) ;
150- }
151- // apparently mpz_export prints 0 bytes to the buffer if the value is 0
152- // hence the special case in the assert below.
153- assert ! ( out_size == ret. len( ) - 1 ) ;
154- if sign == Sign :: Minus {
155- // If the value is negative, we need to convert it to two's
156- // complement. We can't do that in-place.
157- let mut carry = true ;
158- for digit in & mut ret. iter_mut ( ) . rev ( ) {
159- let res = ( !* digit) . overflowing_add ( carry as u8 ) ;
160- * digit = res. 0 ;
161- carry = res. 1 ;
162- }
163- assert ! ( !carry) ;
164- assert ! ( ret[ 0 ] & 0x80 != 0 ) ;
165- if ( ret[ 1 ] & 0x80 ) != 0 {
166- ret. remove ( 0 ) ;
167- }
168- } else if ret[ 1 ] & 0x80 == 0 {
169- ret. remove ( 0 ) ;
170- }
171- ret
172- }
173-
174186 pub fn to_bytes_le ( & self ) -> ( Sign , Vec < u8 > ) {
175187 let sgn = self . sign ( ) ;
176188
@@ -345,8 +357,8 @@ impl From<usize> for Number {
345357 }
346358}
347359
348- impl From < Number > for u64 {
349- fn from ( n : Number ) -> u64 {
360+ impl From < & Number > for u64 {
361+ fn from ( n : & Number ) -> u64 {
350362 unsafe {
351363 assert ! ( gmp:: mpz_sizeinbase( & n. v, 2 ) <= 64 ) ;
352364 assert ! ( gmp:: mpz_cmp_si( & n. v, 0 ) >= 0 ) ;
@@ -355,8 +367,8 @@ impl From<Number> for u64 {
355367 }
356368}
357369
358- impl From < Number > for i64 {
359- fn from ( n : Number ) -> i64 {
370+ impl From < & Number > for i64 {
371+ fn from ( n : & Number ) -> i64 {
360372 unsafe {
361373 assert ! ( gmp:: mpz_sizeinbase( & n. v, 2 ) <= 64 ) ;
362374 gmp:: mpz_get_si ( & n. v )
@@ -456,6 +468,9 @@ impl From<&Node<'_>> for Option<Number> {
456468 }
457469}
458470
471+ // TODO: move all tests to number.rs so we can test both the GMP and num-bigint
472+ // versions
473+
459474// ==== TESTS ====
460475
461476#[ cfg( test) ]
@@ -489,7 +504,7 @@ fn roundtrip_bytes(b: &[u8]) {
489504 assert ! ( num. sign( ) == Sign :: Plus ) ;
490505 }
491506
492- let round_trip = num. to_signed_bytes_be ( ) ;
507+ let round_trip = num. to_signed_bytes ( ) ;
493508
494509 assert_eq ! ( round_trip, b) ;
495510
@@ -516,7 +531,7 @@ fn roundtrip_bytes(b: &[u8]) {
516531 unsafe {
517532 gmp:: mpz_neg ( & mut negated. v , & num. v ) ;
518533 }
519- let magnitude = negated. to_signed_bytes_be ( ) ;
534+ let magnitude = negated. to_signed_bytes ( ) ;
520535 assert ! ( buf_le. iter( ) . eq( magnitude. iter( ) . rev( ) ) ) ;
521536 }
522537 }
@@ -525,7 +540,7 @@ fn roundtrip_bytes(b: &[u8]) {
525540 {
526541 let unsigned_num = Number :: from_unsigned_bytes_be ( b) ;
527542 assert ! ( unsigned_num. sign( ) != Sign :: Minus ) ;
528- let unsigned_round_trip = unsigned_num. to_signed_bytes_be ( ) ;
543+ let unsigned_round_trip = unsigned_num. to_signed_bytes ( ) ;
529544 let unsigned_round_trip = if unsigned_round_trip == & [ 0 ] {
530545 & unsigned_round_trip[ 1 ..]
531546 } else {
@@ -610,7 +625,7 @@ fn roundtrip_u64(v: u64) {
610625 assert ! ( num >= v - 1 ) ;
611626 }
612627
613- let round_trip: u64 = num. into ( ) ;
628+ let round_trip: u64 = ( & num) . into ( ) ;
614629 assert_eq ! ( round_trip, v) ;
615630}
616631
@@ -656,7 +671,7 @@ fn roundtrip_i64(v: i64) {
656671 }
657672
658673 assert ! ( num. bits( ) <= 64 ) ;
659- let round_trip: i64 = num. into ( ) ;
674+ let round_trip: i64 = ( & num) . into ( ) ;
660675 assert_eq ! ( round_trip, v) ;
661676}
662677
0 commit comments