@@ -504,9 +504,8 @@ impl Integer for BigUint {
504
504
impl ToPrimitive for BigUint {
505
505
#[ inline]
506
506
fn to_i64 ( & self ) -> Option < i64 > {
507
- do self . to_uint ( ) . and_then |n| {
508
- // If top bit of u64 is set, it's too large to convert to
509
- // int.
507
+ do self . to_u64 ( ) . and_then |n| {
508
+ // If top bit of u64 is set, it's too large to convert to i64.
510
509
if ( n >> ( 2 * BigDigit :: bits - 1 ) != 0 ) {
511
510
None
512
511
} else {
@@ -515,12 +514,46 @@ impl ToPrimitive for BigUint {
515
514
}
516
515
}
517
516
517
+ #[ cfg( target_word_size = "32" ) ]
518
518
#[ inline]
519
519
fn to_u64 ( & self ) -> Option < u64 > {
520
- match self . data . len ( ) {
521
- 0 => Some ( 0 ) ,
522
- 1 => Some ( self . data [ 0 ] as u64 ) ,
523
- 2 => Some ( BigDigit :: to_uint ( self . data [ 1 ] , self . data [ 0 ] ) as u64 ) ,
520
+ match self . data {
521
+ [ ] => {
522
+ Some ( 0 )
523
+ }
524
+ [ n0] => {
525
+ Some ( n0 as u64 )
526
+ }
527
+ [ n0, n1] => {
528
+ Some ( BigDigit :: to_uint ( n1, n0) as u64 )
529
+ }
530
+ [ n0, n1, n2] => {
531
+ let n_lo = BigDigit :: to_uint ( n1, n0) as u64 ;
532
+ let n_hi = n2 as u64 ;
533
+ Some ( ( n_hi << 32 ) + n_lo)
534
+ }
535
+ [ n0, n1, n2, n3] => {
536
+ let n_lo = BigDigit :: to_uint ( n1, n0) as u64 ;
537
+ let n_hi = BigDigit :: to_uint ( n3, n2) as u64 ;
538
+ Some ( ( n_hi << 32 ) + n_lo)
539
+ }
540
+ _ => None
541
+ }
542
+ }
543
+
544
+ #[ cfg( target_word_size = "64" ) ]
545
+ #[ inline]
546
+ fn to_u64 ( & self ) -> Option < u64 > {
547
+ match self . data {
548
+ [ ] => {
549
+ Some ( 0 )
550
+ }
551
+ [ n0] => {
552
+ Some ( n0 as u64 )
553
+ }
554
+ [ n0, n1] => {
555
+ Some ( BigDigit :: to_uint ( n1, n0) as u64 )
556
+ }
524
557
_ => None
525
558
}
526
559
}
@@ -536,6 +569,23 @@ impl FromPrimitive for BigUint {
536
569
}
537
570
}
538
571
572
+ #[ cfg( target_word_size = "32" ) ]
573
+ #[ inline]
574
+ fn from_u64 ( n : u64 ) -> Option < BigUint > {
575
+ let n_lo = ( n & 0x0000_0000_FFFF_FFFF ) as uint ;
576
+ let n_hi = ( n >> 32 ) as uint ;
577
+
578
+ let n = match ( BigDigit :: from_uint ( n_hi) , BigDigit :: from_uint ( n_lo) ) {
579
+ ( ( 0 , 0 ) , ( 0 , 0 ) ) => Zero :: zero ( ) ,
580
+ ( ( 0 , 0 ) , ( 0 , n0) ) => BigUint :: new ( ~[ n0] ) ,
581
+ ( ( 0 , 0 ) , ( n1, n0) ) => BigUint :: new ( ~[ n0, n1] ) ,
582
+ ( ( 0 , n2) , ( n1, n0) ) => BigUint :: new ( ~[ n0, n1, n2] ) ,
583
+ ( ( n3, n2) , ( n1, n0) ) => BigUint :: new ( ~[ n0, n1, n2, n3] ) ,
584
+ } ;
585
+ Some ( n)
586
+ }
587
+
588
+ #[ cfg( target_word_size = "64" ) ]
539
589
#[ inline]
540
590
fn from_u64 ( n : u64 ) -> Option < BigUint > {
541
591
let n = match BigDigit :: from_uint ( n as uint ) {
@@ -547,7 +597,9 @@ impl FromPrimitive for BigUint {
547
597
}
548
598
}
549
599
600
+ /// A generic trait for converting a value to a `BigUint`.
550
601
pub trait ToBigUint {
602
+ /// Converts the value of `self` to a `BigUint`.
551
603
fn to_biguint ( & self ) -> Option < BigUint > ;
552
604
}
553
605
@@ -696,12 +748,6 @@ impl BigUint {
696
748
}
697
749
}
698
750
699
- /// Converts this `BigUint` into a `BigInt.
700
- #[ inline]
701
- pub fn to_bigint ( & self ) -> BigInt {
702
- BigInt :: from_biguint ( Plus , self . clone ( ) )
703
- }
704
-
705
751
#[ inline]
706
752
fn shl_unit ( & self , n_unit : uint ) -> BigUint {
707
753
if n_unit == 0 || self . is_zero ( ) { return ( * self ) . clone ( ) ; }
@@ -1186,7 +1232,9 @@ impl FromPrimitive for BigInt {
1186
1232
}
1187
1233
}
1188
1234
1235
+ /// A generic trait for converting a value to a `BigInt`.
1189
1236
pub trait ToBigInt {
1237
+ /// Converts the value of `self` to a `BigInt`.
1190
1238
fn to_bigint ( & self ) -> Option < BigInt > ;
1191
1239
}
1192
1240
@@ -1330,7 +1378,7 @@ impl<R: Rng> RandBigInt for R {
1330
1378
-> BigInt {
1331
1379
assert!(*lbound < *ubound);
1332
1380
let delta = (*ubound - *lbound).to_biguint().unwrap();
1333
- return *lbound + self.gen_biguint_below(&delta).to_bigint();
1381
+ return *lbound + self.gen_biguint_below(&delta).to_bigint().unwrap() ;
1334
1382
}
1335
1383
}
1336
1384
@@ -1607,8 +1655,8 @@ mod biguint_tests {
1607
1655
#[ test ]
1608
1656
fn test_convert_to_bigint ( ) {
1609
1657
fn check ( n : BigUint , ans : BigInt ) {
1610
- assert_eq ! ( n. to_bigint( ) , ans) ;
1611
- assert_eq ! ( n. to_bigint( ) . to_biguint( ) . unwrap( ) , n) ;
1658
+ assert_eq ! ( n. to_bigint( ) . unwrap ( ) , ans) ;
1659
+ assert_eq ! ( n. to_bigint( ) . unwrap ( ) . to_biguint( ) . unwrap( ) , n) ;
1612
1660
}
1613
1661
check ( Zero :: zero ( ) , Zero :: zero ( ) ) ;
1614
1662
check ( BigUint :: new ( ~[ 1 , 2 , 3 ] ) ,
@@ -1977,11 +2025,10 @@ mod bigint_tests {
1977
2025
use super :: * ;
1978
2026
1979
2027
use std:: cmp:: { Less , Equal , Greater } ;
1980
- use std:: int;
2028
+ use std:: { int, i64 , uint , u64 } ;
1981
2029
use std:: num:: { Zero , One , FromStrRadix } ;
1982
2030
use std:: num:: { ToPrimitive , FromPrimitive } ;
1983
2031
use std:: rand:: { task_rng} ;
1984
- use std:: uint;
1985
2032
1986
2033
#[ test]
1987
2034
fn test_from_biguint ( ) {
@@ -2092,11 +2139,66 @@ mod bigint_tests {
2092
2139
assert_eq ! ( BigInt :: from_biguint( Minus , BigUint :: new( ~[ 1 , 2 , 3 ] ) ) . to_uint( ) , None ) ;
2093
2140
}
2094
2141
2142
+ #[ test]
2143
+ fn test_convert_i64 ( ) {
2144
+ fn check ( b1 : BigInt , i : i64 ) {
2145
+ let b2: BigInt = FromPrimitive :: from_i64 ( i) . unwrap ( ) ;
2146
+ assert ! ( b1 == b2) ;
2147
+ assert ! ( b1. to_i64( ) . unwrap( ) == i) ;
2148
+ }
2149
+
2150
+ check ( Zero :: zero ( ) , 0 ) ;
2151
+ check ( One :: one ( ) , 1 ) ;
2152
+ check ( i64:: min_value. to_bigint ( ) . unwrap ( ) , i64:: min_value) ;
2153
+ check ( i64:: max_value. to_bigint ( ) . unwrap ( ) , i64:: max_value) ;
2154
+
2155
+ assert_eq ! (
2156
+ ( i64 :: max_value as uint + 1 ) . to_bigint( ) . unwrap( ) . to_i64( ) ,
2157
+ None ) ;
2158
+
2159
+ assert_eq ! (
2160
+ BigInt :: from_biguint( Plus , BigUint :: new( ~[ 1 , 2 , 3 , 4 , 5 ] ) ) . to_i64( ) ,
2161
+ None ) ;
2162
+
2163
+ check (
2164
+ BigInt :: from_biguint ( Minus , BigUint :: new ( ~[ 0 , 1 <<( BigDigit :: bits-1 ) ] ) ) ,
2165
+ i64:: min_value) ;
2166
+
2167
+ assert_eq ! (
2168
+ BigInt :: from_biguint( Minus , BigUint :: new( ~[ 1 , 1 <<( BigDigit :: bits-1 ) ] ) ) . to_i64( ) ,
2169
+ None ) ;
2170
+
2171
+ assert_eq ! (
2172
+ BigInt :: from_biguint( Minus , BigUint :: new( ~[ 1 , 2 , 3 , 4 , 5 ] ) ) . to_i64( ) ,
2173
+ None ) ;
2174
+ }
2175
+
2176
+ #[ test]
2177
+ fn test_convert_u64 ( ) {
2178
+ fn check ( b1 : BigInt , u : u64 ) {
2179
+ let b2: BigInt = FromPrimitive :: from_u64 ( u) . unwrap ( ) ;
2180
+ assert ! ( b1 == b2) ;
2181
+ assert ! ( b1. to_u64( ) . unwrap( ) == u) ;
2182
+ }
2183
+
2184
+ check ( Zero :: zero ( ) , 0 ) ;
2185
+ check ( One :: one ( ) , 1 ) ;
2186
+ check ( u64:: max_value. to_bigint ( ) . unwrap ( ) , u64:: max_value) ;
2187
+
2188
+ assert_eq ! (
2189
+ BigInt :: from_biguint( Plus , BigUint :: new( ~[ 1 , 2 , 3 , 4 , 5 ] ) ) . to_uint( ) ,
2190
+ None ) ;
2191
+
2192
+ let max_value: BigUint = FromPrimitive :: from_uint ( uint:: max_value) . unwrap ( ) ;
2193
+ assert_eq ! ( BigInt :: from_biguint( Minus , max_value) . to_u64( ) , None ) ;
2194
+ assert_eq ! ( BigInt :: from_biguint( Minus , BigUint :: new( ~[ 1 , 2 , 3 ] ) ) . to_u64( ) , None ) ;
2195
+ }
2196
+
2095
2197
#[ test]
2096
2198
fn test_convert_to_biguint ( ) {
2097
2199
fn check ( n : BigInt , ans_1 : BigUint ) {
2098
2200
assert_eq ! ( n. to_biguint( ) . unwrap( ) , ans_1) ;
2099
- assert_eq ! ( n. to_biguint( ) . unwrap( ) . to_bigint( ) , n) ;
2201
+ assert_eq ! ( n. to_biguint( ) . unwrap( ) . to_bigint( ) . unwrap ( ) , n) ;
2100
2202
}
2101
2203
let zero: BigInt = Zero :: zero ( ) ;
2102
2204
let unsigned_zero: BigUint = Zero :: zero ( ) ;
0 commit comments