## This file is generated by tempita. Do not modify this file directly or your changes will get overwritten.
## To edit this file edit the template in template/src

from io import BytesIO
from copy import deepcopy
import warnings
from math import trunc, floor, ceil

from . import __major__
from ._numeric cimport AbstractBaseNumericTag
from ._const cimport ID_FLOAT, ID_DOUBLE
from ._util cimport write_float, write_double, BufferContext, read_data, to_little_endian
if __major__ <= 2:
    from ._util import primitive_conversion
from ._dtype import EncoderType


cdef class AbstractBaseFloatTag(AbstractBaseNumericTag):
    """Abstract Base Class for all float Tag classes"""

    @property
    def py_float(AbstractBaseNumericTag self) -> float:
        """
        A python float representation of the class.
        The returned data is immutable so changes will not mirror the instance.
        """
        raise NotImplementedError

    @property
    def py_data(self):
        """
        A python representation of the class. Note that the return type is undefined and may change in the future.
        You would be better off using the py_{type} or np_array properties if you require a fixed type.
        This is here for convenience to get a python representation under the same property name.
        """
        return self.py_float



cdef inline FloatTag read_float_tag(BufferContext buffer, bint little_endian):
    cdef FloatTag tag = FloatTag.__new__(FloatTag)
    cdef float*pointer = <float*> read_data(buffer, 4)
    tag.value_ = pointer[0]
    to_little_endian(&tag.value_, 4, little_endian)
    return tag


