@@ -465,7 +465,7 @@ impl Integer for BigUint {
465465impl IntConvertible for BigUint {
466466 #[ inline]
467467 fn to_int ( & self ) -> int {
468- num :: min ( self . to_uint ( ) , int :: max_value as uint ) as int
468+ self . to_int_opt ( ) . expect ( "BigUint conversion would overflow int" )
469469 }
470470
471471 #[ inline]
@@ -577,19 +577,38 @@ impl BigUint {
577577 }
578578
579579
580- /// Converts this big integer into a uint, returning the uint::max_value if
581- /// it's too large to fit in a uint .
580+ /// Converts this BigUint into a uint, failing if the conversion
581+ /// would overflow .
582582 #[ inline]
583583 pub fn to_uint ( & self ) -> uint {
584+ self . to_uint_opt ( ) . expect ( "BigUint conversion would overflow uint" )
585+ }
586+
587+ /// Converts this BigUint into a uint, unless it would overflow.
588+ #[ inline]
589+ pub fn to_uint_opt ( & self ) -> Option < uint > {
584590 match self . data . len ( ) {
585- 0 => 0 ,
586- 1 => self . data [ 0 ] as uint ,
587- 2 => BigDigit :: to_uint ( self . data [ 1 ] , self . data [ 0 ] ) ,
588- _ => uint :: max_value
591+ 0 => Some ( 0 ) ,
592+ 1 => Some ( self . data [ 0 ] as uint ) ,
593+ 2 => Some ( BigDigit :: to_uint ( self . data [ 1 ] , self . data [ 0 ] ) ) ,
594+ _ => None
589595 }
590596 }
591597
592- /// Converts this BigUint into a positively-signed BigInt.
598+ // Converts this BigUint into an int, unless it would overflow.
599+ pub fn to_int_opt ( & self ) -> Option < int > {
600+ self . to_uint_opt ( ) . chain ( |n| {
601+ // If top bit of uint is set, it's too large to convert to
602+ // int.
603+ if ( n >> ( 2 * BigDigit :: bits - 1 ) != 0 ) {
604+ None
605+ } else {
606+ Some ( n as int )
607+ }
608+ } )
609+ }
610+
611+ /// Converts this BigUint into a BigInt.
593612 #[ inline]
594613 pub fn to_bigint ( & self ) -> BigInt {
595614 BigInt :: from_biguint ( Plus , self . clone ( ) )
@@ -1016,12 +1035,7 @@ impl Integer for BigInt {
10161035impl IntConvertible for BigInt {
10171036 #[ inline]
10181037 fn to_int ( & self ) -> int {
1019- match self . sign {
1020- Plus => num:: min ( self . to_uint ( ) , int:: max_value as uint ) as int ,
1021- Zero => 0 ,
1022- Minus => num:: min ( ( -self ) . to_uint ( ) ,
1023- ( int:: max_value as uint ) + 1 ) as int
1024- }
1038+ self . to_int_opt ( ) . expect ( "BigInt conversion would overflow int" )
10251039 }
10261040
10271041 #[ inline]
@@ -1100,22 +1114,55 @@ impl BigInt {
11001114 .map_move(|bu| BigInt::from_biguint(sign, bu));
11011115 }
11021116
1117+ /// Converts this BigInt into a uint, failing if the conversion
1118+ /// would overflow.
11031119 #[inline]
11041120 pub fn to_uint(&self) -> uint {
1121+ self.to_uint_opt().expect(" BigInt conversion would overflow uint")
1122+ }
1123+
1124+ /// Converts this BigInt into a uint, unless it would overflow.
1125+ #[ inline]
1126+ pub fn to_uint_opt ( & self ) -> Option < uint > {
11051127 match self . sign {
1106- Plus => self.data.to_uint (),
1107- Zero => 0 ,
1108- Minus => 0
1128+ Plus => self . data . to_uint_opt ( ) ,
1129+ Zero => Some ( 0 ) ,
1130+ Minus => None
11091131 }
11101132 }
11111133
1112- /// Converts this BigInt into a BigUint. Negative BigInts are
1113- /// converted to zero-valued BigUints.
1134+ /// Converts this BigInt into an int, unless it would overflow.
1135+ pub fn to_int_opt ( & self ) -> Option < int > {
1136+ match self . sign {
1137+ Plus => self . data . to_int_opt ( ) ,
1138+ Zero => Some ( 0 ) ,
1139+ Minus => self . data . to_uint_opt ( ) . chain ( |n| {
1140+ let m: uint = 1 << ( 2 * BigDigit :: bits-1 ) ;
1141+ if ( n > m) {
1142+ None
1143+ } else if ( n == m) {
1144+ Some ( int:: min_value)
1145+ } else {
1146+ Some ( -( n as int ) )
1147+ }
1148+ } )
1149+ }
1150+ }
1151+
1152+ /// Converts this BigInt into a BigUint, failing if BigInt is
1153+ /// negative.
11141154 #[ inline]
11151155 pub fn to_biguint ( & self ) -> BigUint {
1156+ self . to_biguint_opt ( ) . expect ( "negative BigInt cannot convert to BigUint" )
1157+ }
1158+
1159+ /// Converts this BigInt into a BigUint, if it's not negative.
1160+ #[ inline]
1161+ pub fn to_biguint_opt ( & self ) -> Option < BigUint > {
11161162 match self . sign {
1117- Plus => self.data.clone(),
1118- _ => Zero::zero()
1163+ Plus => Some ( self . data . clone ( ) ) ,
1164+ Zero => Some ( Zero :: zero ( ) ) ,
1165+ Minus => None
11191166 }
11201167 }
11211168}
@@ -1273,9 +1320,9 @@ mod biguint_tests {
12731320 check ( ~[ 0 , 1 ] , ( ( uint:: max_value >> BigDigit :: bits) + 1 ) as int ) ;
12741321 check ( ~[ -1 , -1 >> 1 ] , int:: max_value) ;
12751322
1276- assert_eq ! ( BigUint :: new( ~[ 0 , -1 ] ) . to_int ( ) , int :: max_value ) ;
1277- assert_eq ! ( BigUint :: new( ~[ 0 , 0 , 1 ] ) . to_int ( ) , int :: max_value ) ;
1278- assert_eq ! ( BigUint :: new( ~[ 0 , 0 , -1 ] ) . to_int ( ) , int :: max_value ) ;
1323+ assert_eq ! ( BigUint :: new( ~[ 0 , -1 ] ) . to_int_opt ( ) , None ) ;
1324+ assert_eq ! ( BigUint :: new( ~[ 0 , 0 , 1 ] ) . to_int_opt ( ) , None ) ;
1325+ assert_eq ! ( BigUint :: new( ~[ 0 , 0 , -1 ] ) . to_int_opt ( ) , None ) ;
12791326 }
12801327
12811328 #[ test]
@@ -1293,8 +1340,8 @@ mod biguint_tests {
12931340 check ( ~[ 0 , -1 ] , uint:: max_value << BigDigit :: bits) ;
12941341 check ( ~[ -1 , -1 ] , uint:: max_value) ;
12951342
1296- assert_eq ! ( BigUint :: new( ~[ 0 , 0 , 1 ] ) . to_uint ( ) , uint :: max_value ) ;
1297- assert_eq ! ( BigUint :: new( ~[ 0 , 0 , -1 ] ) . to_uint ( ) , uint :: max_value ) ;
1343+ assert_eq ! ( BigUint :: new( ~[ 0 , 0 , 1 ] ) . to_uint_opt ( ) , None ) ;
1344+ assert_eq ! ( BigUint :: new( ~[ 0 , 0 , -1 ] ) . to_uint_opt ( ) , None ) ;
12981345 }
12991346
13001347 #[ test]
@@ -1304,7 +1351,8 @@ mod biguint_tests {
13041351 assert_eq ! ( n. to_bigint( ) . to_biguint( ) , n) ;
13051352 }
13061353 check ( Zero :: zero ( ) , Zero :: zero ( ) ) ;
1307- check( BigUint :: from_uint( 637 ) , BigInt :: from_uint( 637 ) ) ;
1354+ check ( BigUint :: new ( ~[ 1 , 2 , 3 ] ) ,
1355+ BigInt :: from_biguint ( Plus , BigUint :: new ( ~[ 1 , 2 , 3 ] ) ) ) ;
13081356 }
13091357
13101358 static sum_triples: & ' static [ ( & ' static [ BigDigit ] ,
@@ -1683,22 +1731,21 @@ mod bigint_tests {
16831731 Plus , BigUint :: from_uint ( int:: max_value as uint )
16841732 ) , int:: max_value) ;
16851733
1686- assert ! ( BigInt :: from_biguint(
1734+ assert_eq ! ( BigInt :: from_biguint(
16871735 Plus , BigUint :: from_uint( int:: max_value as uint + 1 )
1688- ) . to_int ( ) == int :: max_value ) ;
1689- assert ! ( BigInt :: from_biguint(
1736+ ) . to_int_opt ( ) , None ) ;
1737+ assert_eq ! ( BigInt :: from_biguint(
16901738 Plus , BigUint :: new( ~[ 1 , 2 , 3 ] )
1691- ) . to_int ( ) == int :: max_value ) ;
1739+ ) . to_int_opt ( ) , None ) ;
16921740
16931741 check ( BigInt :: from_biguint (
1694- Minus , BigUint :: from_uint ( -int :: min_value as uint )
1742+ Minus , BigUint :: new ( ~ [ 0 , 1 << ( BigDigit :: bits- 1 ) ] )
16951743 ) , int:: min_value) ;
1696- assert ! ( BigInt :: from_biguint(
1697- Minus , BigUint :: from_uint( -int:: min_value as uint + 1 )
1698- ) . to_int( ) == int:: min_value) ;
1699- assert ! ( BigInt :: from_biguint(
1700- Minus , BigUint :: new( ~[ 1 , 2 , 3 ] )
1701- ) . to_int( ) == int:: min_value) ;
1744+ assert_eq ! ( BigInt :: from_biguint(
1745+ Minus , BigUint :: new( ~[ 1 , 1 <<( BigDigit :: bits-1 ) ] )
1746+ ) . to_int_opt( ) , None ) ;
1747+ assert_eq ! ( BigInt :: from_biguint(
1748+ Minus , BigUint :: new( ~[ 1 , 2 , 3 ] ) ) . to_int_opt( ) , None ) ;
17021749 }
17031750
17041751 #[ test]
@@ -1714,31 +1761,31 @@ mod bigint_tests {
17141761 check (
17151762 BigInt :: from_biguint ( Plus , BigUint :: from_uint ( uint:: max_value) ) ,
17161763 uint:: max_value) ;
1717- assert ! ( BigInt :: from_biguint(
1718- Plus , BigUint :: new( ~[ 1 , 2 , 3 ] )
1719- ) . to_uint( ) == uint:: max_value) ;
1764+ assert_eq ! ( BigInt :: from_biguint(
1765+ Plus , BigUint :: new( ~[ 1 , 2 , 3 ] ) ) . to_uint_opt( ) , None ) ;
17201766
1721- assert ! ( BigInt :: from_biguint(
1722- Minus , BigUint :: from_uint( uint:: max_value)
1723- ) . to_uint( ) == 0 ) ;
1724- assert ! ( BigInt :: from_biguint(
1725- Minus , BigUint :: new( ~[ 1 , 2 , 3 ] )
1726- ) . to_uint( ) == 0 ) ;
1767+ assert_eq ! ( BigInt :: from_biguint(
1768+ Minus , BigUint :: from_uint( uint:: max_value) ) . to_uint_opt( ) , None ) ;
1769+ assert_eq ! ( BigInt :: from_biguint(
1770+ Minus , BigUint :: new( ~[ 1 , 2 , 3 ] ) ) . to_uint_opt( ) , None ) ;
17271771 }
17281772
17291773 #[ test]
17301774 fn test_convert_to_biguint ( ) {
1731- fn check ( n : BigInt , ans_1 : BigUint , ans_2 : BigInt ) {
1775+ fn check ( n : BigInt , ans_1 : BigUint ) {
17321776 assert_eq ! ( n. to_biguint( ) , ans_1) ;
1733- assert_eq ! ( n. to_biguint( ) . to_bigint( ) , ans_2 ) ;
1777+ assert_eq ! ( n. to_biguint( ) . to_bigint( ) , n ) ;
17341778 }
17351779 let zero: BigInt = Zero :: zero ( ) ;
17361780 let unsigned_zero: BigUint = Zero :: zero ( ) ;
1737- let positive: BigInt = BigInt :: from_uint ( 637 ) ;
1781+ let positive = BigInt :: from_biguint (
1782+ Plus , BigUint :: new ( ~[ 1 , 2 , 3 ] ) ) ;
17381783 let negative = -positive;
1739- check ( zero. clone ( ) , unsigned_zero. clone ( ) , zero. clone ( ) ) ;
1740- check ( positive. clone ( ) , BigUint :: from_uint ( 637 ) , positive) ;
1741- check ( negative, unsigned_zero, zero) ;
1784+
1785+ check ( zero, unsigned_zero) ;
1786+ check ( positive, BigUint :: new ( ~[ 1 , 2 , 3 ] ) ) ;
1787+
1788+ assert_eq ! ( negative. to_biguint_opt( ) , None ) ;
17421789 }
17431790
17441791 static sum_triples: & ' static [ ( & ' static [ BigDigit ] ,
0 commit comments