@@ -465,7 +465,7 @@ impl Integer for BigUint {
465
465
impl IntConvertible for BigUint {
466
466
#[ inline]
467
467
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" )
469
469
}
470
470
471
471
#[ inline]
@@ -577,19 +577,38 @@ impl BigUint {
577
577
}
578
578
579
579
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 .
582
582
#[ inline]
583
583
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 > {
584
590
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
589
595
}
590
596
}
591
597
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.
593
612
#[ inline]
594
613
pub fn to_bigint ( & self ) -> BigInt {
595
614
BigInt :: from_biguint ( Plus , self . clone ( ) )
@@ -1016,12 +1035,7 @@ impl Integer for BigInt {
1016
1035
impl IntConvertible for BigInt {
1017
1036
#[ inline]
1018
1037
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" )
1025
1039
}
1026
1040
1027
1041
#[ inline]
@@ -1100,22 +1114,55 @@ impl BigInt {
1100
1114
.map_move(|bu| BigInt::from_biguint(sign, bu));
1101
1115
}
1102
1116
1117
+ /// Converts this BigInt into a uint, failing if the conversion
1118
+ /// would overflow.
1103
1119
#[inline]
1104
1120
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 > {
1105
1127
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
1109
1131
}
1110
1132
}
1111
1133
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.
1114
1154
#[ inline]
1115
1155
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 > {
1116
1162
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
1119
1166
}
1120
1167
}
1121
1168
}
@@ -1273,9 +1320,9 @@ mod biguint_tests {
1273
1320
check ( ~[ 0 , 1 ] , ( ( uint:: max_value >> BigDigit :: bits) + 1 ) as int ) ;
1274
1321
check ( ~[ -1 , -1 >> 1 ] , int:: max_value) ;
1275
1322
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 ) ;
1279
1326
}
1280
1327
1281
1328
#[ test]
@@ -1293,8 +1340,8 @@ mod biguint_tests {
1293
1340
check ( ~[ 0 , -1 ] , uint:: max_value << BigDigit :: bits) ;
1294
1341
check ( ~[ -1 , -1 ] , uint:: max_value) ;
1295
1342
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 ) ;
1298
1345
}
1299
1346
1300
1347
#[ test]
@@ -1304,7 +1351,8 @@ mod biguint_tests {
1304
1351
assert_eq ! ( n. to_bigint( ) . to_biguint( ) , n) ;
1305
1352
}
1306
1353
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 ] ) ) ) ;
1308
1356
}
1309
1357
1310
1358
static sum_triples: & ' static [ ( & ' static [ BigDigit ] ,
@@ -1683,22 +1731,21 @@ mod bigint_tests {
1683
1731
Plus , BigUint :: from_uint ( int:: max_value as uint )
1684
1732
) , int:: max_value) ;
1685
1733
1686
- assert ! ( BigInt :: from_biguint(
1734
+ assert_eq ! ( BigInt :: from_biguint(
1687
1735
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(
1690
1738
Plus , BigUint :: new( ~[ 1 , 2 , 3 ] )
1691
- ) . to_int ( ) == int :: max_value ) ;
1739
+ ) . to_int_opt ( ) , None ) ;
1692
1740
1693
1741
check ( BigInt :: from_biguint (
1694
- Minus , BigUint :: from_uint ( -int :: min_value as uint )
1742
+ Minus , BigUint :: new ( ~ [ 0 , 1 << ( BigDigit :: bits- 1 ) ] )
1695
1743
) , 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 ) ;
1702
1749
}
1703
1750
1704
1751
#[ test]
@@ -1714,31 +1761,31 @@ mod bigint_tests {
1714
1761
check (
1715
1762
BigInt :: from_biguint ( Plus , BigUint :: from_uint ( uint:: max_value) ) ,
1716
1763
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 ) ;
1720
1766
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 ) ;
1727
1771
}
1728
1772
1729
1773
#[ test]
1730
1774
fn test_convert_to_biguint ( ) {
1731
- fn check ( n : BigInt , ans_1 : BigUint , ans_2 : BigInt ) {
1775
+ fn check ( n : BigInt , ans_1 : BigUint ) {
1732
1776
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 ) ;
1734
1778
}
1735
1779
let zero: BigInt = Zero :: zero ( ) ;
1736
1780
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 ] ) ) ;
1738
1783
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 ) ;
1742
1789
}
1743
1790
1744
1791
static sum_triples: & ' static [ ( & ' static [ BigDigit ] ,
0 commit comments