cdef class FloatTag(AbstractBaseFloatTag):
    """A single precision float class."""
    tag_id = ID_FLOAT

    def __init__(FloatTag self, value = 0):
        self.value_ = float(value)

    def __str__(FloatTag self):
        return str(self.value_)

    def __eq__(FloatTag self, other):
        cdef FloatTag other_
        if isinstance(other, FloatTag):
            other_ = other
            return self.value_ == other_.value_
        elif __major__ <= 2:
            warnings.warn("NBT comparison operator (a == b) will only return True between classes of the same type.", FutureWarning)
            return self.value_ == primitive_conversion(other)
        return NotImplemented

    def __reduce__(FloatTag self):
        return self.__class__, (self.value_,)

    def __deepcopy__(FloatTag self, memo=None):
        return self.__class__(deepcopy(self.value_, memo=memo))

    def __copy__(FloatTag self):
        return self.__class__(self.value_)

    def __hash__(FloatTag self):
        return hash((self.tag_id, self.value_))

    def __ge__(FloatTag self, other):
        cdef FloatTag other_
        if isinstance(other, FloatTag):
            other_ = other
            return self.value_ >= other_.value_
        elif __major__ <= 2:
            warnings.warn("NBT comparison operator (a >= b) will only return True between classes of the same type.", FutureWarning)
            return self.value_ >= primitive_conversion(other)
        return NotImplemented

    def __gt__(FloatTag self, other):
        cdef FloatTag other_
        if isinstance(other, FloatTag):
            other_ = other
            return self.value_ > other_.value_
        elif __major__ <= 2:
            warnings.warn("NBT comparison operator (a > b) will only return True between classes of the same type.", FutureWarning)
            return self.value_ > primitive_conversion(other)
        return NotImplemented

    def __le__(FloatTag self, other):
        cdef FloatTag other_
        if isinstance(other, FloatTag):
            other_ = other
            return self.value_ <= other_.value_
        elif __major__ <= 2:
            warnings.warn("NBT comparison operator (a <= b) will only return True between classes of the same type.", FutureWarning)
            return self.value_ <= primitive_conversion(other)
        return NotImplemented

    def __lt__(FloatTag self, other):
        cdef FloatTag other_
        if isinstance(other, FloatTag):
            other_ = other
            return self.value_ < other_.value_
        elif __major__ <= 2:
            warnings.warn("NBT comparison operator (a == b) will only return True between classes of the same type.", FutureWarning)
            return self.value_ < primitive_conversion(other)
        return NotImplemented

    def __repr__(FloatTag self):
        return f"{self.__class__.__name__}({self.value_})"

    def __int__(FloatTag self):
        return self.value_.__int__()

    def __float__(FloatTag self):
        return self.value_.__float__()

    def __bool__(FloatTag self):
        return self.value_.__bool__()

    @property
    def py_float(FloatTag self) -> float:
        """
        A python float representation of the class.
        The returned data is immutable so changes will not mirror the instance.
        """
        return self.value_

    if __major__ <= 2:
        def __add__(self, other):
            warnings.warn(f"__add__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return float(primitive_conversion(self) + primitive_conversion(other))

        def __sub__(self, other):
            warnings.warn(f"__sub__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return float(primitive_conversion(self) - primitive_conversion(other))

        def __mul__(self, other):
            warnings.warn(f"__mul__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return float(primitive_conversion(self) * primitive_conversion(other))

        def __truediv__(self, other):
            warnings.warn(f"__truediv__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return float(primitive_conversion(self) / primitive_conversion(other))

        def __floordiv__(self, other):
            warnings.warn(f"__floordiv__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(self) // primitive_conversion(other)

        def __mod__(self, other):
            warnings.warn(f"__mod__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(self) % primitive_conversion(other)

        def __divmod__(self, other):
            warnings.warn(f"__divmod__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return divmod(primitive_conversion(self), primitive_conversion(other))

        def __pow__(self, power, modulo):
            warnings.warn(f"__pow__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return pow(primitive_conversion(self), power, modulo)

        def __lshift__(self, other):
            warnings.warn(f"__lshift__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(self) << primitive_conversion(other)

        def __rshift__(self, other):
            warnings.warn(f"__rshift__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(self) >> primitive_conversion(other)

        def __and__(self, other):
            warnings.warn(f"__and__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(self) & primitive_conversion(other)

        def __xor__(self, other):
            warnings.warn(f"__xor__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(self) ^ primitive_conversion(other)

        def __or__(self, other):
            warnings.warn(f"__or__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(self) | primitive_conversion(other)

        def __radd__(self, other):
            warnings.warn(f"__radd__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return float(primitive_conversion(other) + primitive_conversion(self))

        def __rsub__(self, other):
            warnings.warn(f"__rsub__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return float(primitive_conversion(other) - primitive_conversion(self))

        def __rmul__(self, other):
            warnings.warn(f"__rmul__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(other) * primitive_conversion(self)

        def __rtruediv__(self, other):
            warnings.warn(f"__rtruediv__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return float(primitive_conversion(other) / primitive_conversion(self))

        def __rfloordiv__(self, other):
            warnings.warn(f"__rfloordiv__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(other) // primitive_conversion(self)

        def __rmod__(self, other):
            warnings.warn(f"__rmod__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(other) % primitive_conversion(self)

        def __rdivmod__(self, other):
            warnings.warn(f"__rdivmod__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return divmod(primitive_conversion(other), primitive_conversion(self))

        def __rpow__(self, other, modulo):
            warnings.warn(f"__rpow__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return pow(primitive_conversion(other), primitive_conversion(self), modulo)

        def __rlshift__(self, other):
            warnings.warn(f"__rlshift__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(other) << primitive_conversion(self)

        def __rrshift__(self, other):
            warnings.warn(f"__rrshift__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(other) >> primitive_conversion(self)

        def __rand__(self, other):
            warnings.warn(f"__rand__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(other) & primitive_conversion(self)

        def __rxor__(self, other):
            warnings.warn(f"__rxor__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(other) ^ primitive_conversion(self)

        def __ror__(self, other):
            warnings.warn(f"__ror__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(other) | primitive_conversion(self)

        def __neg__(self):
            warnings.warn(f"__neg__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return -self.value_

        def __pos__(self):
            warnings.warn(f"__pos__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return +self.value_

        def __abs__(self):
            warnings.warn(f"__abs__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return abs(self.value_)

        def __round__(self, n=None):
            warnings.warn(f"__round__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return round(self.value_, n)

        def __trunc__(self):
            warnings.warn(f"__trunc__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return trunc(self.value_)

        def __floor__(self):
            warnings.warn(f"__floor__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return floor(self.value_)

        def __ceil__(self):
            warnings.warn(f"__ceil__ is depreciated on FloatTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return ceil(self.value_)

    cdef str _to_snbt(FloatTag self):
        return f"{self.value_}f"

    cdef void write_payload(
        FloatTag self,
        object buffer: BytesIO,
        bint little_endian,
        string_encoder: EncoderType,
    ) except *:
        write_float(self.value_, buffer, little_endian)


cdef inline DoubleTag read_double_tag(BufferContext buffer, bint little_endian):
    cdef DoubleTag tag = DoubleTag.__new__(DoubleTag)
    cdef double *pointer = <double *> read_data(buffer, 8)
    tag.value_ = pointer[0]
    to_little_endian(&tag.value_, 8, little_endian)
    return tag


cdef class DoubleTag(AbstractBaseFloatTag):
    """A double precision float class."""
    tag_id = ID_DOUBLE

    def __init__(DoubleTag self, value = 0):
        self.value_ = float(value)

    def __str__(DoubleTag self):
        return str(self.value_)

    def __eq__(DoubleTag self, other):
        cdef DoubleTag other_
        if isinstance(other, DoubleTag):
            other_ = other
            return self.value_ == other_.value_
        elif __major__ <= 2:
            warnings.warn("NBT comparison operator (a == b) will only return True between classes of the same type.", FutureWarning)
            return self.value_ == primitive_conversion(other)
        return NotImplemented

    def __reduce__(DoubleTag self):
        return self.__class__, (self.value_,)

    def __deepcopy__(DoubleTag self, memo=None):
        return self.__class__(deepcopy(self.value_, memo=memo))

    def __copy__(DoubleTag self):
        return self.__class__(self.value_)

    def __hash__(DoubleTag self):
        return hash((self.tag_id, self.value_))

    def __ge__(DoubleTag self, other):
        cdef DoubleTag other_
        if isinstance(other, DoubleTag):
            other_ = other
            return self.value_ >= other_.value_
        elif __major__ <= 2:
            warnings.warn("NBT comparison operator (a >= b) will only return True between classes of the same type.", FutureWarning)
            return self.value_ >= primitive_conversion(other)
        return NotImplemented

    def __gt__(DoubleTag self, other):
        cdef DoubleTag other_
        if isinstance(other, DoubleTag):
            other_ = other
            return self.value_ > other_.value_
        elif __major__ <= 2:
            warnings.warn("NBT comparison operator (a > b) will only return True between classes of the same type.", FutureWarning)
            return self.value_ > primitive_conversion(other)
        return NotImplemented

    def __le__(DoubleTag self, other):
        cdef DoubleTag other_
        if isinstance(other, DoubleTag):
            other_ = other
            return self.value_ <= other_.value_
        elif __major__ <= 2:
            warnings.warn("NBT comparison operator (a <= b) will only return True between classes of the same type.", FutureWarning)
            return self.value_ <= primitive_conversion(other)
        return NotImplemented

    def __lt__(DoubleTag self, other):
        cdef DoubleTag other_
        if isinstance(other, DoubleTag):
            other_ = other
            return self.value_ < other_.value_
        elif __major__ <= 2:
            warnings.warn("NBT comparison operator (a == b) will only return True between classes of the same type.", FutureWarning)
            return self.value_ < primitive_conversion(other)
        return NotImplemented

    def __repr__(DoubleTag self):
        return f"{self.__class__.__name__}({self.value_})"

    def __int__(DoubleTag self):
        return self.value_.__int__()

    def __float__(DoubleTag self):
        return self.value_.__float__()

    def __bool__(DoubleTag self):
        return self.value_.__bool__()

    @property
    def py_float(DoubleTag self) -> float:
        """
        A python float representation of the class.
        The returned data is immutable so changes will not mirror the instance.
        """
        return self.value_

    if __major__ <= 2:
        def __add__(self, other):
            warnings.warn(f"__add__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return float(primitive_conversion(self) + primitive_conversion(other))

        def __sub__(self, other):
            warnings.warn(f"__sub__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return float(primitive_conversion(self) - primitive_conversion(other))

        def __mul__(self, other):
            warnings.warn(f"__mul__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return float(primitive_conversion(self) * primitive_conversion(other))

        def __truediv__(self, other):
            warnings.warn(f"__truediv__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return float(primitive_conversion(self) / primitive_conversion(other))

        def __floordiv__(self, other):
            warnings.warn(f"__floordiv__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(self) // primitive_conversion(other)

        def __mod__(self, other):
            warnings.warn(f"__mod__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(self) % primitive_conversion(other)

        def __divmod__(self, other):
            warnings.warn(f"__divmod__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return divmod(primitive_conversion(self), primitive_conversion(other))

        def __pow__(self, power, modulo):
            warnings.warn(f"__pow__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return pow(primitive_conversion(self), power, modulo)

        def __lshift__(self, other):
            warnings.warn(f"__lshift__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(self) << primitive_conversion(other)

        def __rshift__(self, other):
            warnings.warn(f"__rshift__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(self) >> primitive_conversion(other)

        def __and__(self, other):
            warnings.warn(f"__and__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(self) & primitive_conversion(other)

        def __xor__(self, other):
            warnings.warn(f"__xor__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(self) ^ primitive_conversion(other)

        def __or__(self, other):
            warnings.warn(f"__or__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(self) | primitive_conversion(other)

        def __radd__(self, other):
            warnings.warn(f"__radd__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return float(primitive_conversion(other) + primitive_conversion(self))

        def __rsub__(self, other):
            warnings.warn(f"__rsub__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return float(primitive_conversion(other) - primitive_conversion(self))

        def __rmul__(self, other):
            warnings.warn(f"__rmul__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(other) * primitive_conversion(self)

        def __rtruediv__(self, other):
            warnings.warn(f"__rtruediv__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return float(primitive_conversion(other) / primitive_conversion(self))

        def __rfloordiv__(self, other):
            warnings.warn(f"__rfloordiv__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(other) // primitive_conversion(self)

        def __rmod__(self, other):
            warnings.warn(f"__rmod__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(other) % primitive_conversion(self)

        def __rdivmod__(self, other):
            warnings.warn(f"__rdivmod__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return divmod(primitive_conversion(other), primitive_conversion(self))

        def __rpow__(self, other, modulo):
            warnings.warn(f"__rpow__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return pow(primitive_conversion(other), primitive_conversion(self), modulo)

        def __rlshift__(self, other):
            warnings.warn(f"__rlshift__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(other) << primitive_conversion(self)

        def __rrshift__(self, other):
            warnings.warn(f"__rrshift__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(other) >> primitive_conversion(self)

        def __rand__(self, other):
            warnings.warn(f"__rand__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(other) & primitive_conversion(self)

        def __rxor__(self, other):
            warnings.warn(f"__rxor__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(other) ^ primitive_conversion(self)

        def __ror__(self, other):
            warnings.warn(f"__ror__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return primitive_conversion(other) | primitive_conversion(self)

        def __neg__(self):
            warnings.warn(f"__neg__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return -self.value_

        def __pos__(self):
            warnings.warn(f"__pos__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return +self.value_

        def __abs__(self):
            warnings.warn(f"__abs__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return abs(self.value_)

        def __round__(self, n=None):
            warnings.warn(f"__round__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return round(self.value_, n)

        def __trunc__(self):
            warnings.warn(f"__trunc__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return trunc(self.value_)

        def __floor__(self):
            warnings.warn(f"__floor__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return floor(self.value_)

        def __ceil__(self):
            warnings.warn(f"__ceil__ is depreciated on DoubleTag and will be removed in the future. Please use .py_float to achieve the same behaviour.", DeprecationWarning)
            return ceil(self.value_)

    cdef str _to_snbt(DoubleTag self):
        return f"{self.value_}d"

    cdef void write_payload(
        DoubleTag self,
        object buffer: BytesIO,
        bint little_endian,
        string_encoder: EncoderType,
    ) except *:
        write_double(self.value_, buffer, little_endian)
