//! §3.0, §3.9, §2.9: `div255`, `R_rat`, `R_half_up` and the straight-alpha channel, //! against their definitions as exact rationals. use wai_vector::arith::*; /// `⌊n/d⌋` of the exact rational, in `i128`. fn floor_q(n: i128, d: i128) -> i128 { n.div_euclid(d) } #[test] fn div255_over_every_input() { for x in 0..=65_025u32 { let want = floor_q(2 * i128::from(x) + 255, 510); assert_eq!(i128::from(div255(x)), want, "div255({x}) is the half-up rounding of x/255"); // The rq form: pre-bias 128, multiplier 257, shift 16, floor. assert_eq!(div255(x), ((x + 128) * 257) >> 16, "rq form at {x}"); } assert_eq!(div255(65_025), 255); for c in 0..=255u32 { assert_eq!(div255(255 * c), c, "div255(255c) = c"); } } #[test] fn r_rat_is_half_up_of_the_exact_rational() { for d in 1i64..=300 { for n in -3_000i64..=3_000 { let want = floor_q(2 * i128::from(n) + i128::from(d), 2 * i128::from(d)); assert_eq!(i128::from(r_rat(n, d)), want, "R_rat({n}, {d})"); } } let big = (1i64 << 58) - 1; for d in [1i64, 2, 3, 1 << 20, (1 << 28) - 1, 1 << 28] { for n in [big, -big, big - 7, -big + 7, 0, d / 2, -(d / 2), (d + 1) / 2, -(d + 1) / 2] { let want = floor_q(2 * i128::from(n) + i128::from(d), 2 * i128::from(d)); assert_eq!(i128::from(r_rat(n, d)), want, "R_rat({n}, {d})"); } } } #[test] fn r_half_up_is_the_rounded_shift() { for s in 0u32..=20 { for p in (-(1i64 << 21)..=(1 << 21)).step_by(13) { let want = if s == 0 { i128::from(p) } else { floor_q(i128::from(p) + (1i128 << (s - 1)), 1i128 << s) }; assert_eq!(i128::from(r_half_up(p, s)), want, "R_half_up({p}, {s})"); } } for p in [-(1i64 << 47), (1i64 << 47) - 1, -32_768, 32_768, -1, 1] { assert_eq!(i128::from(r_half_up(p, 16)), floor_q(i128::from(p) + (1 << 15), 1 << 16)); } } #[test] fn straight_alpha_is_r_rat_over_every_c_le_a() { for a in 1..=255u8 { for c in 0..=a { let v = unpremul(c, a); assert_eq!(i64::from(v), r_rat(255 * i64::from(c), i64::from(a)), "({c}, {a})"); assert_eq!(u32::from(v), (255 * u32::from(c) + u32::from(a) / 2) / u32::from(a)); } } assert_eq!(unpremul(0, 0), 0); } #[test] fn quantisers_are_even_and_bounded() { for v in -(1i32 << 19)..=(1 << 19) { let (nz, eo) = (alpha_nonzero(v), alpha_evenodd(v)); assert_eq!(nz, alpha_nonzero(-v)); assert_eq!(eo, alpha_evenodd(-v)); } assert_eq!(alpha_nonzero(1 << 17), 255); assert_eq!(alpha_nonzero(1 << 16), 128); assert_eq!(alpha_evenodd(1 << 17), 255); assert_eq!(alpha_evenodd(1 << 18), 0); assert_eq!(alpha_nonzero(i32::MIN), 255); }