include "Tensor.fbs";
namespace MNN;
enum PadMode : byte{
    CAFFE=0,
    VALID=1,
    SAME=2
}

table Convolution2DCommon {
    padX:int = 0;
    padY:int = 0;
    kernelX:int = 1;
    kernelY:int = 1;
    strideX:int = 1;
    strideY:int = 1;
    dilateX:int = 1;
    dilateY:int = 1;
    padMode:PadMode = CAFFE;
    group:int = 1;
    outputCount:int = 0;
    inputCount:int = 0;
    relu:bool=false;
    relu6:bool=false;
    pads:[int];
    outPads:[int];
    hasOutputShape:bool = false;
}

table Convolution3DCommon {
    dilates:[int];
    strides:[int];
    kernels:[int];
    pads:[int];
    padMode:PadMode = CAFFE;
    inputCount:int = 0;
    outputCount:int = 0;
    relu:bool = false;
    relu6:bool = false;
    group:int = 1;
    outPads:[int];
    hasOutputShape:bool = false;
}

enum SparseAlgo : byte {
    RANDOM = 0,
    SIMD_OC = 1,
}

table SparseCommon {
    method:SparseAlgo = RANDOM;
    args:[Attribute];
}

// idst param
table IDSTQuan {
    buffer:[byte];
    alpha:[float];
    // 1->idstQuanInt8, 2->idstSparseQuan, 3->fp16, 4->weightInt8
    type:int;
    useInt32:bool;
    quantScale:float;
    scaleIn:float;
    scaleOut:float;
    aMax:int;
    aMin:int;
    readType:int;
    has_scaleInt:bool;
}

enum QuantizeAlgo : byte {
    DEFAULT = 0,
    OVERFLOW_AWARE = 1,
    WINOGRAD_AWARE = 2,
}

table QuantizedFloatParam{
    weight:[byte];
    bias:[int];
    // scale channel-wise(depthwise conv/batchnorm...)
    // which is used to int32*scale->int8
    scale:[float];
    // tensor scale, which is used to dequantize the int8 value to float value
    // only used for debug or output op
    tensorScale:[float];
    // quantize algorithm
    method:QuantizeAlgo = DEFAULT;
    nbits: int = 8;
    zeroPoint: byte = 0;
    outputZeroPoint: byte = 0;
    clampMin: byte = -128;
    clampMax: byte = 127;
    // binary proto: [originKySize, originKxSize, transKySize, transKxSize, {kyStart, kxStart, unitY, unitX}, {...} ...]
    winogradAttr:[int];
}

table Convolution2D {
    common:Convolution2DCommon;
    weight:[float];
    bias:[float];
    quanParameter:IDSTQuan;
    symmetricQuan:QuantizedFloatParam;
    sparseParameter:SparseCommon;
}

table Convolution3D {
    common:Convolution3DCommon;
    weight:[float];
    bias:[float];
}

table InnerProduct {
    outputCount:int;
    biasTerm:int;
    weightSize:int;
    weight:[float];
    bias:[float];
    axis:int;
    transpose:bool;
    // idst param
    quanParameter:IDSTQuan;
}

enum PoolType : byte {
    MAXPOOL=0,
    AVEPOOL
}
enum PoolPadType : byte {
    CAFFE=0,
    VALID,
    SAME
}
enum AvgPoolCountType : byte {
    DEFAULT=0,
    INCLUDE_PADDING,
    EXCLUDE_PADDING
}
table Pool {
    padX:int;
    padY:int;
    isGlobal:bool=false;
    kernelX:int;
    kernelY:int;
    strideX:int;
    strideY:int;
    type:PoolType;
    padType:PoolPadType;
    dataType:DataType=DT_FLOAT;
    ceilModel:bool=true;
    pads:[int];
    countType:AvgPoolCountType;
}

table Pool3D {
    strides:[int];
    kernels:[int];
    pads:[int];

    type:PoolType;
    padType:PoolPadType;
    isGlobal:bool=false;
}

table Relu {
    slope:float;
}

