# Path: qkeras/qtools/quantized_operators/divider_impl.py
# class IDividerImpl(abc.ABC):
# class FloatingPointDivider(IDividerImpl):
# class Shifter(IDividerImpl):
# class Subtractor(IDividerImpl):
#   def __init__(self, numerator_quantizer, denominator_quantizer,
#                output_quantizer):
#   def implemented_as():
#   def __init__(self, numerator_quantizer, denominator_quantizer,
#                output_quantizer):
#   def implemented_as():
#   def __init__(self, numerator_quantizer, denominator_quantizer,
#                output_quantizer):
#   def implemented_as():
#   def __init__(self, numerator_quantizer, denominator_quantizer,
#                output_quantizer):
#   def implemented_as():
# 
# Path: qkeras/qtools/quantized_operators/quantizer_impl.py
# FLOATINGPOINT_BITS = 32
# def get_np_value(val):
# def get_exp(quantizer):
#   def __init__(self):
#   def __init__(self):
#   def convert_qkeras_quantizer(
#       self, quantizer: quantizers.quantized_bits):
#   def convert_to_qkeras_quantizer(
#       self, symmetric=1, alpha=None, use_stochastic_rounding=False,
#       scale_axis=None, qnoise_factor=1.0):
#   def __init__(self):
#   def convert_qkeras_quantizer(
#       self, quantizer: quantizers.quantized_tanh):
#   def convert_to_qkeras_quantizer(
#       self, symmetric=False, use_stochastic_rounding=False):
#   def __init__(self):
#   def convert_qkeras_quantizer(
#       self, quantizer: quantizers.quantized_ulaw):
#   def convert_to_qkeras_quantizer(self, symmetric=0, u=255.0):
#   def __init__(self, use_01=False):
#   def convert_qkeras_quantizer(self, quantizer: quantizers.binary):
#   def convert_to_qkeras_quantizer(self, alpha=None,
#                                   use_stochastic_rounding=False):
#   def __init__(self):
#   def convert_qkeras_quantizer(
#       self, quantizer: quantizers.stochastic_binary):
#   def convert_to_qkeras_quantizer(self, alpha=None, temperature=6.0,
#                                   use_real_sigmoid=True):
#   def __init__(self):
#   def convert_qkeras_quantizer(self, quantizer: quantizers.bernoulli):
#   def convert_to_qkeras_quantizer(self, alpha=None, temperature=6.0,
#                                   use_real_sigmoid=True):
#   def __init__(self):
#   def convert_qkeras_quantizer(
#       self, quantizer: quantizers.quantized_relu):
#   def convert_to_qkeras_quantizer(
#       self, use_sigmoid=0, negative_slope=0.0, use_stochastic_rounding=False,
#       relu_upper_bound=None, is_quantized_clip=True, qnoise_factor=1.0):
#   def __init__(self):
#   def convert_qkeras_quantizer(
#       self, quantizer: quantizers.ternary):
#   def convert_to_qkeras_quantizer(
#       self, alpha=None, threshold=None, use_stochastic_rounding=False,
#       number_of_unrolls=5):
#   def __init__(self):
#   def convert_qkeras_quantizer(
#       self, quantizer: quantizers.stochastic_ternary):
#   def convert_to_qkeras_quantizer(
#       self, alpha=None, threshold=None, temperature=8.0,
#       use_real_sigmoid=True, number_of_unrolls=5):
#   def __init__(self, bits):
#   def convert_qkeras_quantizer(self, bits):
#   def convert_to_qkeras_quantizer(self, bits):
#   def __init__(self, is_signed=True):
#   def convert_qkeras_quantizer(self, quantizer):
#   def convert_to_qkeras_quantizer(
#       self, negative_slope=0, use_stochastic_rounding=False,
#       quadratic_approximation=False):
#   def get_min_max_exp(self):
#   def quantizer_bits_calculator(self, val):
#   def update_quantizer(self, val, reset=False):
#   def update_inference_values(self, weights):
#   def __init__(self):
#   def convert_qkeras_quantizer(
#       self, quantizer: quantizers.quantized_relu_po2):
#   def convert_to_qkeras_quantizer(
#       self, negative_slope=0, use_stochastic_rounding=False,
#       quadratic_approximation=False):
# class IQuantizer(abc.ABC):
# class QuantizedBits(IQuantizer):
# class QuantizedTanh(QuantizedBits):
# class QuantizedUlaw(QuantizedBits):
# class Binary(IQuantizer):
# class StochasticBinary(Binary):
# class Bernoulli(Binary):
# class QuantizedRelu(IQuantizer):
# class Ternary(IQuantizer):
# class StochasticTernary(Ternary):
# class FloatingPoint(IQuantizer):
# class PowerOfTwo(IQuantizer):
# class ReluPowerOfTwo(PowerOfTwo):


