# automatically generated by the FlatBuffers compiler, do not modify

# namespace: tflite

import flatbuffers
from flatbuffers.compat import import_numpy
np = import_numpy()

class SparsityParameters(object):
    __slots__ = ['_tab']

    @classmethod
    def GetRootAs(cls, buf, offset=0):
        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
        x = SparsityParameters()
        x.Init(buf, n + offset)
        return x

    @classmethod
    def GetRootAsSparsityParameters(cls, buf, offset=0):
        """This method is deprecated. Please switch to GetRootAs."""
        return cls.GetRootAs(buf, offset)
    @classmethod
    def SparsityParametersBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
        return flatbuffers.util.BufferHasIdentifier(buf, offset, b"\x54\x46\x4C\x33", size_prefixed=size_prefixed)

    # SparsityParameters
    def Init(self, buf, pos):
        self._tab = flatbuffers.table.Table(buf, pos)

    # SparsityParameters
    def TraversalOrder(self, j):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
        if o != 0:
            a = self._tab.Vector(o)
            return self._tab.Get(flatbuffers.number_types.Int32Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
        return 0

    # SparsityParameters
    def TraversalOrderAsNumpy(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
        if o != 0:
            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
        return 0

    # SparsityParameters
    def TraversalOrderLength(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
        if o != 0:
            return self._tab.VectorLen(o)
        return 0

    # SparsityParameters
    def TraversalOrderIsNone(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
        return o == 0

    # SparsityParameters
    def BlockMap(self, j):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
        if o != 0:
            a = self._tab.Vector(o)
            return self._tab.Get(flatbuffers.number_types.Int32Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
        return 0

    # SparsityParameters
    def BlockMapAsNumpy(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
        if o != 0:
            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
        return 0

    # SparsityParameters
    def BlockMapLength(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
        if o != 0:
            return self._tab.VectorLen(o)
        return 0

    # SparsityParameters
    def BlockMapIsNone(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
        return o == 0

    # SparsityParameters
    def DimMetadata(self, j):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
        if o != 0:
            x = self._tab.Vector(o)
            x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
            x = self._tab.Indirect(x)
            from tflite.DimensionMetadata import DimensionMetadata
            obj = DimensionMetadata()
            obj.Init(self._tab.Bytes, x)
            return obj
        return None

    # SparsityParameters
    def DimMetadataLength(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
        if o != 0:
            return self._tab.VectorLen(o)
        return 0

    # SparsityParameters
    def DimMetadataIsNone(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
        return o == 0

def Start(builder): builder.StartObject(3)
def SparsityParametersStart(builder):
    """This method is deprecated. Please switch to Start."""
    return Start(builder)
def AddTraversalOrder(builder, traversalOrder): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(traversalOrder), 0)
def SparsityParametersAddTraversalOrder(builder, traversalOrder):
    """This method is deprecated. Please switch to AddTraversalOrder."""
    return AddTraversalOrder(builder, traversalOrder)
def StartTraversalOrderVector(builder, numElems): return builder.StartVector(4, numElems, 4)
def SparsityParametersStartTraversalOrderVector(builder, numElems):
    """This method is deprecated. Please switch to Start."""
    return StartTraversalOrderVector(builder, numElems)
def AddBlockMap(builder, blockMap): builder.PrependUOffsetTRelativeSlot(1, flatbuffers.number_types.UOffsetTFlags.py_type(blockMap), 0)
def SparsityParametersAddBlockMap(builder, blockMap):
    """This method is deprecated. Please switch to AddBlockMap."""
    return AddBlockMap(builder, blockMap)
def StartBlockMapVector(builder, numElems): return builder.StartVector(4, numElems, 4)
def SparsityParametersStartBlockMapVector(builder, numElems):
    """This method is deprecated. Please switch to Start."""
    return StartBlockMapVector(builder, numElems)
def AddDimMetadata(builder, dimMetadata): builder.PrependUOffsetTRelativeSlot(2, flatbuffers.number_types.UOffsetTFlags.py_type(dimMetadata), 0)
def SparsityParametersAddDimMetadata(builder, dimMetadata):
    """This method is deprecated. Please switch to AddDimMetadata."""
    return AddDimMetadata(builder, dimMetadata)
def StartDimMetadataVector(builder, numElems): return builder.StartVector(4, numElems, 4)
def SparsityParametersStartDimMetadataVector(builder, numElems):
    """This method is deprecated. Please switch to Start."""
    return StartDimMetadataVector(builder, numElems)
def End(builder): return builder.EndObject()
def SparsityParametersEnd(builder):
    """This method is deprecated. Please switch to End."""
    return End(builder)