You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: quantile.rs
    path of file: ./repos/polars/crates/polars-arrow/src/legacy/kernels/rolling/nulls
    
    the code of the file until where you have to start completion: use polars_utils::slice::GetSaferUnchecked;

use super::*;
use crate::array::MutablePrimitiveArray;

pub struct QuantileWindow<'a, T: NativeType + IsFloat + PartialOrd> {
    sorted: SortedBufNulls<'a, T>,
    prob: f64,
    interpol: QuantileInterpolOptions,
}

impl<
        'a,
        T: NativeType
            + IsFloat
            + Float
            + std::iter::Sum
            + AddAssign
            + SubAssign
 
    
    unsafe fn update(&mut self, start: usize, end: usize) -> Option<T> {
        let (values, null_count) = self.sorted.update(start, end);
        // The min periods_issue will be taken care of when actually rolling
        if null_count == values.len() {
            return None;
        }
        // Nulls are guaranteed to be at the front
        let values = &values[null_count..];
        let length = values.len();

        let mut idx = match self.interpol {
            QuantileInterpolOptions::Nearest => ((length as f64) * self.prob) as usize,
            QuantileInterpolOptions::Lower
            | QuantileInterpolOptions::Midpoint
            | QuantileInterpolOptions::Linear => {
                ((length as f64 - 1.0) * self.prob).floor() as usize
            },
            QuantileInterpolOptions::Higher => ((length as f64 - 1.0) * self.prob).ceil() as usize,
        };

        idx = std::cmp::min(idx, length - 1);

        // we can unwrap because we sliced of the nulls
        match self.interpol {
            QuantileInterpolOptions::Midpoint => {
                let top_idx = ((length as f64 - 1.0) * self.prob).ceil() as usize;
                Some(
                    (values.get_unchecked_release(idx).unwrap()
                        + values.get_unchecked_release(top_idx).unwrap())
                        / T::from::<f64>(2.0f64).unwrap(),
                )
            },
            QuantileInterpolOptions::Linear => {
                let float_idx = (length as f64 - 1.0) * self.prob;
                let top_idx = f64::ceil(float_idx) as usize;

                if top_idx == idx {
                    Some(values.get_unchecked_release(idx).unwrap())
                } else {
                    let proportion = T::from(float_idx - idx as f64).unwrap();
                    Some(
                        proportion
                            * (values.get_unchecked_release(top_idx).unwrap()
                                - values.get_unchecked_release(idx).unwrap())
                            + values.get_unchecked_release(idx).unwrap(),
                    )
                }
            },
            _ => Some(values.get_unchecked_release(idx).unwrap()),
        }
    }