# Path: qkeras/safe_eval.py
# def safe_eval(eval_str, op_dict, *params, **kwparams):  # pylint: disable=invalid-name
#   """Replaces eval by a safe eval mechanism."""
# 
#   function_split = eval_str.split("(")
#   quantizer = op_dict.get(function_split[0], None)
# 
#   if len(function_split) == 2:
#     args, kwargs = GetParams("(" + function_split[1])
#   else:
#     args = []
#     kwargs = {}
# 
#   args = args + list(params)
#   for k in kwparams:
#     kwargs[k] = kwparams[k]
# 
#   # must be Keras activation object if None
#   if quantizer is None:
#     logging.info("keras dict %s", function_split[0])
#     quantizer = keras.activations.get(function_split[0])
# 
#   if len(function_split) == 2 or args or kwargs:
#     return quantizer(*args, **kwargs)
#   else:
#     if isinstance(quantizer, type):
#       # Check if quantizer is a class
#       return quantizer()
#     else:
#       # Otherwise it is a function, so just return it
#       return quantizer


import six
import re
import numpy as np
import tensorflow.compat.v2 as tf
import tensorflow.keras.backend as K
from six.moves import range
from tensorflow.keras import initializers
from tensorflow.keras.utils import deserialize_keras_object
from tensorflow.python.framework import smart_cond as tf_utils
from .safe_eval import safe_eval
    ordered by their binary representation ascending."""
    assert self.symmetric == 0
    assert self.keep_negative
    assert self.alpha is None or self.alpha == 1.0

    x = np.asarray(range(2**self.bits), dtype=np.float32)
    p_and_n = np.where(x >= 2**(self.bits - 1),
                       (x - 2**(self.bits - 1)) - 2**(self.bits - 1), x)
    return p_and_n * np.array(
        K.pow(2.0, -self.bits + K.cast(self.integer, dtype="float32") + 1),
        dtype="float32")

  @classmethod
  def from_config(cls, config):
    return cls(**config)

  def get_config(self):
    config = {
        "bits":
            self.bits,
        "integer":
            self.integer.numpy()
            if isinstance(self.integer, tf.Variable) else self.integer,
        "symmetric":
            self.symmetric,
        "alpha":
            self.alpha,
        "keep_negative":
            self.keep_negative,
        "use_stochastic_rounding":

# Path: qkeras/safe_eval.py
# def safe_eval(eval_str, op_dict, *params, **kwparams):  # pylint: disable=invalid-name
#   """Replaces eval by a safe eval mechanism."""
# 
#   function_split = eval_str.split("(")
#   quantizer = op_dict.get(function_split[0], None)
# 
#   if len(function_split) == 2:
#     args, kwargs = GetParams("(" + function_split[1])
#   else:
#     args = []
#     kwargs = {}
# 
#   args = args + list(params)
#   for k in kwparams:
#     kwargs[k] = kwparams[k]
# 
#   # must be Keras activation object if None
#   if quantizer is None:
#     logging.info("keras dict %s", function_split[0])
#     quantizer = keras.activations.get(function_split[0])
# 
#   if len(function_split) == 2 or args or kwargs:
#     return quantizer(*args, **kwargs)
#   else:
#     if isinstance(quantizer, type):
#       # Check if quantizer is a class
#       return quantizer()
#     else:
#       # Otherwise it is a function, so just return it
#       return quantizer


# Path: qkeras/quantizers.py
import six
import re
import numpy as np
import tensorflow.compat.v2 as tf
import tensorflow.keras.backend as K
from six.moves import range
from tensorflow.keras import initializers
from tensorflow.keras.utils import deserialize_keras_object
from tensorflow.python.framework import smart_cond as tf_utils
from .safe_eval import safe_eval

    ordered by their binary representation ascending."""
    assert self.symmetric == 0
    assert self.keep_negative
    assert self.alpha is None or self.alpha == 1.0

    x = np.asarray(range(2**self.bits), dtype=np.float32)
    p_and_n = np.where(x >= 2**(self.bits - 1),
                       (x - 2**(self.bits - 1)) - 2**(self.bits - 1), x)
    return p_and_n * np.array(
        K.pow(2.0, -self.bits + K.cast(self.integer, dtype="float32") + 1),
        dtype="float32")

  @classmethod
  def from_config(cls, config):
    return cls(**config)

  def get_config(self):
    config = {
        "bits":
            self.bits,
        "integer":
            self.integer.numpy()
            if isinstance(self.integer, tf.Variable) else self.integer,
        "symmetric":
            self.symmetric,
        "alpha":
            self.alpha,
        "keep_negative":
            self.keep_negative,
        "use_stochastic_rounding":

            self.use_stochastic_rounding,