Skip to content

Commit 4d13ac0

Browse files
committed
fix both libgmp and num-bigin builds
1 parent ea0e742 commit 4d13ac0

File tree

5 files changed

+115
-69
lines changed

5 files changed

+115
-69
lines changed

src/more_ops.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ pub fn op_div_impl(a: &mut Allocator, input: NodePtr, mempool: bool) -> Response
436436

437437
// this is to preserve a buggy behavior from the initial implementation
438438
// of this operator.
439-
if q == -1 && r != 0 {
439+
if q.equal(-1) && r.not_equal(0) {
440440
q += 1;
441441
}
442442
let q1 = ptr_from_number(a, &q)?;
@@ -807,7 +807,7 @@ pub fn op_softfork(a: &mut Allocator, input: NodePtr, max_cost: Cost) -> Respons
807807
Some((p1, _)) => {
808808
let n: Number = Number::from_u8(int_atom(&p1, "softfork")?);
809809
if n.sign() == Sign::Plus {
810-
if n > max_cost {
810+
if n.greater_than(max_cost) {
811811
return err(a.null(), "cost exceeded");
812812
}
813813
let cost: Cost = n.to_u64();

src/number.rs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,18 @@ pub use num_bigint::BigInt as Number;
77
pub use num_bigint::Sign;
88

99
use crate::allocator::{Allocator, NodePtr};
10+
use crate::number_traits::NumberTraits;
1011
use crate::reduction::EvalErr;
1112

1213
pub fn ptr_from_number(allocator: &mut Allocator, item: &Number) -> Result<NodePtr, EvalErr> {
13-
let bytes: Vec<u8> = item.to_signed_bytes_be();
14+
let bytes: Vec<u8> = item.to_signed_bytes();
1415
allocator.new_atom(bytes.as_slice())
1516
}
1617

1718
#[cfg(test)]
1819
#[cfg(feature = "num-bigint")]
1920
impl crate::number_traits::TestNumberTraits for Number {
20-
fn from_str_radix(mut s: &str, radix: i32) -> Number {
21+
fn from_str_radix(s: &str, radix: i32) -> Number {
2122
num_traits::Num::from_str_radix(s, radix as u32).unwrap()
2223
}
2324
}
@@ -29,6 +30,19 @@ impl crate::number_traits::NumberTraits for Number {
2930
i.into()
3031
}
3132

33+
fn to_signed_bytes(&self) -> Vec<u8> {
34+
let mut ret = self.to_signed_bytes_be();
35+
36+
// make number minimal by removing leading zeros
37+
while (!ret.is_empty()) && (ret[0] == 0) {
38+
if ret.len() > 1 && (ret[1] & 0x80 == 0x80) {
39+
break;
40+
}
41+
ret.remove(0);
42+
}
43+
ret
44+
}
45+
3246
fn zero() -> Number {
3347
<Number as num_traits::Zero>::zero()
3448
}
@@ -42,17 +56,30 @@ impl crate::number_traits::NumberTraits for Number {
4256
}
4357
}
4458

45-
fn to_u64(n: &Number) -> u64 {
46-
n.into()
59+
fn to_u64(&self) -> u64 {
60+
use std::convert::TryFrom;
61+
TryFrom::try_from(self).unwrap()
4762
}
4863

4964
fn div_mod_floor(&self, denominator: &Number) -> (Number, Number) {
50-
self.div_mod_floor(denominator)
65+
num_integer::Integer::div_mod_floor(self, denominator)
5166
}
5267

5368
fn mod_floor(&self, denominator: &Number) -> Number {
5469
num_integer::Integer::mod_floor(&self, denominator)
5570
}
71+
72+
fn equal(&self, other: i64) -> bool {
73+
self == &Number::from(other)
74+
}
75+
76+
fn not_equal(&self, other: i64) -> bool {
77+
self != &Number::from(other)
78+
}
79+
80+
fn greater_than(&self, other: u64) -> bool {
81+
self > &Number::from(other)
82+
}
5683
}
5784

5885
#[test]
@@ -115,4 +142,3 @@ fn test_ptr_from_number() {
115142
let ptr = ptr_from_number(&mut a, &num).unwrap();
116143
assert_eq!(&[0x40, 0x00], &a.atom(ptr));
117144
}
118-

src/number_gmp.rs

Lines changed: 72 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use crate::gmp_ffi as gmp;
22
use crate::node::Node;
3+
use crate::number_traits::NumberTraits;
4+
#[cfg(test)]
5+
use crate::number_traits::TestNumberTraits;
36
use core::mem::MaybeUninit;
47
use std::cmp::Ordering;
58
use std::cmp::PartialOrd;
@@ -8,9 +11,6 @@ use std::ops::Drop;
811
use std::ops::{
912
AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, MulAssign, Not, Shl, Shr, SubAssign,
1013
};
11-
use crate::number_traits::NumberTraits;
12-
#[cfg(test)]
13-
use crate::number_traits::TestNumberTraits;
1414

1515
#[allow(clippy::enum_variant_names)]
1616
#[derive(PartialEq)]
@@ -60,6 +60,49 @@ impl NumberTraits for Number {
6060
ret
6161
}
6262

63+
fn to_signed_bytes(&self) -> Vec<u8> {
64+
let size = (self.bits() + 7) / 8;
65+
let mut ret: Vec<u8> = Vec::new();
66+
if size == 0 {
67+
return ret;
68+
}
69+
ret.resize(size + 1, 0);
70+
let sign = self.sign();
71+
let mut out_size: usize = size;
72+
unsafe {
73+
gmp::mpz_export(
74+
ret.as_mut_slice()[1..].as_mut_ptr() as *mut c_void,
75+
&mut out_size,
76+
1,
77+
1,
78+
0,
79+
0,
80+
&self.v,
81+
);
82+
}
83+
// apparently mpz_export prints 0 bytes to the buffer if the value is 0
84+
// hence the special case in the assert below.
85+
assert!(out_size == ret.len() - 1);
86+
if sign == Sign::Minus {
87+
// If the value is negative, we need to convert it to two's
88+
// complement. We can't do that in-place.
89+
let mut carry = true;
90+
for digit in &mut ret.iter_mut().rev() {
91+
let res = (!*digit).overflowing_add(carry as u8);
92+
*digit = res.0;
93+
carry = res.1;
94+
}
95+
assert!(!carry);
96+
assert!(ret[0] & 0x80 != 0);
97+
if (ret[1] & 0x80) != 0 {
98+
ret.remove(0);
99+
}
100+
} else if ret[1] & 0x80 == 0 {
101+
ret.remove(0);
102+
}
103+
ret
104+
}
105+
63106
fn zero() -> Number {
64107
let mut v = MaybeUninit::<gmp::mpz_t>::uninit();
65108
unsafe {
@@ -74,8 +117,8 @@ impl NumberTraits for Number {
74117
Number::from_signed_bytes_be(v)
75118
}
76119

77-
fn to_u64(n: &Number) -> u64 {
78-
n.into()
120+
fn to_u64(&self) -> u64 {
121+
u64::from(self)
79122
}
80123

81124
// returns the quotient and remained, from dividing self with denominator
@@ -95,6 +138,18 @@ impl NumberTraits for Number {
95138
}
96139
r
97140
}
141+
142+
fn equal(&self, other: i64) -> bool {
143+
self == &other
144+
}
145+
146+
fn not_equal(&self, other: i64) -> bool {
147+
self != &other
148+
}
149+
150+
fn greater_than(&self, other: u64) -> bool {
151+
self > &other
152+
}
98153
}
99154

100155
impl Number {
@@ -128,49 +183,6 @@ impl Number {
128183
ret
129184
}
130185

131-
pub fn to_signed_bytes_be(&self) -> Vec<u8> {
132-
let size = (self.bits() + 7) / 8;
133-
let mut ret: Vec<u8> = Vec::new();
134-
if size == 0 {
135-
return ret;
136-
}
137-
ret.resize(size + 1, 0);
138-
let sign = self.sign();
139-
let mut out_size: usize = size;
140-
unsafe {
141-
gmp::mpz_export(
142-
ret.as_mut_slice()[1..].as_mut_ptr() as *mut c_void,
143-
&mut out_size,
144-
1,
145-
1,
146-
0,
147-
0,
148-
&self.v,
149-
);
150-
}
151-
// apparently mpz_export prints 0 bytes to the buffer if the value is 0
152-
// hence the special case in the assert below.
153-
assert!(out_size == ret.len() - 1);
154-
if sign == Sign::Minus {
155-
// If the value is negative, we need to convert it to two's
156-
// complement. We can't do that in-place.
157-
let mut carry = true;
158-
for digit in &mut ret.iter_mut().rev() {
159-
let res = (!*digit).overflowing_add(carry as u8);
160-
*digit = res.0;
161-
carry = res.1;
162-
}
163-
assert!(!carry);
164-
assert!(ret[0] & 0x80 != 0);
165-
if (ret[1] & 0x80) != 0 {
166-
ret.remove(0);
167-
}
168-
} else if ret[1] & 0x80 == 0 {
169-
ret.remove(0);
170-
}
171-
ret
172-
}
173-
174186
pub fn to_bytes_le(&self) -> (Sign, Vec<u8>) {
175187
let sgn = self.sign();
176188

@@ -345,8 +357,8 @@ impl From<usize> for Number {
345357
}
346358
}
347359

348-
impl From<Number> for u64 {
349-
fn from(n: Number) -> u64 {
360+
impl From<&Number> for u64 {
361+
fn from(n: &Number) -> u64 {
350362
unsafe {
351363
assert!(gmp::mpz_sizeinbase(&n.v, 2) <= 64);
352364
assert!(gmp::mpz_cmp_si(&n.v, 0) >= 0);
@@ -355,8 +367,8 @@ impl From<Number> for u64 {
355367
}
356368
}
357369

358-
impl From<Number> for i64 {
359-
fn from(n: Number) -> i64 {
370+
impl From<&Number> for i64 {
371+
fn from(n: &Number) -> i64 {
360372
unsafe {
361373
assert!(gmp::mpz_sizeinbase(&n.v, 2) <= 64);
362374
gmp::mpz_get_si(&n.v)
@@ -456,6 +468,9 @@ impl From<&Node<'_>> for Option<Number> {
456468
}
457469
}
458470

471+
// TODO: move all tests to number.rs so we can test both the GMP and num-bigint
472+
// versions
473+
459474
// ==== TESTS ====
460475

461476
#[cfg(test)]
@@ -489,7 +504,7 @@ fn roundtrip_bytes(b: &[u8]) {
489504
assert!(num.sign() == Sign::Plus);
490505
}
491506

492-
let round_trip = num.to_signed_bytes_be();
507+
let round_trip = num.to_signed_bytes();
493508

494509
assert_eq!(round_trip, b);
495510

@@ -516,7 +531,7 @@ fn roundtrip_bytes(b: &[u8]) {
516531
unsafe {
517532
gmp::mpz_neg(&mut negated.v, &num.v);
518533
}
519-
let magnitude = negated.to_signed_bytes_be();
534+
let magnitude = negated.to_signed_bytes();
520535
assert!(buf_le.iter().eq(magnitude.iter().rev()));
521536
}
522537
}
@@ -525,7 +540,7 @@ fn roundtrip_bytes(b: &[u8]) {
525540
{
526541
let unsigned_num = Number::from_unsigned_bytes_be(b);
527542
assert!(unsigned_num.sign() != Sign::Minus);
528-
let unsigned_round_trip = unsigned_num.to_signed_bytes_be();
543+
let unsigned_round_trip = unsigned_num.to_signed_bytes();
529544
let unsigned_round_trip = if unsigned_round_trip == &[0] {
530545
&unsigned_round_trip[1..]
531546
} else {
@@ -610,7 +625,7 @@ fn roundtrip_u64(v: u64) {
610625
assert!(num >= v - 1);
611626
}
612627

613-
let round_trip: u64 = num.into();
628+
let round_trip: u64 = (&num).into();
614629
assert_eq!(round_trip, v);
615630
}
616631

@@ -656,7 +671,7 @@ fn roundtrip_i64(v: i64) {
656671
}
657672

658673
assert!(num.bits() <= 64);
659-
let round_trip: i64 = num.into();
674+
let round_trip: i64 = (&num).into();
660675
assert_eq!(round_trip, v);
661676
}
662677

src/number_traits.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
21
pub trait NumberTraits {
32
fn from_unsigned_bytes_be(v: &[u8]) -> Self;
3+
fn to_signed_bytes(&self) -> Vec<u8>;
44
fn zero() -> Self;
55
fn from_u8(v: &[u8]) -> Self;
6-
fn to_u64(n: &Self) -> u64;
7-
fn div_mod_floor(&self, denominator: &Self) -> (Self, Self) where Self: Sized;
6+
fn to_u64(&self) -> u64;
7+
fn div_mod_floor(&self, denominator: &Self) -> (Self, Self)
8+
where
9+
Self: Sized;
810
fn mod_floor(&self, denominator: &Self) -> Self;
11+
fn equal(&self, other: i64) -> bool;
12+
fn not_equal(&self, other: i64) -> bool;
13+
fn greater_than(&self, other: u64) -> bool;
914
}
1015

1116
#[cfg(test)]

src/test_ops.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ use crate::more_ops::{
77
op_point_add, op_pubkey_for_exp, op_sha256, op_softfork, op_strlen, op_substr, op_subtract,
88
};
99
use crate::number::{ptr_from_number, Number};
10+
use crate::number_traits::TestNumberTraits;
1011
use crate::reduction::{Reduction, Response};
1112
use hex::FromHex;
1213
use std::collections::HashMap;
13-
use crate::number_traits::TestNumberTraits;
1414

1515
static TEST_CASES: &str = r#"
1616
lognot ( 1 2 3 ) => FAIL

0 commit comments

Comments
 (0)