From 79933434012636e588da6652bdd18fa358b51a31 Mon Sep 17 00:00:00 2001 From: Leonardo Yvens Schwarzstein Date: Fri, 14 Dec 2018 17:42:26 -0200 Subject: [PATCH 1/3] Fix `to_signed_bytes_*` for positive number with leading `0x80` --- src/bigint.rs | 4 ++-- tests/bigint.rs | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/bigint.rs b/src/bigint.rs index 16caac46..5202e687 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -2759,7 +2759,7 @@ impl BigInt { pub fn to_signed_bytes_be(&self) -> Vec { let mut bytes = self.data.to_bytes_be(); let first_byte = bytes.first().map(|v| *v).unwrap_or(0); - if first_byte > 0x7f && !(first_byte == 0x80 && bytes.iter().skip(1).all(Zero::is_zero)) { + if first_byte > 0x7f && !(first_byte == 0x80 && bytes.iter().skip(1).all(Zero::is_zero) && self.sign == Sign::Minus) { // msb used by magnitude, extend by 1 byte bytes.insert(0, 0); } @@ -2783,7 +2783,7 @@ impl BigInt { pub fn to_signed_bytes_le(&self) -> Vec { let mut bytes = self.data.to_bytes_le(); let last_byte = bytes.last().map(|v| *v).unwrap_or(0); - if last_byte > 0x7f && !(last_byte == 0x80 && bytes.iter().rev().skip(1).all(Zero::is_zero)) + if last_byte > 0x7f && !(last_byte == 0x80 && bytes.iter().rev().skip(1).all(Zero::is_zero) && self.sign == Sign::Minus) { // msb used by magnitude, extend by 1 byte bytes.push(0); diff --git a/tests/bigint.rs b/tests/bigint.rs index 1eb08890..da3e1508 100644 --- a/tests/bigint.rs +++ b/tests/bigint.rs @@ -116,6 +116,7 @@ fn test_to_signed_bytes_le() { check("-100", vec![156]); check("-8388608", vec![0, 0, 0x80]); check("-192", vec![0x40, 0xff]); + check("128", vec![0x80, 0]) } #[test] @@ -157,6 +158,7 @@ fn test_to_signed_bytes_be() { check("-100", vec![156]); check("-8388608", vec![128, 0, 0]); check("-192", vec![0xff, 0x40]); + check("128", vec![0, 0x80]); } #[test] From 443cc8ea1f986a1503adfe75e55527b41d9adc4f Mon Sep 17 00:00:00 2001 From: Leonardo Yvens Schwarzstein Date: Fri, 14 Dec 2018 18:40:51 -0200 Subject: [PATCH 2/3] Run rustfmt --- src/bigint.rs | 32 +++++++++++++++++++------------- src/biguint.rs | 3 ++- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/bigint.rs b/src/bigint.rs index 5202e687..4df63de6 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -710,9 +710,10 @@ impl ShlAssign for BigInt { // Negative values need a rounding adjustment if there are any ones in the // bits that are getting shifted out. fn shr_round_down(i: &BigInt, rhs: usize) -> bool { - i.is_negative() && biguint::trailing_zeros(&i.data) - .map(|n| n < rhs) - .unwrap_or(false) + i.is_negative() + && biguint::trailing_zeros(&i.data) + .map(|n| n < rhs) + .unwrap_or(false) } impl Shr for BigInt { @@ -1126,15 +1127,13 @@ macro_rules! bigint_sub { (_, NoSign) => $a_owned, (NoSign, _) => -$b_owned, // opposite signs => keep the sign of the left with the sum of magnitudes - (Plus, Minus) | (Minus, Plus) => - BigInt::from_biguint($a.sign, $a_data + $b_data), + (Plus, Minus) | (Minus, Plus) => BigInt::from_biguint($a.sign, $a_data + $b_data), // same sign => keep or toggle the sign of the left with the difference of magnitudes - (Plus, Plus) | (Minus, Minus) => - match $a.data.cmp(&$b.data) { - Less => BigInt::from_biguint(-$a.sign, $b_data - $a_data), - Greater => BigInt::from_biguint($a.sign, $a_data - $b_data), - Equal => Zero::zero(), - }, + (Plus, Plus) | (Minus, Minus) => match $a.data.cmp(&$b.data) { + Less => BigInt::from_biguint(-$a.sign, $b_data - $a_data), + Greater => BigInt::from_biguint($a.sign, $a_data - $b_data), + Equal => Zero::zero(), + }, } }; } @@ -2759,7 +2758,11 @@ impl BigInt { pub fn to_signed_bytes_be(&self) -> Vec { let mut bytes = self.data.to_bytes_be(); let first_byte = bytes.first().map(|v| *v).unwrap_or(0); - if first_byte > 0x7f && !(first_byte == 0x80 && bytes.iter().skip(1).all(Zero::is_zero) && self.sign == Sign::Minus) { + if first_byte > 0x7f + && !(first_byte == 0x80 + && bytes.iter().skip(1).all(Zero::is_zero) + && self.sign == Sign::Minus) + { // msb used by magnitude, extend by 1 byte bytes.insert(0, 0); } @@ -2783,7 +2786,10 @@ impl BigInt { pub fn to_signed_bytes_le(&self) -> Vec { let mut bytes = self.data.to_bytes_le(); let last_byte = bytes.last().map(|v| *v).unwrap_or(0); - if last_byte > 0x7f && !(last_byte == 0x80 && bytes.iter().rev().skip(1).all(Zero::is_zero) && self.sign == Sign::Minus) + if last_byte > 0x7f + && !(last_byte == 0x80 + && bytes.iter().rev().skip(1).all(Zero::is_zero) + && self.sign == Sign::Minus) { // msb used by magnitude, extend by 1 byte bytes.push(0); diff --git a/src/biguint.rs b/src/biguint.rs index 71242225..29487385 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -135,7 +135,8 @@ fn from_bitwise_digits_le(v: &[u8], bits: usize) -> BigUint { .iter() .rev() .fold(0, |acc, &c| (acc << bits) | c as BigDigit) - }).collect(); + }) + .collect(); BigUint::new(data) } From 732e8e711424ebe56258d504d5d4f8b72994962b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 14 Dec 2018 12:44:43 -0800 Subject: [PATCH 3/3] Test a range of round trips to/from_signed_bytes --- tests/bigint.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/bigint.rs b/tests/bigint.rs index da3e1508..ba2e6584 100644 --- a/tests/bigint.rs +++ b/tests/bigint.rs @@ -182,6 +182,22 @@ fn test_from_signed_bytes_be() { check(&[0xff, 0x40], "-192"); } +#[test] +fn test_signed_bytes_be_round_trip() { + for i in -0x1FFFF..0x20000 { + let n = BigInt::from(i); + assert_eq!(n, BigInt::from_signed_bytes_be(&n.to_signed_bytes_be())); + } +} + +#[test] +fn test_signed_bytes_le_round_trip() { + for i in -0x1FFFF..0x20000 { + let n = BigInt::from(i); + assert_eq!(n, BigInt::from_signed_bytes_le(&n.to_signed_bytes_le())); + } +} + #[test] fn test_cmp() { let vs: [&[u32]; 4] = [&[2 as u32], &[1, 1], &[2, 1], &[1, 1, 1]];