@@ -503,7 +503,7 @@ impl Integer for BigUint {
503503impl IntConvertible for BigUint {
504504 #[ inline]
505505 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" )
507507 }
508508
509509 #[ inline]
@@ -615,18 +615,43 @@ impl BigUint {
615615 }
616616
617617
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 .
620620 #[ inline]
621621 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 > {
622628 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
627633 }
628634 }
629635
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+
630655 #[ inline]
631656 fn shl_unit ( & self , n_unit : uint ) -> BigUint {
632657 if n_unit == 0 || self . is_zero ( ) { return ( * self ) . clone ( ) ; }
@@ -1048,12 +1073,7 @@ impl Integer for BigInt {
10481073impl IntConvertible for BigInt {
10491074 #[ inline]
10501075 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" )
10571077 }
10581078
10591079 #[ inline]
@@ -1179,12 +1199,55 @@ impl BigInt {
11791199 .map_move(|bu| BigInt::from_biguint(sign, bu));
11801200 }
11811201
1202+ /// Converts this BigInt into a uint, failing if the conversion
1203+ /// would overflow.
11821204 #[inline]
11831205 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 > {
11841247 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
11881251 }
11891252 }
11901253}
@@ -1385,9 +1448,9 @@ mod biguint_tests {
13851448 check ( ~[ 0 , 1 ] , ( ( uint:: max_value >> BigDigit :: bits) + 1 ) as int ) ;
13861449 check ( ~[ -1 , -1 >> 1 ] , int:: max_value) ;
13871450
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 ) ;
13911454 }
13921455
13931456 #[ test]
@@ -1405,8 +1468,19 @@ mod biguint_tests {
14051468 check ( ~[ 0 , -1 ] , uint:: max_value << BigDigit :: bits) ;
14061469 check ( ~[ -1 , -1 ] , uint:: max_value) ;
14071470
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 ] ) ) ) ;
14101484 }
14111485
14121486 static sum_triples: & ' static [ ( & ' static [ BigDigit ] ,
@@ -1793,22 +1867,21 @@ mod bigint_tests {
17931867 Plus , BigUint :: from_uint ( int:: max_value as uint )
17941868 ) , int:: max_value) ;
17951869
1796- assert ! ( BigInt :: from_biguint(
1870+ assert_eq ! ( BigInt :: from_biguint(
17971871 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(
18001874 Plus , BigUint :: new( ~[ 1 , 2 , 3 ] )
1801- ) . to_int ( ) == int :: max_value ) ;
1875+ ) . to_int_opt ( ) , None ) ;
18021876
18031877 check ( BigInt :: from_biguint (
1804- Minus , BigUint :: from_uint ( -int :: min_value as uint )
1878+ Minus , BigUint :: new ( ~ [ 0 , 1 << ( BigDigit :: bits- 1 ) ] )
18051879 ) , 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 ) ;
18121885 }
18131886
18141887 #[ test]
@@ -1824,16 +1897,31 @@ mod bigint_tests {
18241897 check (
18251898 BigInt :: from_biguint ( Plus , BigUint :: from_uint ( uint:: max_value) ) ,
18261899 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 ) ;
18371925 }
18381926
18391927 static sum_triples: & ' static [ ( & ' static [ BigDigit ] ,
0 commit comments