Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ jobs:
echo " lock_api -> 0.4.12"
echo " quote -> 1.0.40"
echo " unicode-ident -> 1.0.13"
echo " zeroize -> 1.8.1"
cargo update -p parking_lot --precise 0.12.3
cargo update -p lock_api --precise 0.4.12
cargo update -p quote --precise 1.0.40
cargo update -p unicode-ident --precise 1.0.13
cargo update -p zeroize --precise 1.8.1
elif [ "${{ matrix.rust }}" = "1.85" ]; then
echo "Pinning packages for Rust 1.85:"
echo " diesel -> 2.2.12"
Expand Down
16 changes: 10 additions & 6 deletions base/benches/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ macro_rules! uop_case {
($t:ty, $bits:literal, $method:ident, $rng:ident, $group:ident) => {
let bits = $bits;
let a: $t = $rng.gen_range(0..1 << $bits);
$group.bench_with_input(BenchmarkId::from_parameter(bits), &bits, |bencher, _| {
bencher.iter(|| black_box(a).$method())
});
$group.bench_with_input(
BenchmarkId::from_parameter(format!("{}b", bits)),
&bits,
|bencher, _| bencher.iter(|| black_box(a).$method()),
);
};
}

Expand All @@ -25,9 +27,11 @@ macro_rules! binop_case {
let bits = $bits;
let a: $t = $rng.gen_range(0..1 << $bits);
let b: $t = $rng.gen_range(0..1 << $bits);
$group.bench_with_input(BenchmarkId::from_parameter(bits), &bits, |bencher, _| {
bencher.iter(|| black_box(a).$method(black_box(b)))
});
$group.bench_with_input(
BenchmarkId::from_parameter(format!("{}b", bits)),
&bits,
|bencher, _| bencher.iter(|| black_box(a).$method(black_box(b))),
);
};
}

Expand Down
44 changes: 27 additions & 17 deletions float/benches/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,17 @@ fn dbig_to_string(criterion: &mut Criterion) {
let precision = 10usize.pow(log_prec);
let a = random_dbig(precision, &mut rng);
let mut out = String::new();
group.bench_with_input(BenchmarkId::from_parameter(precision), &a, |bencher, ta| {
bencher.iter(|| {
out.clear();
write!(&mut out, "{}", ta).unwrap();
out.len()
})
});
group.bench_with_input(
BenchmarkId::from_parameter(format!("1e{}", log_prec)),
&a,
|bencher, ta| {
bencher.iter(|| {
out.clear();
write!(&mut out, "{}", ta).unwrap();
out.len()
})
},
);
}

group.finish();
Expand All @@ -54,9 +58,11 @@ fn dbig_from_str(criterion: &mut Criterion) {
let precision = 10usize.pow(log_prec);
let a = random_dbig(precision, &mut rng);
let s = a.to_string();
group.bench_with_input(BenchmarkId::from_parameter(precision), &s, |bencher, ts| {
bencher.iter(|| ts.parse::<DBig>())
});
group.bench_with_input(
BenchmarkId::from_parameter(format!("1e{}", log_prec)),
&s,
|bencher, ts| bencher.iter(|| ts.parse::<DBig>()),
);
}

group.finish();
Expand All @@ -71,13 +77,17 @@ fn dbig_scientific_fmt(criterion: &mut Criterion) {
let precision = 10usize.pow(log_prec);
let a = random_dbig(precision, &mut rng);
let mut out = String::new();
group.bench_with_input(BenchmarkId::from_parameter(precision), &a, |bencher, ta| {
bencher.iter(|| {
out.clear();
write!(&mut out, "{:e}", ta).unwrap();
out.len()
})
});
group.bench_with_input(
BenchmarkId::from_parameter(format!("1e{}", log_prec)),
&a,
|bencher, ta| {
bencher.iter(|| {
out.clear();
write!(&mut out, "{:e}", ta).unwrap();
out.len()
})
},
);
}

