@@ -503,7 +503,7 @@ impl Integer for BigUint {
503
503
impl IntConvertible for BigUint {
504
504
#[ inline]
505
505
fn to_int ( & self ) -> int {
506
- num :: min ( self . to_uint ( ) , int :: max_value as uint ) as int
506
+ self . to_int_opt ( ) . expect ( "BigUint conversion would overflow int" )
507
507
}
508
508
509
509
#[ inline]
@@ -615,18 +615,43 @@ impl BigUint {
615
615
}
616
616
617
617
618
- /// Converts this big integer into a uint, returning the uint::max_value if
619
- /// it's too large to fit in a uint .
618
+ /// Converts this BigUint into a uint, failing if the conversion
619
+ /// would overflow .
620
620
#[ inline]
621
621
pub fn to_uint ( & self ) -> uint {
622
+ self . to_uint_opt ( ) . expect ( "BigUint conversion would overflow uint" )
623
+ }
624
+
625
+ /// Converts this BigUint into a uint, unless it would overflow.
626
+ #[ inline]
627
+ pub fn to_uint_opt ( & self ) -> Option < uint > {
622
628
match self . data . len ( ) {
623
- 0 => 0 ,
624
- 1 => self . data [ 0 ] as uint ,
625
- 2 => BigDigit :: to_uint ( self . data [ 1 ] , self . data [ 0 ] ) ,
626
- _ => uint :: max_value
629
+ 0 => Some ( 0 ) ,
630
+ 1 => Some ( self . data [ 0 ] as uint ) ,
631
+ 2 => Some ( BigDigit :: to_uint ( self . data [ 1 ] , self . data [ 0 ] ) ) ,
632
+ _ => None
627
633
}
628
634
}
629
635
636
+ // Converts this BigUint into an int, unless it would overflow.
637
+ pub fn to_int_opt ( & self ) -> Option < int > {
638
+ self . to_uint_opt ( ) . chain ( |n| {
639
+ // If top bit of uint is set, it's too large to convert to
640
+ // int.
641
+ if ( n >> ( 2 * BigDigit :: bits - 1 ) != 0 ) {
642
+ None
643
+ } else {
644
+ Some ( n as int )
645
+ }
646
+ } )
647
+ }
648
+
649
+ /// Converts this BigUint into a BigInt.
650
+ #[ inline]
651
+ pub fn to_bigint ( & self ) -> BigInt {
652
+ BigInt :: from_biguint ( Plus , self . clone ( ) )
653
+ }
654
+
630
655
#[ inline]
631
656
fn shl_unit ( & self , n_unit : uint ) -> BigUint {
632
657
if n_unit == 0 || self . is_zero ( ) { return ( * self ) . clone ( ) ; }
@@ -1048,12 +1073,7 @@ impl Integer for BigInt {
1048
1073
impl IntConvertible for BigInt {
1049
1074
#[ inline]
1050
1075
fn to_int ( & self ) -> int {
1051
- match self . sign {
1052
- Plus => num:: min ( self . to_uint ( ) , int:: max_value as uint ) as int ,
1053
- Zero => 0 ,
1054
- Minus => num:: min ( ( -self ) . to_uint ( ) ,
1055
- ( int:: max_value as uint ) + 1 ) as int
1056
- }
1076
+ self . to_int_opt ( ) . expect ( "BigInt conversion would overflow int" )
1057
1077
}
1058
1078
1059
1079
#[ inline]
@@ -1179,12 +1199,55 @@ impl BigInt {
1179
1199
.map_move(|bu| BigInt::from_biguint(sign, bu));
1180
1200
}
1181
1201
1202
+ /// Converts this BigInt into a uint, failing if the conversion
1203
+ /// would overflow.
1182
1204
#[inline]
1183
1205
pub fn to_uint(&self) -> uint {
1206
+ self.to_uint_opt().expect(" BigInt conversion would overflow uint")
1207
+ }
1208
+
1209
+ /// Converts this BigInt into a uint, unless it would overflow.
1210
+ #[ inline]
1211
+ pub fn to_uint_opt ( & self ) -> Option < uint > {
1212
+ match self . sign {
1213
+ Plus => self . data . to_uint_opt ( ) ,
1214
+ Zero => Some ( 0 ) ,
1215
+ Minus => None
1216
+ }
1217
+ }
1218
+
1219
+ /// Converts this BigInt into an int, unless it would overflow.
1220
+ pub fn to_int_opt ( & self ) -> Option < int > {
1221
+ match self . sign {
1222
+ Plus => self . data . to_int_opt ( ) ,
1223
+ Zero => Some ( 0 ) ,
1224
+ Minus => self . data . to_uint_opt ( ) . chain ( |n| {
1225
+ let m: uint = 1 << ( 2 * BigDigit :: bits-1 ) ;
1226
+ if ( n > m) {
1227
+ None
1228
+ } else if ( n == m) {
1229
+ Some ( int:: min_value)
1230
+ } else {
1231
+ Some ( -( n as int ) )
1232
+ }
1233
+ } )
1234
+ }
1235
+ }
1236
+
1237
+ /// Converts this BigInt into a BigUint, failing if BigInt is
1238
+ /// negative.
1239
+ #[ inline]
1240
+ pub fn to_biguint ( & self ) -> BigUint {
1241
+ self . to_biguint_opt ( ) . expect ( "negative BigInt cannot convert to BigUint" )
1242
+ }
1243
+
1244
+ /// Converts this BigInt into a BigUint, if it's not negative.
1245
+ #[ inline]
1246
+ pub fn to_biguint_opt ( & self ) -> Option < BigUint > {
1184
1247
match self . sign {
1185
- Plus => self.data.to_uint( ),
1186
- Zero => 0 ,
1187
- Minus => 0
1248
+ Plus => Some ( self . data . clone ( ) ) ,
1249
+ Zero => Some ( Zero :: zero ( ) ) ,
1250
+ Minus => None
1188
1251
}
1189
1252
}
1190
1253
}
@@ -1385,9 +1448,9 @@ mod biguint_tests {
1385
1448
check ( ~[ 0 , 1 ] , ( ( uint:: max_value >> BigDigit :: bits) + 1 ) as int ) ;
1386
1449
check ( ~[ -1 , -1 >> 1 ] , int:: max_value) ;
1387
1450
1388
- assert_eq ! ( BigUint :: new( ~[ 0 , -1 ] ) . to_int ( ) , int :: max_value ) ;
1389
- assert_eq ! ( BigUint :: new( ~[ 0 , 0 , 1 ] ) . to_int ( ) , int :: max_value ) ;
1390
- assert_eq ! ( BigUint :: new( ~[ 0 , 0 , -1 ] ) . to_int ( ) , int :: max_value ) ;
1451
+ assert_eq ! ( BigUint :: new( ~[ 0 , -1 ] ) . to_int_opt ( ) , None ) ;
1452
+ assert_eq ! ( BigUint :: new( ~[ 0 , 0 , 1 ] ) . to_int_opt ( ) , None ) ;
1453
+ assert_eq ! ( BigUint :: new( ~[ 0 , 0 , -1 ] ) . to_int_opt ( ) , None ) ;
1391
1454
}
1392
1455
1393
1456
#[ test]
@@ -1405,8 +1468,19 @@ mod biguint_tests {
1405
1468
check ( ~[ 0 , -1 ] , uint:: max_value << BigDigit :: bits) ;
1406
1469
check ( ~[ -1 , -1 ] , uint:: max_value) ;
1407
1470
1408
- assert_eq ! ( BigUint :: new( ~[ 0 , 0 , 1 ] ) . to_uint( ) , uint:: max_value) ;
1409
- assert_eq ! ( BigUint :: new( ~[ 0 , 0 , -1 ] ) . to_uint( ) , uint:: max_value) ;
1471
+ assert_eq ! ( BigUint :: new( ~[ 0 , 0 , 1 ] ) . to_uint_opt( ) , None ) ;
1472
+ assert_eq ! ( BigUint :: new( ~[ 0 , 0 , -1 ] ) . to_uint_opt( ) , None ) ;
1473
+ }
1474
+
1475
+ #[ test]
1476
+ fn test_convert_to_bigint ( ) {
1477
+ fn check ( n : BigUint , ans : BigInt ) {
1478
+ assert_eq ! ( n. to_bigint( ) , ans) ;
1479
+ assert_eq ! ( n. to_bigint( ) . to_biguint( ) , n) ;
1480
+ }
1481
+ check ( Zero :: zero ( ) , Zero :: zero ( ) ) ;
1482
+ check ( BigUint :: new ( ~[ 1 , 2 , 3 ] ) ,
1483
+ BigInt :: from_biguint ( Plus , BigUint :: new ( ~[ 1 , 2 , 3 ] ) ) ) ;
1410
1484
}
1411
1485
1412
1486
static sum_triples: & ' static [ ( & ' static [ BigDigit ] ,
@@ -1793,22 +1867,21 @@ mod bigint_tests {
1793
1867
Plus , BigUint :: from_uint ( int:: max_value as uint )
1794
1868
) , int:: max_value) ;
1795
1869
1796
- assert ! ( BigInt :: from_biguint(
1870
+ assert_eq ! ( BigInt :: from_biguint(
1797
1871
Plus , BigUint :: from_uint( int:: max_value as uint + 1 )
1798
- ) . to_int ( ) == int :: max_value ) ;
1799
- assert ! ( BigInt :: from_biguint(
1872
+ ) . to_int_opt ( ) , None ) ;
1873
+ assert_eq ! ( BigInt :: from_biguint(
1800
1874
Plus , BigUint :: new( ~[ 1 , 2 , 3 ] )
1801
- ) . to_int ( ) == int :: max_value ) ;
1875
+ ) . to_int_opt ( ) , None ) ;
1802
1876
1803
1877
check ( BigInt :: from_biguint (
1804
- Minus , BigUint :: from_uint ( -int :: min_value as uint )
1878
+ Minus , BigUint :: new ( ~ [ 0 , 1 << ( BigDigit :: bits- 1 ) ] )
1805
1879
) , int:: min_value) ;
1806
- assert ! ( BigInt :: from_biguint(
1807
- Minus , BigUint :: from_uint( -int:: min_value as uint + 1 )
1808
- ) . to_int( ) == int:: min_value) ;
1809
- assert ! ( BigInt :: from_biguint(
1810
- Minus , BigUint :: new( ~[ 1 , 2 , 3 ] )
1811
- ) . to_int( ) == int:: min_value) ;
1880
+ assert_eq ! ( BigInt :: from_biguint(
1881
+ Minus , BigUint :: new( ~[ 1 , 1 <<( BigDigit :: bits-1 ) ] )
1882
+ ) . to_int_opt( ) , None ) ;
1883
+ assert_eq ! ( BigInt :: from_biguint(
1884
+ Minus , BigUint :: new( ~[ 1 , 2 , 3 ] ) ) . to_int_opt( ) , None ) ;
1812
1885
}
1813
1886
1814
1887
#[ test]
@@ -1824,16 +1897,31 @@ mod bigint_tests {
1824
1897
check (
1825
1898
BigInt :: from_biguint ( Plus , BigUint :: from_uint ( uint:: max_value) ) ,
1826
1899
uint:: max_value) ;
1827
- assert ! ( BigInt :: from_biguint(
1828
- Plus , BigUint :: new( ~[ 1 , 2 , 3 ] )
1829
- ) . to_uint( ) == uint:: max_value) ;
1830
-
1831
- assert ! ( BigInt :: from_biguint(
1832
- Minus , BigUint :: from_uint( uint:: max_value)
1833
- ) . to_uint( ) == 0 ) ;
1834
- assert ! ( BigInt :: from_biguint(
1835
- Minus , BigUint :: new( ~[ 1 , 2 , 3 ] )
1836
- ) . to_uint( ) == 0 ) ;
1900
+ assert_eq ! ( BigInt :: from_biguint(
1901
+ Plus , BigUint :: new( ~[ 1 , 2 , 3 ] ) ) . to_uint_opt( ) , None ) ;
1902
+
1903
+ assert_eq ! ( BigInt :: from_biguint(
1904
+ Minus , BigUint :: from_uint( uint:: max_value) ) . to_uint_opt( ) , None ) ;
1905
+ assert_eq ! ( BigInt :: from_biguint(
1906
+ Minus , BigUint :: new( ~[ 1 , 2 , 3 ] ) ) . to_uint_opt( ) , None ) ;
1907
+ }
1908
+
1909
+ #[ test]
1910
+ fn test_convert_to_biguint ( ) {
1911
+ fn check ( n : BigInt , ans_1 : BigUint ) {
1912
+ assert_eq ! ( n. to_biguint( ) , ans_1) ;
1913
+ assert_eq ! ( n. to_biguint( ) . to_bigint( ) , n) ;
1914
+ }
1915
+ let zero: BigInt = Zero :: zero ( ) ;
1916
+ let unsigned_zero: BigUint = Zero :: zero ( ) ;
1917
+ let positive = BigInt :: from_biguint (
1918
+ Plus , BigUint :: new ( ~[ 1 , 2 , 3 ] ) ) ;
1919
+ let negative = -positive;
1920
+
1921
+ check ( zero, unsigned_zero) ;
1922
+ check ( positive, BigUint :: new ( ~[ 1 , 2 , 3 ] ) ) ;
1923
+
1924
+ assert_eq ! ( negative. to_biguint_opt( ) , None ) ;
1837
1925
}
1838
1926
1839
1927
static sum_triples: & ' static [ ( & ' static [ BigDigit ] ,
0 commit comments