import abc
import copy
from absl import logging
from qkeras.qtools.quantized_operators import divider_impl
from qkeras.qtools.quantized_operators import quantizer_impl
class UnacceptedQuantizerError(ValueError):
  pass


class IDivider(abc.ABC):
  """abstract class for divider."""

  def __init__(self):
    # also attached the output datatype in the table
    self.divider_impl_table = [
        [
            # when qbits is denominator, use default bits for float result
            (divider_impl.FloatingPointDivider, quantizer_impl.FloatingPoint(
                bits=quantizer_impl.FLOATINGPOINT_BITS)),
            (divider_impl.Shifter, quantizer_impl.QuantizedBits()),
            (None, None),
            (None, None),
            (None, None),
            # when bits sets to None, will decide f16/f32 according
            # to input quantizer
            (divider_impl.FloatingPointDivider, quantizer_impl.FloatingPoint(
                bits=None))
        ],
        [
            (divider_impl.FloatingPointDivider, quantizer_impl.FloatingPoint(
                bits=quantizer_impl.FLOATINGPOINT_BITS)),
            (divider_impl.Subtractor, quantizer_impl.PowerOfTwo()),
            (None, None),
            (None, None),
            (None, None),

# Path: qkeras/qtools/quantized_operators/divider_impl.py
# class IDividerImpl(abc.ABC):
# class FloatingPointDivider(IDividerImpl):
# class Shifter(IDividerImpl):
# class Subtractor(IDividerImpl):
#   def __init__(self, numerator_quantizer, denominator_quantizer,
#                output_quantizer):
#   def implemented_as():
#   def __init__(self, numerator_quantizer, denominator_quantizer,
#                output_quantizer):
#   def implemented_as():
#   def __init__(self, numerator_quantizer, denominator_quantizer,
#                output_quantizer):
#   def implemented_as():
#   def __init__(self, numerator_quantizer, denominator_quantizer,
#                output_quantizer):
#   def implemented_as():
# 
# Path: qkeras/qtools/quantized_operators/quantizer_impl.py
# FLOATINGPOINT_BITS = 32
# def get_np_value(val):
# def get_exp(quantizer):
#   def __init__(self):
#   def __init__(self):
#   def convert_qkeras_quantizer(
#       self, quantizer: quantizers.quantized_bits):
#   def convert_to_qkeras_quantizer(
#       self, symmetric=1, alpha=None, use_stochastic_rounding=False,
#       scale_axis=None, qnoise_factor=1.0):
#   def __init__(self):
#   def convert_qkeras_quantizer(
#       self, quantizer: quantizers.quantized_tanh):
#   def convert_to_qkeras_quantizer(
#       self, symmetric=False, use_stochastic_rounding=False):
#   def __init__(self):
#   def convert_qkeras_quantizer(
#       self, quantizer: quantizers.quantized_ulaw):
#   def convert_to_qkeras_quantizer(self, symmetric=0, u=255.0):
#   def __init__(self, use_01=False):
#   def convert_qkeras_quantizer(self, quantizer: quantizers.binary):
#   def convert_to_qkeras_quantizer(self, alpha=None,
#                                   use_stochastic_rounding=False):
#   def __init__(self):
#   def convert_qkeras_quantizer(
#       self, quantizer: quantizers.stochastic_binary):
#   def convert_to_qkeras_quantizer(self, alpha=None, temperature=6.0,
#                                   use_real_sigmoid=True):
#   def __init__(self):
#   def convert_qkeras_quantizer(self, quantizer: quantizers.bernoulli):
#   def convert_to_qkeras_quantizer(self, alpha=None, temperature=6.0,
#                                   use_real_sigmoid=True):
#   def __init__(self):
#   def convert_qkeras_quantizer(
#       self, quantizer: quantizers.quantized_relu):
#   def convert_to_qkeras_quantizer(
#       self, use_sigmoid=0, negative_slope=0.0, use_stochastic_rounding=False,
#       relu_upper_bound=None, is_quantized_clip=True, qnoise_factor=1.0):
#   def __init__(self):
#   def convert_qkeras_quantizer(
#       self, quantizer: quantizers.ternary):
#   def convert_to_qkeras_quantizer(
#       self, alpha=None, threshold=None, use_stochastic_rounding=False,
#       number_of_unrolls=5):
#   def __init__(self):
#   def convert_qkeras_quantizer(
#       self, quantizer: quantizers.stochastic_ternary):
#   def convert_to_qkeras_quantizer(
#       self, alpha=None, threshold=None, temperature=8.0,
#       use_real_sigmoid=True, number_of_unrolls=5):
#   def __init__(self, bits):
#   def convert_qkeras_quantizer(self, bits):
#   def convert_to_qkeras_quantizer(self, bits):
#   def __init__(self, is_signed=True):
#   def convert_qkeras_quantizer(self, quantizer):
#   def convert_to_qkeras_quantizer(
#       self, negative_slope=0, use_stochastic_rounding=False,
#       quadratic_approximation=False):
#   def get_min_max_exp(self):
#   def quantizer_bits_calculator(self, val):
#   def update_quantizer(self, val, reset=False):
#   def update_inference_values(self, weights):
#   def __init__(self):
#   def convert_qkeras_quantizer(
#       self, quantizer: quantizers.quantized_relu_po2):
#   def convert_to_qkeras_quantizer(
#       self, negative_slope=0, use_stochastic_rounding=False,
#       quadratic_approximation=False):
# class IQuantizer(abc.ABC):
# class QuantizedBits(IQuantizer):
# class QuantizedTanh(QuantizedBits):
# class QuantizedUlaw(QuantizedBits):
# class Binary(IQuantizer):
# class StochasticBinary(Binary):
# class Bernoulli(Binary):
# class QuantizedRelu(IQuantizer):
# class Ternary(IQuantizer):
# class StochasticTernary(Ternary):
# class FloatingPoint(IQuantizer):
# class PowerOfTwo(IQuantizer):
# class ReluPowerOfTwo(PowerOfTwo):


# Path: qkeras/qtools/quantized_operators/divider_factory.py
import abc
import copy
from absl import logging
from qkeras.qtools.quantized_operators import divider_impl
from qkeras.qtools.quantized_operators import quantizer_impl

class UnacceptedQuantizerError(ValueError):
  pass


class IDivider(abc.ABC):
  """abstract class for divider."""

  def __init__(self):
    # also attached the output datatype in the table
    self.divider_impl_table = [
        [
            # when qbits is denominator, use default bits for float result
            (divider_impl.FloatingPointDivider, quantizer_impl.FloatingPoint(
                bits=quantizer_impl.FLOATINGPOINT_BITS)),
            (divider_impl.Shifter, quantizer_impl.QuantizedBits()),
            (None, None),
            (None, None),
            (None, None),
            # when bits sets to None, will decide f16/f32 according
            # to input quantizer
            (divider_impl.FloatingPointDivider, quantizer_impl.FloatingPoint(
                bits=None))
        ],
        [
            (divider_impl.FloatingPointDivider, quantizer_impl.FloatingPoint(
                bits=quantizer_impl.FLOATINGPOINT_BITS)),
            (divider_impl.Subtractor, quantizer_impl.PowerOfTwo()),
            (None, None),
            (None, None),
            (None, None),

            (divider_impl.FloatingPointDivider, quantizer_impl.FloatingPoint(