# automatically generated by the FlatBuffers compiler, do not modify

# namespace: tosa

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

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

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

    @classmethod
    def GetRootAsTransposeConvAttribute(cls, buf, offset=0):
        """This method is deprecated. Please switch to GetRootAs."""
        return cls.GetRootAs(buf, offset)
    @classmethod
    def TransposeConvAttributeBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
        return flatbuffers.util.BufferHasIdentifier(buf, offset, b"\x54\x4F\x53\x41", size_prefixed=size_prefixed)

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

    # TransposeConvAttribute
    def OutPad(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

    # TransposeConvAttribute
    def OutPadAsNumpy(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

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

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

    # TransposeConvAttribute
    def Stride(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

    # TransposeConvAttribute
    def StrideAsNumpy(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

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

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

    # TransposeConvAttribute
    def InputZp(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
        if o != 0:
            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
        return 0

    # TransposeConvAttribute
    def WeightZp(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
        if o != 0:
            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
        return 0

    # TransposeConvAttribute
    def LocalBound(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
        if o != 0:
            return bool(self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
        return False

    # TransposeConvAttribute
    def AccType(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
        if o != 0:
            return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos)
        return 0

def TransposeConvAttributeStart(builder):
    builder.StartObject(6)

def Start(builder):
    TransposeConvAttributeStart(builder)

def TransposeConvAttributeAddOutPad(builder, outPad):
    builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(outPad), 0)

def AddOutPad(builder, outPad):
    TransposeConvAttributeAddOutPad(builder, outPad)

def TransposeConvAttributeStartOutPadVector(builder, numElems):
    return builder.StartVector(4, numElems, 4)

def StartOutPadVector(builder, numElems: int) -> int:
    return TransposeConvAttributeStartOutPadVector(builder, numElems)

def TransposeConvAttributeAddStride(builder, stride):
    builder.PrependUOffsetTRelativeSlot(1, flatbuffers.number_types.UOffsetTFlags.py_type(stride), 0)

def AddStride(builder, stride):
    TransposeConvAttributeAddStride(builder, stride)

def TransposeConvAttributeStartStrideVector(builder, numElems):
    return builder.StartVector(4, numElems, 4)

def StartStrideVector(builder, numElems: int) -> int:
    return TransposeConvAttributeStartStrideVector(builder, numElems)

def TransposeConvAttributeAddInputZp(builder, inputZp):
    builder.PrependInt32Slot(2, inputZp, 0)

def AddInputZp(builder, inputZp):
    TransposeConvAttributeAddInputZp(builder, inputZp)

def TransposeConvAttributeAddWeightZp(builder, weightZp):
    builder.PrependInt32Slot(3, weightZp, 0)

def AddWeightZp(builder, weightZp):
    TransposeConvAttributeAddWeightZp(builder, weightZp)

def TransposeConvAttributeAddLocalBound(builder, localBound):
    builder.PrependBoolSlot(4, localBound, 0)

def AddLocalBound(builder, localBound):
    TransposeConvAttributeAddLocalBound(builder, localBound)

def TransposeConvAttributeAddAccType(builder, accType):
    builder.PrependUint32Slot(5, accType, 0)

def AddAccType(builder, accType):
    TransposeConvAttributeAddAccType(builder, accType)

def TransposeConvAttributeEnd(builder):
    return builder.EndObject()

def End(builder):
    return TransposeConvAttributeEnd(builder)
