# 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 numpy as np
from qkeras.qtools.quantized_operators import quantizer_impl
      # multiplier factor for gate counts
      if input_quantizer.name == "binary":
        self.gate_factor = 0.3
      else:
        self.gate_factor = 2 * 0.3
      self.gate_bits = weight_quantizer.bits

    if "po2" in output_quantizer.name:
      if self.output.is_signed:
        output_quantizer.name = "quantized_po2"
      else:
        output_quantizer.name = "quantized_relu_po2"

      if "po2" in weight_quantizer.name:
        self.output.max_val_po2 = weight_quantizer.max_val_po2
      else:
        self.output.max_val_po2 = input_quantizer.max_val_po2

      self.output.int_bits = self.output.bits

  @staticmethod
  def implemented_as():
    return "mux"


class XorGate(IMultiplier):
  """Use XorGate for hardware implementation of a multiplier."""

  def __init__(self, weight_quantizer: quantizer_impl.IQuantizer,
               input_quantizer: quantizer_impl.IQuantizer,

# 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/multiplier_impl.py
import abc
import numpy as np
from qkeras.qtools.quantized_operators import quantizer_impl

      # multiplier factor for gate counts
      if input_quantizer.name == "binary":
        self.gate_factor = 0.3
      else:
        self.gate_factor = 2 * 0.3
      self.gate_bits = weight_quantizer.bits

    if "po2" in output_quantizer.name:
      if self.output.is_signed:
        output_quantizer.name = "quantized_po2"
      else:
        output_quantizer.name = "quantized_relu_po2"

      if "po2" in weight_quantizer.name:
        self.output.max_val_po2 = weight_quantizer.max_val_po2
      else:
        self.output.max_val_po2 = input_quantizer.max_val_po2

      self.output.int_bits = self.output.bits

  @staticmethod
  def implemented_as():
    return "mux"


class XorGate(IMultiplier):
  """Use XorGate for hardware implementation of a multiplier."""

  def __init__(self, weight_quantizer: quantizer_impl.IQuantizer,
               input_quantizer: quantizer_impl.IQuantizer,

               output_quantizer: quantizer_impl.IQuantizer):