use std::num::{NonZeroU8, NonZeroUsize};
use num_traits::clamp;
use crate::util::{Pixel, round_ties_to_even};
use semisafe::option::unwrap as semisafe_opt_unwrap;
use semisafe::slice::get as semisafe_get;
use semisafe::slice::get_mut as semisafe_get_mut;
pub(super) fn float_src_to_pixels<T: Pixel>(
dst: &mut [T],
dst_pitch: NonZeroUsize,
src_dct: &[f32],
size_x: NonZeroUsize,
size_y: NonZeroUsize,
bits_per_sample: NonZeroU8,
dct_shift: usize,
dct_shift0: usize,
) {
let sqrt_2_div_2: f32 = (2f32).sqrt() / 2.0;
let pixel_max = (1 << bits_per_sample.get() as usize) - 1;
let pixel_half = 1 << (bits_per_sample.get() as usize - 1);
for j in 0..size_y.get() {
let real_data = semisafe_get(semisafe_get(src_dct, j * size_x.get()..), ..size_x.get());
let dst = semisafe_get_mut(semisafe_get_mut(dst, j * dst_pitch.get()..), ..size_x.get());
for (f, p) in real_data.iter().zip(dst.iter_mut()) {
let f = *f * sqrt_2_div_2;
let integ = round_ties_to_even(f) as i32;
*p = semisafe_opt_unwrap(T::from(clamp(
(integ >> dct_shift) + pixel_half,
0,
pixel_max,
)));
}
}
let f = *semisafe_get(src_dct, 0) * 0.5;
let integ = round_ties_to_even(f) as i32;
*semisafe_get_mut(dst, 0) = semisafe_opt_unwrap(T::from(clamp(
(integ >> dct_shift0) + pixel_half,
0,
pixel_max,
)));
}