group.finish();
Expand Down
4 changes: 2 additions & 2 deletions float/benches/primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ macro_rules! add_binop_benchmark {
let a = random_fbig(precision, &mut rng);
let b = random_fbig(precision, &mut rng);
group.bench_with_input(
BenchmarkId::from_parameter(precision),
BenchmarkId::from_parameter(format!("1e{}", log_prec)),
&(a, b),
|bencher, (ta, tb)| bencher.iter(|| ta.$method(tb)),
);
Expand All @@ -70,7 +70,7 @@ macro_rules! add_binop_benchmark {
let a = random_dbig(precision, &mut rng);
let b = random_dbig(precision, &mut rng);
group.bench_with_input(
BenchmarkId::from_parameter(precision),
BenchmarkId::from_parameter(format!("1e{}", log_prec)),
&(a, b),
|bencher, (ta, tb)| bencher.iter(|| ta.$method(tb)),
);
Expand Down
3 changes: 2 additions & 1 deletion integer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
- `UBig::from_u64` and `IBig::from_i64`, const on 32-bit and 64-bit targets.

### Improve
- Addition and subtraction carry/borrow propagation now uses `Word` (u64/u32) instead of `bool` throughout the architecture-specific `add_with_carry` and `sub_with_borrow` functions, eliminating `bool`↔Word conversions in the inner loops. Combined with comparison-based overflow detection on the generic code path, this reduces the per-word instruction count from ~9 to ~7 on ARM64. ~36% faster addition and ~17% faster subtraction at 10000-bit operand sizes, bringing dashu roughly even with malachite at this scale. Added `#[inline]` annotations on the hot loop functions to ensure cross-function optimization.
- Basecase (schoolbook) multiplication now uses an dword mult inner kernel (two multiplier words per sweep over the accumulator, mirroring GMP's `mpn_addmul_2` and `mpn_submul_2`), roughly halving accumulator memory traffic.
- Addition and subtraction carry/borrow propagation now uses `Word` (u64/u32) instead of `bool` throughout the architecture-specific `add_with_carry` and `sub_with_borrow` functions, eliminating `bool`↔Word conversions in the inner loops.

### Improve
- Logarithm for very large values uses power-sequence decomposition, replacing iterative single-step multiplication.
Expand Down
52 changes: 32 additions & 20 deletions integer/benches/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,17 @@ fn ubig_to_hex(criterion: &mut Criterion) {
let bits = 10usize.pow(log_bits);
let a = random_ubig(bits, &mut rng);
let mut out = String::with_capacity(bits / 4 + 1);
group.bench_with_input(BenchmarkId::from_parameter(bits), &a, |bencher, ta| {
bencher.iter(|| {
out.clear();
write!(&mut out, "{:x}", &ta).unwrap();
out.len()
})
});
group.bench_with_input(
BenchmarkId::from_parameter(format!("1e{}", log_bits)),
&a,
|bencher, ta| {
bencher.iter(|| {
out.clear();
write!(&mut out, "{:x}", &ta).unwrap();
out.len()
})
},
);
}

group.finish();
Expand All @@ -47,13 +51,17 @@ fn ubig_to_dec(criterion: &mut Criterion) {
let bits = 10usize.pow(log_bits);
let a = random_ubig(bits, &mut rng);
let mut out = String::with_capacity(bits / 3 + 1);
group.bench_with_input(BenchmarkId::from_parameter(bits), &a, |bencher, ta| {
bencher.iter(|| {
out.clear();
write!(&mut out, "{}", &ta).unwrap();
out.len()
})
});
group.bench_with_input(
BenchmarkId::from_parameter(format!("1e{}", log_bits)),
&a,
|bencher, ta| {
bencher.iter(|| {
out.clear();
write!(&mut out, "{}", &ta).unwrap();
out.len()
})
},
);
}

group.finish();
Expand All @@ -68,9 +76,11 @@ fn ubig_from_hex(criterion: &mut Criterion) {
let bits = 10usize.pow(log_bits);
let a = random_ubig(bits, &mut rng);
let s = a.in_radix(16).to_string();
group.bench_with_input(BenchmarkId::from_parameter(bits), &s, |bencher, ts| {
bencher.iter(|| UBig::from_str_radix(ts, 16))
});
group.bench_with_input(
BenchmarkId::from_parameter(format!("1e{}", log_bits)),
&s,
|bencher, ts| bencher.iter(|| UBig::from_str_radix(ts, 16)),
);
}

group.finish();
Expand All @@ -85,9 +95,11 @@ fn ubig_from_dec(criterion: &mut Criterion) {
let bits = 10usize.pow(log_bits);
let a = random_ubig(bits, &mut rng);
let s = a.in_radix(10).to_string();
group.bench_with_input(BenchmarkId::from_parameter(bits), &s, |bencher, ts| {
bencher.iter(|| UBig::from_str_radix(ts, 10))
});
group.bench_with_input(
BenchmarkId::from_parameter(format!("1e{}", log_bits)),
&s,
|bencher, ts| bencher.iter(|| UBig::from_str_radix(ts, 10)),
);
}

group.finish();
Expand Down
44 changes: 27 additions & 17 deletions integer/benches/primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ macro_rules! add_binop_benchmark {
let a = random_ubig(bits, &mut rng);
let b = random_ubig(bits, &mut rng) + &a; // make b > a so that sub won't underflow
group.bench_with_input(
BenchmarkId::from_parameter(bits),
BenchmarkId::from_parameter(format!("1e{}", log_bits)),
&(a, b),
|bencher, (ta, tb)| bencher.iter(|| tb.$method(ta)),
);
Expand All @@ -48,7 +48,7 @@ macro_rules! add_binop_benchmark {

add_binop_benchmark!(ubig_add, add, 6);
add_binop_benchmark!(ubig_sub, sub, 6);
add_binop_benchmark!(ubig_mul, mul, 6);
add_binop_benchmark!(ubig_mul, mul, 7);
add_binop_benchmark!(ubig_div, div, 6);
add_binop_benchmark!(ubig_gcd, gcd, 6);
add_binop_benchmark!(ubig_gcd_ext, gcd_ext, 5);
Expand All @@ -59,9 +59,11 @@ fn ubig_pow(criterion: &mut Criterion) {

for log_power in 1..=6 {
let p = 10usize.pow(log_power);
group.bench_with_input(BenchmarkId::from_parameter(p), &p, |bencher, p| {
bencher.iter(|| UBig::from(3u8).pow(*p))
});
group.bench_with_input(
BenchmarkId::from_parameter(format!("1e{}", log_power)),
&p,
|bencher, p| bencher.iter(|| UBig::from(3u8).pow(*p)),
);
}

group.finish();
Expand All @@ -78,9 +80,11 @@ fn ubig_modulo_mul(criterion: &mut Criterion) {
let ring = ConstDivisor::new(m);
let a = ring.reduce(random_ubig(bits, &mut rng));
let b = ring.reduce(random_ubig(bits, &mut rng));
group.bench_with_input(BenchmarkId::from_parameter(bits), &(a, b), |bencher, (ta, tb)| {
bencher.iter(|| ta * tb)
});
group.bench_with_input(
BenchmarkId::from_parameter(format!("1e{}", log_bits)),
&(a, b),
|bencher, (ta, tb)| bencher.iter(|| ta * tb),
);
}

group.finish();
Expand All @@ -100,9 +104,11 @@ fn ubig_modulo_pow(criterion: &mut Criterion) {
let ring = ConstDivisor::new(m);
let a = ring.reduce(random_ubig(2048, &mut rng));
let b = random_ubig(bits, &mut rng);
group.bench_with_input(BenchmarkId::from_parameter(bits), &(a, b), |bencher, (ta, tb)| {
bencher.iter(|| ta.pow(tb))
});
group.bench_with_input(
BenchmarkId::from_parameter(format!("1e{}", log_bits)),
&(a, b),
|bencher, (ta, tb)| bencher.iter(|| ta.pow(tb)),
);
}

group.finish();
Expand All @@ -115,9 +121,11 @@ fn ubig_pow_large_base(criterion: &mut Criterion) {
let base = UBig::from(12345u32);
for log_exp in 1..=6usize {
let exp = 10usize.pow(log_exp as u32);
group.bench_with_input(BenchmarkId::from_parameter(exp), &exp, |bencher, exp| {
bencher.iter(|| base.pow(*exp))
});
group.bench_with_input(
BenchmarkId::from_parameter(format!("1e{}", log_exp)),
&exp,
|bencher, exp| bencher.iter(|| base.pow(*exp)),
);
}

group.finish();
Expand All @@ -132,9 +140,11 @@ fn ubig_ilog_large(criterion: &mut Criterion) {
for log_bits in 1..=6usize {
let bits = 10usize.pow(log_bits as u32);
let n = random_ubig(bits, &mut rng);
group.bench_with_input(BenchmarkId::from_parameter(bits), &n, |bencher, tn| {
bencher.iter(|| tn.ilog(&base))
});
group.bench_with_input(
BenchmarkId::from_parameter(format!("1e{}", log_bits)),
&n,
|bencher, tn| bencher.iter(|| tn.ilog(&base)),
);
}

group.finish();
Expand Down
Loading
Loading