table Relu6 {
    minValue:float = 0.0;
    maxValue:float = 6.0;
}

table PRelu {
    slopeCount:int;
    slope:[float];
}

table ELU {
    alpha:float;
}

table LRN {
    regionType:int;
    localSize:int;
    alpha:float;
    beta:float;
    bias:float=1.0;
}

table ArgMax {
    outMaxVal:int;
    topK:int;
    axis:int;
    softmaxThreshold:int;
}

table Axis {
    axis:int;
}

table Input {
    dims:[int];
    dtype:DataType = DT_FLOAT;
    dformat:MNN_DATA_FORMAT = NC4HW4;
}

table LSTM {
    // param
  outputCount:int;
  weightSize:int;
  clippingThreshold:float;
  // model
  weightI:Blob;
  weightH:Blob;
  bias:Blob;
  weightIQ:Blob;
  weightIA:Blob;
  quantScale:float;
}

table Slice {
    axis:int;
    slicePoints:[int];
    sourceType:NetSource=CAFFE;
}

table BatchNorm {
  channels:int;
  slopeData:[float];
  meanData:[float];
  varData:[float];
  biasData:[float];
  Adata:[float];
  Bdata:[float];
  epsilon:float=0.001;
}

table Scale {
    channels:int;
    scaleData:[float];
    biasData:[float];
}

enum EltwiseType : byte {
    PROD = 0,
    SUM = 1,
    MAXIMUM = 2,
    SUB = 3
}

table Eltwise {
    type:EltwiseType;
    coeff:[float];
}

table Flatten {
    axis:int;
    endAxis:int;
}

table Permute {
    dims:[int];
}

table Reshape {
    dims:[int];
    dimType: MNN_DATA_FORMAT;
}

table DetectionOutput {
    classCount:int;
    nmsThresholdold:float;
    nmsTopK:int;
    keepTopK:int;
    confidenceThreshold:float;
    shareLocation:int;
    backgroundLable:int;
    varianceEncodedTarget:int;
    codeType:int;
    objectnessScore:float=0.01;
}

table RoiParameters {
    pooledWidth:int;
    pooledHeight:int;
    spatialScale:float;
    samplingRatio:int = -1;
    aligned:bool = false;
    poolType:PoolType = AVEPOOL;
}

table Proposal {
    featStride:int;
    baseSize:int;
    preNmsTopN:int;
    afterNmsTopN:int;
    nmsThreshold:float;
    minSize:int;
    ratios:Blob;
    scales:Blob;
    anchors:Blob;
}

enum CoordinateTransformationMode : byte{
    NotSet = 0,
    AlignCorners = 1,
    HalfPixels = 2,
    PytorchHalfPixels = 3,
    Asymmetric = 4,
    TensorflowHalfPixels = 5,
    TensorflowCropAndResize = 6,
}

table Interp {
    widthScale:float;
    heightScale:float;
    outputWidth:int;
    outputHeight:int;
    resizeType:int;
    alignCorners:bool;
    halfPixelCenters:bool = false;
    widthOffset:float;
    heightOffset:float;
    cubicCoeffA:float = -0.75;
    ctm:CoordinateTransformationMode = NotSet;
    depthScale:float;
    outputDepth:int;
    depthOffset:float;
} 

table Resize {
    xScale:float;
    yScale:float;
}

table PriorBox {
  minSizes : [float];
  maxSizes : [float];
  aspectRatios : [float];
  variances:[float];
  flip:bool;
  clip:bool;
  imageWidth:int;
  imageHeight:int;
  stepWidth:int;
  stepHeight:int;
  offset:float;
}

table Normalize {
  acrossSpatial:int;
  channelShared:int;
  eps:float;
  scale:[float];
}

table EltwiseInt8 {
    type:EltwiseType;
    inputQuan0:QuantizedFloatParam;
    inputQuan1:QuantizedFloatParam;
    outputQuan:QuantizedFloatParam;
}

table CumSum {
    exclusive:bool;
    reverse:bool;
}
