multitype 0.21.1

Arithmetic type traits.
Documentation
// Copyright 2025-2026 Gabriel Bjørnager Jensen.
//
// SPDX: MIT OR Apache-2.0

#![cfg(test)]

use multitype::Integral;

#[cfg(feature = "std")]
use std::panic::catch_unwind;

#[test]
fn test_highest_one() {
	assert_eq!(Integral::highest_one(0_u8), None);
	assert_eq!(Integral::highest_one(1_u8), Some(0));
	assert_eq!(Integral::highest_one(2_u8), Some(1));
	assert_eq!(Integral::highest_one(3_u8), Some(1));
	assert_eq!(Integral::highest_one(4_u8), Some(2));
	assert_eq!(Integral::highest_one(5_u8), Some(2));
	assert_eq!(Integral::highest_one(6_u8), Some(2));
	assert_eq!(Integral::highest_one(7_u8), Some(2));

	assert_eq!(Integral::highest_one(-0_i8), None);
	assert_eq!(Integral::highest_one(-1_i8), Some(7));
	assert_eq!(Integral::highest_one(-2_i8), Some(7));
	assert_eq!(Integral::highest_one(-3_i8), Some(7));
	assert_eq!(Integral::highest_one(-4_i8), Some(7));
	assert_eq!(Integral::highest_one(-5_i8), Some(7));
	assert_eq!(Integral::highest_one(-6_i8), Some(7));
	assert_eq!(Integral::highest_one(-7_i8), Some(7));
}

#[test]
fn test_isolate_highest_one() {
	assert_eq!(Integral::isolate_highest_one(0_u8), 0);
	assert_eq!(Integral::isolate_highest_one(1_u8), 1);
	assert_eq!(Integral::isolate_highest_one(2_u8), 2);
	assert_eq!(Integral::isolate_highest_one(3_u8), 2);
	assert_eq!(Integral::isolate_highest_one(4_u8), 4);
	assert_eq!(Integral::isolate_highest_one(5_u8), 4);
	assert_eq!(Integral::isolate_highest_one(6_u8), 4);
	assert_eq!(Integral::isolate_highest_one(7_u8), 4);

	assert_eq!(Integral::isolate_highest_one(-0_i8),    0);
	assert_eq!(Integral::isolate_highest_one(-1_i8), -128);
	assert_eq!(Integral::isolate_highest_one(-2_i8), -128);
	assert_eq!(Integral::isolate_highest_one(-3_i8), -128);
	assert_eq!(Integral::isolate_highest_one(-4_i8), -128);
	assert_eq!(Integral::isolate_highest_one(-5_i8), -128);
	assert_eq!(Integral::isolate_highest_one(-6_i8), -128);
	assert_eq!(Integral::isolate_highest_one(-7_i8), -128);
}

#[test]
fn test_isolate_lowest_one() {
	assert_eq!(Integral::isolate_lowest_one(0_u8), 0);
	assert_eq!(Integral::isolate_lowest_one(1_u8), 1);
	assert_eq!(Integral::isolate_lowest_one(2_u8), 2);
	assert_eq!(Integral::isolate_lowest_one(3_u8), 1);
	assert_eq!(Integral::isolate_lowest_one(4_u8), 4);
	assert_eq!(Integral::isolate_lowest_one(5_u8), 1);
	assert_eq!(Integral::isolate_lowest_one(6_u8), 2);
	assert_eq!(Integral::isolate_lowest_one(7_u8), 1);

	assert_eq!(Integral::isolate_lowest_one(-0_i8), 0);
	assert_eq!(Integral::isolate_lowest_one(-1_i8), 1);
	assert_eq!(Integral::isolate_lowest_one(-2_i8), 2);
	assert_eq!(Integral::isolate_lowest_one(-3_i8), 1);
	assert_eq!(Integral::isolate_lowest_one(-4_i8), 4);
	assert_eq!(Integral::isolate_lowest_one(-5_i8), 1);
	assert_eq!(Integral::isolate_lowest_one(-6_i8), 2);
	assert_eq!(Integral::isolate_lowest_one(-7_i8), 1);
}

