//! Left-shifts the dividend by the divisor's normalization amount into a 9-limb buffer.
use super::KnuthD;

impl KnuthD {
    /// Left-shifts the 8-limb little-endian dividend by `self.s` bits,
    /// writing into the 9-element `un` buffer (extra element for overflow).
    ///
    /// Applies the same normalization shift that was used on the divisor
    /// during [`new`](Self::new), so that the quotient estimation in
    /// [`knuth_loop`](Self::knuth_loop) operates on consistently shifted
    /// values.
    pub(super) fn normalize_dividend(&self, u_le: &[u64; 8], un: &mut [u64; 9]) {
        if self.s > 0 {
            un[0] = u_le[0] << self.s;
            for i in 1..8 {
                un[i] = (u_le[i] << self.s) | (u_le[i - 1] >> (64 - self.s));
            }
            un[8] = u_le[7] >> (64 - self.s);
        } else {
            un[..8].copy_from_slice(u_le);
        }
    }
}

#[cfg(test)]
mod ai_tests {
    use super::*;

    /// Zero shift copies the input unchanged.
    #[test]
    fn zero_shift() {
        let kd = KnuthD::new(&[0, 1u64 << 63, 0, 0], 2);
        assert_eq!(kd.s, 0);
        let u_le = [1, 2, 3, 4, 5, 6, 7, 8];
        let mut un = [0u64; 9];
        kd.normalize_dividend(&u_le, &mut un);
        assert_eq!(&un[..8], &u_le);
        assert_eq!(un[8], 0);
    }

    /// Non-zero shift produces a left-shifted result with overflow in un[8].
    #[test]
    fn nonzero_shift() {
        let kd = KnuthD::new(&[1, 1, 0, 0], 2);
        assert!(kd.s > 0);
        let u_le = [0, 0, 0, 0, 0, 0, 0, 1];
        let mut un = [0u64; 9];
        kd.normalize_dividend(&u_le, &mut un);
        // un[7] should have 1 shifted left by s bits
        assert_eq!(un[7], 1u64 << kd.s);
        // un[8] should be 0 since shifting 1 left doesn't overflow for s < 64
        assert_eq!(un[8], 0);
    }

    /// Normalizing all-zero dividend stays all zero.
    #[test]
    fn zero_dividend() {
        let kd = KnuthD::new(&[1, 1, 0, 0], 2);
        let u_le = [0u64; 8];
        let mut un = [0u64; 9];
        kd.normalize_dividend(&u_le, &mut un);
        assert_eq!(un, [0u64; 9]);
    }
}
