round_mult

Crates.ioround_mult
lib.rsround_mult
version0.1.4
created_at2022-08-12 11:32:27.720972+00
updated_at2025-03-25 17:02:04.995229+00
descriptionA tiny library to round a number up or down to a multiplier.
homepagehttps://github.com/yehuthi/round_mult
repositoryhttps://github.com/yehuthi/round_mult
max_upload_size
id643957
size41,358
Yehuthi (yehuthi)

documentation

README

round_mult

A tiny library to round a number up or down to a multiplier.

Usage

The library has two functions:

  • round_mult::[up] (see note below)
  • round_mult::[down]

They both take a value and a multiplier and round the value down or up to the multiplier respectively.

[!NOTE] As of Rust 1.73.0, integer primitives have a built-in next_multiple_of method.

Multiplier

There are two kind of multipliers:

  • [NonZeroPow2] When the multiplier is a power of two, it can be calculated faster. Prefer it when possible.
  • std::num::NonZeroU_ for any multiplier value.

Example

E.g.

use std::num::NonZeroUsize;
use round_mult::NonZeroPow2;

assert_eq!(
	round_mult::down(70usize, NonZeroPow2::v32()),
	64
);

// These two are semantically equivalent:
assert_eq!(
	round_mult::down(70usize, NonZeroPow2::new(32).unwrap()),
	round_mult::down(70usize, NonZeroUsize::new(32).unwrap()),
);
// but NonZeroPow2 (the first parameter) is faster.

// However, it can't be used when the multiplier isn't a power of two.
// In that case use a NonZeroU_ type:
assert_eq!(
    round_mult::down(109usize, NonZeroUsize::new(10).unwrap()),
    100
);
assert_eq!(
    round_mult::up(101usize, NonZeroUsize::new(10).unwrap()),
    Some(110)
);

Example: SIMD

The main motivation for this library is SIMD processing. Specifically when the length of data isn't a multiple of the SIMD lanes count, which means you will have a remainder of data to process without SIMD.

use round_mult::NonZeroPow2;

fn f(data: &[u8]) {
	// for this example, assume we want to use u8x32 SIMD. We could do:
	// type Simd = std::simd::u8x32;
	// let lanes = NonZeroPow2::of::<Simd>();
	// but to keep this example compiling on stable, we could also use:
	let lanes = NonZeroPow2::v32();

	let mut i = 0;

	while i < round_mult::down(data.len(), lanes) {
		// SIMD process…
		// let data = Simd::from_slice(s[i..]);
		// etc. etc.
		i += lanes.get();
	}
	while i < data.len() {
		// remainder process…
		i += 1;
	}
}
Commit count: 71

cargo fmt