#[test]
fn test_lowest_one() {
	assert_eq!(Integral::lowest_one(0_u8), None);
	assert_eq!(Integral::lowest_one(1_u8), Some(0));
	assert_eq!(Integral::lowest_one(2_u8), Some(1));
	assert_eq!(Integral::lowest_one(3_u8), Some(0));
	assert_eq!(Integral::lowest_one(4_u8), Some(2));
	assert_eq!(Integral::lowest_one(5_u8), Some(0));
	assert_eq!(Integral::lowest_one(6_u8), Some(1));
	assert_eq!(Integral::lowest_one(7_u8), Some(0));

	assert_eq!(Integral::lowest_one(-0_i8), None);
	assert_eq!(Integral::lowest_one(-1_i8), Some(0));
	assert_eq!(Integral::lowest_one(-2_i8), Some(1));
	assert_eq!(Integral::lowest_one(-3_i8), Some(0));
	assert_eq!(Integral::lowest_one(-4_i8), Some(2));
	assert_eq!(Integral::lowest_one(-5_i8), Some(0));
	assert_eq!(Integral::lowest_one(-6_i8), Some(1));
	assert_eq!(Integral::lowest_one(-7_i8), Some(0));
}

#[test]
fn test_midpoint() {
	assert_eq!(Integral::midpoint(0_u128,        0_u128),    0_u128);
	assert_eq!(Integral::midpoint(0_u128,        u128::MAX), u128::MAX / 2);
	assert_eq!(Integral::midpoint(u128::MAX,     u128::MAX), u128::MAX);
	assert_eq!(Integral::midpoint(u128::MAX - 2, u128::MAX), u128::MAX - 1);
	assert_eq!(Integral::midpoint(i128::MIN,     i128::MAX), 0);
}

