def try_to_divide(
        self,
        dequantize_x: Operation,
        dequantize_y: Operation,
        quantize_z: Operation,
    ) -> Tuple[np.ndarray, np.ndarray]:
        """
        compute s_x/s_y and s_z/s_y, return the results if succeeds, else None

        The broadcast rule is very complicated:
        1. Broadcast s_x to x, s_y to y, s_z to z, according to axes
        2. Broadcast s_x and s_y
        3. Perform s_x/s_y and s_z/s_y
        4. De-broadcast s_x/s_y and s_z/s_y down to vectors according to axes,
           raise exception if impossible to de-broadcast

        As a result, for now we only handle the scalar s_y case
        """

        # TODO (rdar://109170887): explore vector s_y
        if dequantize_y.axis is not None:
            return None, None

        s_x_fp32 = np.float32(dequantize_x.scale.val)
        s_y_fp32 = np.float32(dequantize_y.scale.val)
        s_z_fp32 = np.float32(quantize_z.scale.val)

        s_x_d_s_y = s_x_fp32 / s_y_fp32
        s_z_d_s_y = s_z_fp32 / s_y_fp32

        if (
            self.overflow_fp16(s_x_d_s_y)
            or self.underflow_fp16(s_x_d_s_y)
            or self.overflow_fp16(s_z_d_s_y)
            or self.underflow_fp16(s_z_d_s_y)
        ):
            return None, None

        return s_x_d_s_y, s_z_d_s_y

        compute s_x/s_y and s_z/s_y, return the results if succeeds, else None

        The broadcast rule is very complicated:
        1. Broadcast s_x to x, s_y to y, s_z to z, according to axes
        2. Broadcast s_x and s_y
        3. Perform s_x/s_y and s_z/s_y
        4. De-broadcast s_x/s_y and s_z/s_y down to vectors according to axes,
           raise exception if impossible to de-broadcast

        As a result, for now we only handle the scalar s_y case
        
coremltools/converters/mil/mil/passes/defs/optimize_quantization.py