#[cfg(feature = "std")]
#[test]
fn test_strict_add() {
	catch_unwind(|| Integral::strict_add(u8::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_add(u16::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_add(u32::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_add(u64::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_add(u128::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_add(usize::MIN, 1)).unwrap();

	catch_unwind(|| Integral::strict_add(i8::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_add(i16::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_add(i32::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_add(i64::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_add(i128::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_add(isize::MIN, 1)).unwrap();

	catch_unwind(|| Integral::strict_add(u8::MAX, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_add(u16::MAX, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_add(u32::MAX, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_add(u64::MAX, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_add(u128::MAX, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_add(usize::MAX, 1)).unwrap_err();

	catch_unwind(|| Integral::strict_add(i8::MAX, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_add(i16::MAX, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_add(i32::MAX, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_add(i64::MAX, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_add(i128::MAX, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_add(isize::MAX, 1)).unwrap_err();
}

#[cfg(feature = "std")]
#[test]
fn test_strict_div() {
	catch_unwind(|| Integral::strict_div(u8::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_div(u16::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_div(u32::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_div(u64::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_div(u128::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_div(usize::MIN, 1)).unwrap();

	catch_unwind(|| Integral::strict_div(i8::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_div(i16::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_div(i32::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_div(i64::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_div(i128::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_div(isize::MIN, 1)).unwrap();

	catch_unwind(|| Integral::strict_div(u8::MIN, 0)).unwrap_err();
	catch_unwind(|| Integral::strict_div(u16::MIN, 0)).unwrap_err();
	catch_unwind(|| Integral::strict_div(u32::MIN, 0)).unwrap_err();
	catch_unwind(|| Integral::strict_div(u64::MIN, 0)).unwrap_err();
	catch_unwind(|| Integral::strict_div(u128::MIN, 0)).unwrap_err();
	catch_unwind(|| Integral::strict_div(usize::MIN, 0)).unwrap_err();

	catch_unwind(|| Integral::strict_div(i8::MIN, -1)).unwrap_err();
	catch_unwind(|| Integral::strict_div(i16::MIN, -1)).unwrap_err();
	catch_unwind(|| Integral::strict_div(i32::MIN, -1)).unwrap_err();
	catch_unwind(|| Integral::strict_div(i64::MIN, -1)).unwrap_err();
	catch_unwind(|| Integral::strict_div(i128::MIN, -1)).unwrap_err();
	catch_unwind(|| Integral::strict_div(isize::MIN, -1)).unwrap_err();
}

#[cfg(feature = "std")]
#[test]
fn test_strict_mul() {
	catch_unwind(|| Integral::strict_mul(u8::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_mul(u16::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_mul(u32::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_mul(u64::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_mul(u128::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_mul(usize::MAX, 1)).unwrap();

	catch_unwind(|| Integral::strict_mul(i8::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_mul(i16::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_mul(i32::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_mul(i64::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_mul(i128::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_mul(isize::MAX, 1)).unwrap();

	catch_unwind(|| Integral::strict_mul(u8::MAX, 2)).unwrap_err();
	catch_unwind(|| Integral::strict_mul(u16::MAX, 2)).unwrap_err();
	catch_unwind(|| Integral::strict_mul(u32::MAX, 2)).unwrap_err();
	catch_unwind(|| Integral::strict_mul(u64::MAX, 2)).unwrap_err();
	catch_unwind(|| Integral::strict_mul(u128::MAX, 2)).unwrap_err();
	catch_unwind(|| Integral::strict_mul(usize::MAX, 2)).unwrap_err();

	catch_unwind(|| Integral::strict_mul(i8::MAX, 2)).unwrap_err();
	catch_unwind(|| Integral::strict_mul(i16::MAX, 2)).unwrap_err();
	catch_unwind(|| Integral::strict_mul(i32::MAX, 2)).unwrap_err();
	catch_unwind(|| Integral::strict_mul(i64::MAX, 2)).unwrap_err();
	catch_unwind(|| Integral::strict_mul(i128::MAX, 2)).unwrap_err();
	catch_unwind(|| Integral::strict_mul(isize::MAX, 2)).unwrap_err();
}

#[cfg(feature = "std")]
#[test]
fn test_strict_pow() {
	catch_unwind(|| Integral::strict_pow(2_u8, 7)).unwrap();
	catch_unwind(|| Integral::strict_pow(2_u16, 15)).unwrap();
	catch_unwind(|| Integral::strict_pow(2_u32, 31)).unwrap();
	catch_unwind(|| Integral::strict_pow(2_u64, 63)).unwrap();
	catch_unwind(|| Integral::strict_pow(2_u128, 127)).unwrap();
	catch_unwind(|| Integral::strict_pow(2_usize, usize::MAX.ilog2())).unwrap();

	catch_unwind(|| Integral::strict_pow(2_i8, 6)).unwrap();
	catch_unwind(|| Integral::strict_pow(2_i16, 14)).unwrap();
	catch_unwind(|| Integral::strict_pow(2_i32, 30)).unwrap();
	catch_unwind(|| Integral::strict_pow(2_i64, 62)).unwrap();
	catch_unwind(|| Integral::strict_pow(2_i128, 126)).unwrap();
	catch_unwind(|| Integral::strict_pow(2_isize, isize::MAX.ilog2())).unwrap();

	catch_unwind(|| Integral::strict_pow(2_u8, 8)).unwrap_err();
	catch_unwind(|| Integral::strict_pow(2_u16, 16)).unwrap_err();
	catch_unwind(|| Integral::strict_pow(2_u32, 32)).unwrap_err();
	catch_unwind(|| Integral::strict_pow(2_u64, 64)).unwrap_err();
	catch_unwind(|| Integral::strict_pow(2_u128, 128)).unwrap_err();
	catch_unwind(|| Integral::strict_pow(2_usize, usize::MAX.ilog2() + 1)).unwrap_err();

	catch_unwind(|| Integral::strict_pow(2_i8, 7)).unwrap_err();
	catch_unwind(|| Integral::strict_pow(2_i16, 15)).unwrap_err();
	catch_unwind(|| Integral::strict_pow(2_i32, 31)).unwrap_err();
	catch_unwind(|| Integral::strict_pow(2_i64, 63)).unwrap_err();
	catch_unwind(|| Integral::strict_pow(2_i128, 127)).unwrap_err();
	catch_unwind(|| Integral::strict_pow(2_isize, isize::MAX.ilog2() + 1)).unwrap_err();
}

#[cfg(feature = "std")]
#[test]
fn test_strict_rem() {
	catch_unwind(|| Integral::strict_rem(u8::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_rem(u16::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_rem(u32::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_rem(u64::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_rem(u128::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_rem(usize::MIN, 1)).unwrap();

	catch_unwind(|| Integral::strict_rem(i8::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_rem(i16::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_rem(i32::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_rem(i64::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_rem(i128::MIN, 1)).unwrap();
	catch_unwind(|| Integral::strict_rem(isize::MIN, 1)).unwrap();

	catch_unwind(|| Integral::strict_rem(u8::MIN, 0)).unwrap_err();
	catch_unwind(|| Integral::strict_rem(u16::MIN, 0)).unwrap_err();
	catch_unwind(|| Integral::strict_rem(u32::MIN, 0)).unwrap_err();
	catch_unwind(|| Integral::strict_rem(u64::MIN, 0)).unwrap_err();
	catch_unwind(|| Integral::strict_rem(u128::MIN, 0)).unwrap_err();
	catch_unwind(|| Integral::strict_rem(usize::MIN, 0)).unwrap_err();

	catch_unwind(|| Integral::strict_rem(i8::MIN, -1)).unwrap_err();
	catch_unwind(|| Integral::strict_rem(i16::MIN, -1)).unwrap_err();
	catch_unwind(|| Integral::strict_rem(i32::MIN, -1)).unwrap_err();
	catch_unwind(|| Integral::strict_rem(i64::MIN, -1)).unwrap_err();
	catch_unwind(|| Integral::strict_rem(i128::MIN, -1)).unwrap_err();
	catch_unwind(|| Integral::strict_rem(isize::MIN, -1)).unwrap_err();
}

#[cfg(feature = "std")]
#[test]
fn test_strict_sub() {
	catch_unwind(|| Integral::strict_sub(u8::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_sub(u16::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_sub(u32::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_sub(u64::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_sub(u128::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_sub(usize::MAX, 1)).unwrap();

	catch_unwind(|| Integral::strict_sub(i8::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_sub(i16::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_sub(i32::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_sub(i64::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_sub(i128::MAX, 1)).unwrap();
	catch_unwind(|| Integral::strict_sub(isize::MAX, 1)).unwrap();

	catch_unwind(|| Integral::strict_sub(u8::MIN, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_sub(u16::MIN, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_sub(u32::MIN, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_sub(u64::MIN, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_sub(u128::MIN, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_sub(usize::MIN, 1)).unwrap_err();

	catch_unwind(|| Integral::strict_sub(i8::MIN, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_sub(i16::MIN, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_sub(i32::MIN, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_sub(i64::MIN, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_sub(i128::MIN, 1)).unwrap_err();
	catch_unwind(|| Integral::strict_sub(isize::MIN, 1)).unwrap_err();
}

#[test]
fn test_unbounded_shl() {
	assert_eq!(Integral::unbounded_shl(1_u128,   0),                           1);
	assert_eq!(Integral::unbounded_shl(1_u128,   1),                           2);
	assert_eq!(Integral::unbounded_shl(1_u128,   2),                           4);
	assert_eq!(Integral::unbounded_shl(1_u128,   4),                          16);
	assert_eq!(Integral::unbounded_shl(1_u128,   8),                         256);
	assert_eq!(Integral::unbounded_shl(1_u128,  16),                      65_536);
	assert_eq!(Integral::unbounded_shl(1_u128,  32),               4_294_967_296);
	assert_eq!(Integral::unbounded_shl(1_u128,  64),  18_446_744_073_709_551_616);
	assert_eq!(Integral::unbounded_shl(1_u128, 128),                           0);
}

#[test]
fn test_unbounded_shr() {
	assert_eq!(Integral::unbounded_shr(u128::MAX,   0), 340_282_366_920_938_463_463_374_607_431_768_211_455);
	assert_eq!(Integral::unbounded_shr(u128::MAX,   1), 170_141_183_460_469_231_731_687_303_715_884_105_727);
	assert_eq!(Integral::unbounded_shr(u128::MAX,   2),  85_070_591_730_234_615_865_843_651_857_942_052_863);
	assert_eq!(Integral::unbounded_shr(u128::MAX,   4),  21_267_647_932_558_653_966_460_912_964_485_513_215);
	assert_eq!(Integral::unbounded_shr(u128::MAX,   8),   1_329_227_995_784_915_872_903_807_060_280_344_575);
	assert_eq!(Integral::unbounded_shr(u128::MAX,  16),       5_192_296_858_534_827_628_530_496_329_220_095);
	assert_eq!(Integral::unbounded_shr(u128::MAX,  32),              79_228_162_514_264_337_593_543_950_335);
	assert_eq!(Integral::unbounded_shr(u128::MAX,  64),                          18_446_744_073_709_551_615);
	assert_eq!(Integral::unbounded_shr(u128::MAX, 128),                                                   0);

	assert_eq!(Integral::unbounded_shr(i128::MAX,   0), 170_141_183_460_469_231_731_687_303_715_884_105_727);
	assert_eq!(Integral::unbounded_shr(i128::MAX,   1),  85_070_591_730_234_615_865_843_651_857_942_052_863);
	assert_eq!(Integral::unbounded_shr(i128::MAX,   2),  42_535_295_865_117_307_932_921_825_928_971_026_431);
	assert_eq!(Integral::unbounded_shr(i128::MAX,   4),  10_633_823_966_279_326_983_230_456_482_242_756_607);
	assert_eq!(Integral::unbounded_shr(i128::MAX,   8),     664_613_997_892_457_936_451_903_530_140_172_287);
	assert_eq!(Integral::unbounded_shr(i128::MAX,  16),       2_596_148_429_267_413_814_265_248_164_610_047);
	assert_eq!(Integral::unbounded_shr(i128::MAX,  32),              39_614_081_257_132_168_796_771_975_167);
	assert_eq!(Integral::unbounded_shr(i128::MAX,  64),                           9_223_372_036_854_775_807);
	assert_eq!(Integral::unbounded_shr(i128::MAX, 128),                                                   0);
}