/*******************************************************************************
* Copyright 2015-2020 Intel Corporation.
*
* This software and the related documents are Intel copyrighted  materials,  and
* your use of  them is  governed by the  express license  under which  they were
* provided to you (License).  Unless the License provides otherwise, you may not
* use, modify, copy, publish, distribute,  disclose or transmit this software or
* the related documents without Intel's prior written permission.
*
* This software and the related documents  are provided as  is,  with no express
* or implied  warranties,  other  than those  that are  expressly stated  in the
* License.
*******************************************************************************/

/*
//   Purpose: Functions of Addition operation
//   Contents:
//       ippiAdd_8u_C1RSfs_LT
//       ippiAdd_8u_C3RSfs_LT
//       ippiAdd_8u_C4RSfs_LT
//       ippiAdd_8u_AC4RSfs_LT
//       ippiAdd_16u_C1RSfs_LT
//       ippiAdd_16u_C3RSfs_LT
//       ippiAdd_16u_C4RSfs_LT
//       ippiAdd_16u_AC4RSfs_LT
//       ippiAdd_16s_C1RSfs_LT
//       ippiAdd_16s_C3RSfs_LT
//       ippiAdd_16s_C4RSfs_LT
//       ippiAdd_16s_AC4RSfs_LT
//       ippiAdd_32f_C1R_LT
//       ippiAdd_32f_C3R_LT
//       ippiAdd_32f_C4R_LT
//       ippiAdd_32f_AC4R_LT
//       ippiAdd_8u_C1IRSfs_LT
//       ippiAdd_8u_C3IRSfs_LT
//       ippiAdd_8u_C4IRSfs_LT
//       ippiAdd_8u_AC4IRSfs_LT
//       ippiAdd_16u_C1IRSfs_LT
//       ippiAdd_16u_C3IRSfs_LT
//       ippiAdd_16u_C4IRSfs_LT
//       ippiAdd_16u_AC4IRSfs_LT
//       ippiAdd_16s_C1IRSfs_LT
//       ippiAdd_16s_C3IRSfs_LT
//       ippiAdd_16s_C4IRSfs_LT
//       ippiAdd_16s_AC4IRSfs_LT
//       ippiAdd_32f_C1IR_LT
//       ippiAdd_32f_C3IR_LT
//       ippiAdd_32f_C4IR_LT
//       ippiAdd_32f_AC4IR_LT
*/

#include "pisimplearithm_tl.h"



IppStatus ippiAdd_8u_C1RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmetics_8u_LT_Str *ts = (ippiSimpleArithmetics_8u_LT_Str *)arg;
    const Ipp8u *pSrc1 = (const Ipp8u *)ts->pSrc1;
    IppSizeL src1Step = ts->src1Step;
    const Ipp8u *pSrc2 = (const Ipp8u *)ts->pSrc2;
    IppSizeL src2Step = ts->src2Step;
    Ipp8u *pDst = ts->pDst;
    IppSizeL dstStep = ts->dstStep;
    IppiSizeL roiSize = ts->roiSize;
    int scaleFactor = ts->scaleFactor;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;

    const Ipp8u *pSrc1Roi, *pSrc2Roi;
    Ipp8u       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrc1Roi = owniGetImagePointer_8u_C1 (pSrc1, src1Step, roiOffset.x, roiOffset.y);
    pSrc2Roi = owniGetImagePointer_8u_C1 (pSrc2, src2Step, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_8u_C1 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiAdd_8u_C1RSfs_L (pSrc1Roi, src1Step, pSrc2Roi, src2Step, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_8u_C1RSfs_LT, (const Ipp8u* pSrc1, IppSizeL src1Step, const Ipp8u* pSrc2,
                                          IppSizeL src2Step, Ipp8u* pDst, IppSizeL dstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp8u);

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   minTileSize = IPP64_MIN_ADD_2D / pixelSize;

    if (pSrc1 == 0 || pSrc2 == 0 || pDst == 0)     return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    owniSplitUniform2D_LT (roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiAdd_8u_C1RSfs_L (pSrc1, src1Step, pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmetics_8u_LT_Str ts;
        simpleArithmeticsThreadingStructureEncode_8u ((Ipp8u *)pSrc1, src1Step, (Ipp8u *)pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiAdd_8u_C1RSfs_LT_Fun);
    }

    return status;
}

IPPFUN (IppStatus, ippiAdd_8u_C3RSfs_LT, (const Ipp8u* pSrc1, IppSizeL src1Step, const Ipp8u* pSrc2,
                                          IppSizeL src2Step, Ipp8u* pDst, IppSizeL dstStep, IppiSizeL roiSize, int scaleFactor))
{
    roiSize.width *= 3;
    return ippiAdd_8u_C1RSfs_LT (pSrc1, src1Step, pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_8u_C4RSfs_LT, (const Ipp8u* pSrc1, IppSizeL src1Step, const Ipp8u* pSrc2,
                                          IppSizeL src2Step, Ipp8u* pDst, IppSizeL dstStep, IppiSizeL roiSize, int scaleFactor))
{
    roiSize.width *= 4;
    return ippiAdd_8u_C1RSfs_LT (pSrc1, src1Step, pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor);
}

IppStatus ippiAdd_8u_AC4RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmetics_8u_LT_Str *ts = (ippiSimpleArithmetics_8u_LT_Str *)arg;
    const Ipp8u *pSrc1 = (const Ipp8u *)ts->pSrc1;
    IppSizeL src1Step = ts->src1Step;
    const Ipp8u *pSrc2 = (const Ipp8u *)ts->pSrc2;
    IppSizeL src2Step = ts->src2Step;
    Ipp8u *pDst = ts->pDst;
    IppSizeL dstStep = ts->dstStep;
    IppiSizeL roiSize = ts->roiSize;
    int scaleFactor = ts->scaleFactor;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;

    const Ipp8u *pSrc1Roi, *pSrc2Roi;
    Ipp8u       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrc1Roi = owniGetImagePointer_8u_AC4 (pSrc1, src1Step, roiOffset.x, roiOffset.y);
    pSrc2Roi = owniGetImagePointer_8u_AC4 (pSrc2, src2Step, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_8u_AC4 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiAdd_8u_AC4RSfs_L (pSrc1Roi, src1Step, pSrc2Roi, src2Step, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_8u_AC4RSfs_LT, (const Ipp8u* pSrc1, IppSizeL src1Step, const Ipp8u* pSrc2,
                                           IppSizeL src2Step, Ipp8u* pDst, IppSizeL dstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp8u) * 4;

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   minTileSize = IPP_MIN (IPP64_MIN_ADD_2D / pixelSize, IPP_MAX_32S / pixelSize);

    if (pSrc1 == 0 || pSrc2 == 0 || pDst == 0)     return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    owniSplitUniform2D_LT (roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiAdd_8u_AC4RSfs_L (pSrc1, src1Step, pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmetics_8u_LT_Str ts;
        simpleArithmeticsThreadingStructureEncode_8u ((Ipp8u *)pSrc1, src1Step, (Ipp8u *)pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiAdd_8u_AC4RSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiAdd_16u_C1RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmetics_16u_LT_Str *ts = (ippiSimpleArithmetics_16u_LT_Str *)arg;
    const Ipp16u *pSrc1 = (const Ipp16u *)ts->pSrc1;
    IppSizeL src1Step = ts->src1Step;
    const Ipp16u *pSrc2 = (const Ipp16u *)ts->pSrc2;
    IppSizeL src2Step = ts->src2Step;
    Ipp16u *pDst = ts->pDst;
    IppSizeL dstStep = ts->dstStep;
    IppiSizeL roiSize = ts->roiSize;
    int scaleFactor = ts->scaleFactor;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;

    const Ipp16u *pSrc1Roi, *pSrc2Roi;
    Ipp16u       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrc1Roi = owniGetImagePointer_16u_C1 (pSrc1, src1Step, roiOffset.x, roiOffset.y);
    pSrc2Roi = owniGetImagePointer_16u_C1 (pSrc2, src2Step, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_16u_C1 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiAdd_16u_C1RSfs_L (pSrc1Roi, src1Step, pSrc2Roi, src2Step, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_16u_C1RSfs_LT, (const Ipp16u* pSrc1, IppSizeL src1Step, const Ipp16u* pSrc2,
                                           IppSizeL src2Step, Ipp16u* pDst, IppSizeL dstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp16u);

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   minTileSize = IPP64_MIN_ADD_2D / pixelSize;

    if (pSrc1 == 0 || pSrc2 == 0 || pDst == 0)     return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    owniSplitUniform2D_LT (roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiAdd_16u_C1RSfs_L (pSrc1, src1Step, pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmetics_16u_LT_Str ts;
        simpleArithmeticsThreadingStructureEncode_16u ((Ipp16u *)pSrc1, src1Step, (Ipp16u *)pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiAdd_16u_C1RSfs_LT_Fun);
    }

    return status;
}

IPPFUN (IppStatus, ippiAdd_16u_C3RSfs_LT, (const Ipp16u* pSrc1, IppSizeL src1Step, const Ipp16u* pSrc2,
                                           IppSizeL src2Step, Ipp16u* pDst, IppSizeL dstStep, IppiSizeL roiSize, int scaleFactor))
{
    roiSize.width *= 3;
    return ippiAdd_16u_C1RSfs_LT (pSrc1, src1Step, pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_16u_C4RSfs_LT, (const Ipp16u* pSrc1, IppSizeL src1Step, const Ipp16u* pSrc2,
                                           IppSizeL src2Step, Ipp16u* pDst, IppSizeL dstStep, IppiSizeL roiSize, int scaleFactor))
{
    roiSize.width *= 4;
    return ippiAdd_16u_C1RSfs_LT (pSrc1, src1Step, pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor);
}

IppStatus ippiAdd_16u_AC4RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmetics_16u_LT_Str *ts = (ippiSimpleArithmetics_16u_LT_Str *)arg;
    const Ipp16u *pSrc1 = (const Ipp16u *)ts->pSrc1;
    IppSizeL src1Step = ts->src1Step;
    const Ipp16u *pSrc2 = (const Ipp16u *)ts->pSrc2;
    IppSizeL src2Step = ts->src2Step;
    Ipp16u *pDst = ts->pDst;
    IppSizeL dstStep = ts->dstStep;
    IppiSizeL roiSize = ts->roiSize;
    int scaleFactor = ts->scaleFactor;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;

    const Ipp16u *pSrc1Roi, *pSrc2Roi;
    Ipp16u       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrc1Roi = owniGetImagePointer_16u_AC4 (pSrc1, src1Step, roiOffset.x, roiOffset.y);
    pSrc2Roi = owniGetImagePointer_16u_AC4 (pSrc2, src2Step, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_16u_AC4 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiAdd_16u_AC4RSfs_L (pSrc1Roi, src1Step, pSrc2Roi, src2Step, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_16u_AC4RSfs_LT, (const Ipp16u* pSrc1, IppSizeL src1Step, const Ipp16u* pSrc2,
                                            IppSizeL src2Step, Ipp16u* pDst, IppSizeL dstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp16u) * 4;

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   minTileSize = IPP_MIN (IPP64_MIN_ADD_2D / pixelSize, IPP_MAX_32S / pixelSize);

    if (pSrc1 == 0 || pSrc2 == 0 || pDst == 0)     return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    owniSplitUniform2D_LT (roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiAdd_16u_AC4RSfs_L (pSrc1, src1Step, pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmetics_16u_LT_Str ts;
        simpleArithmeticsThreadingStructureEncode_16u ((Ipp16u *)pSrc1, src1Step, (Ipp16u *)pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiAdd_16u_AC4RSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiAdd_16s_C1RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmetics_16s_LT_Str *ts = (ippiSimpleArithmetics_16s_LT_Str *)arg;
    const Ipp16s *pSrc1 = (const Ipp16s *)ts->pSrc1;
    IppSizeL src1Step = ts->src1Step;
    const Ipp16s *pSrc2 = (const Ipp16s *)ts->pSrc2;
    IppSizeL src2Step = ts->src2Step;
    Ipp16s *pDst = ts->pDst;
    IppSizeL dstStep = ts->dstStep;
    IppiSizeL roiSize = ts->roiSize;
    int scaleFactor = ts->scaleFactor;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;

    const Ipp16s *pSrc1Roi, *pSrc2Roi;
    Ipp16s       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrc1Roi = owniGetImagePointer_16s_C1 (pSrc1, src1Step, roiOffset.x, roiOffset.y);
    pSrc2Roi = owniGetImagePointer_16s_C1 (pSrc2, src2Step, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_16s_C1 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiAdd_16s_C1RSfs_L (pSrc1Roi, src1Step, pSrc2Roi, src2Step, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_16s_C1RSfs_LT, (const Ipp16s* pSrc1, IppSizeL src1Step, const Ipp16s* pSrc2,
                                           IppSizeL src2Step, Ipp16s* pDst, IppSizeL dstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp16s);

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   minTileSize = IPP64_MIN_ADD_2D / pixelSize;

    if (pSrc1 == 0 || pSrc2 == 0 || pDst == 0)     return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    owniSplitUniform2D_LT (roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiAdd_16s_C1RSfs_L (pSrc1, src1Step, pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmetics_16s_LT_Str ts;
        simpleArithmeticsThreadingStructureEncode_16s ((Ipp16s *)pSrc1, src1Step, (Ipp16s *)pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiAdd_16s_C1RSfs_LT_Fun);
    }

    return status;
}

IPPFUN (IppStatus, ippiAdd_16s_C3RSfs_LT, (const Ipp16s* pSrc1, IppSizeL src1Step, const Ipp16s* pSrc2,
                                           IppSizeL src2Step, Ipp16s* pDst, IppSizeL dstStep, IppiSizeL roiSize, int scaleFactor))
{
    roiSize.width *= 3;
    return ippiAdd_16s_C1RSfs_LT (pSrc1, src1Step, pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_16s_C4RSfs_LT, (const Ipp16s* pSrc1, IppSizeL src1Step, const Ipp16s* pSrc2,
                                           IppSizeL src2Step, Ipp16s* pDst, IppSizeL dstStep, IppiSizeL roiSize, int scaleFactor))
{
    roiSize.width *= 4;
    return ippiAdd_16s_C1RSfs_LT (pSrc1, src1Step, pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor);
}

IppStatus ippiAdd_16s_AC4RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmetics_16s_LT_Str *ts = (ippiSimpleArithmetics_16s_LT_Str *)arg;
    const Ipp16s *pSrc1 = (const Ipp16s *)ts->pSrc1;
    IppSizeL src1Step = ts->src1Step;
    const Ipp16s *pSrc2 = (const Ipp16s *)ts->pSrc2;
    IppSizeL src2Step = ts->src2Step;
    Ipp16s *pDst = ts->pDst;
    IppSizeL dstStep = ts->dstStep;
    IppiSizeL roiSize = ts->roiSize;
    int scaleFactor = ts->scaleFactor;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;

    const Ipp16s *pSrc1Roi, *pSrc2Roi;
    Ipp16s       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrc1Roi = owniGetImagePointer_16s_AC4 (pSrc1, src1Step, roiOffset.x, roiOffset.y);
    pSrc2Roi = owniGetImagePointer_16s_AC4 (pSrc2, src2Step, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_16s_AC4 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiAdd_16s_AC4RSfs_L (pSrc1Roi, src1Step, pSrc2Roi, src2Step, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_16s_AC4RSfs_LT, (const Ipp16s* pSrc1, IppSizeL src1Step, const Ipp16s* pSrc2,
                                            IppSizeL src2Step, Ipp16s* pDst, IppSizeL dstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp16s) * 4;

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   minTileSize = IPP_MIN (IPP64_MIN_ADD_2D / pixelSize, IPP_MAX_32S / pixelSize);

    if (pSrc1 == 0 || pSrc2 == 0 || pDst == 0)     return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    owniSplitUniform2D_LT (roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiAdd_16s_AC4RSfs_L (pSrc1, src1Step, pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmetics_16s_LT_Str ts;
        simpleArithmeticsThreadingStructureEncode_16s ((Ipp16s *)pSrc1, src1Step, (Ipp16s *)pSrc2, src2Step, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiAdd_16s_AC4RSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiAdd_8u_C1IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmetics_8u_LT_Str *ts = (ippiSimpleArithmetics_8u_LT_Str *)arg;
    const Ipp8u* pSrc = (const Ipp8u*)ts->pSrc1;
    IppSizeL srcStep = ts->src1Step;
    Ipp8u* pSrcDst = ts->pDst;
    IppSizeL srcDstStep = ts->dstStep;
    IppiSizeL roiSize = ts->roiSize;
    int scaleFactor = ts->scaleFactor;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;

    const Ipp8u *pSrcRoi;
    Ipp8u       *pSrcDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_8u_C1 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pSrcDstRoi = owniGetImagePointer_8u_C1 (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y);

    return ippiAdd_8u_C1IRSfs_L (pSrcRoi, srcStep, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_8u_C1IRSfs_LT, (const Ipp8u* pSrc, IppSizeL srcStep, Ipp8u* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp8u);

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   minTileSize = IPP_MIN (IPP64_MIN_ADD_2D / pixelSize, IPP_MAX_32S / pixelSize);

    if (pSrc == 0 || pSrcDst == 0)                 return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    owniSplitUniform2D_LT (roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiAdd_8u_C1IRSfs_L (pSrc, srcStep, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    { /* 32b function cannot be called directly */
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmetics_8u_LT_Str ts;
        simpleArithmeticsThreadingStructureEncode_8u ((Ipp8u*)pSrc, srcStep, (Ipp8u*)0, (IppSizeL)0, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiAdd_8u_C1IRSfs_LT_Fun);
    }

    return status;
}

IPPFUN (IppStatus, ippiAdd_8u_C3IRSfs_LT, (const Ipp8u* pSrc, IppSizeL srcStep, Ipp8u* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize, int scaleFactor))
{
    roiSize.width *= 3;
    return ippiAdd_8u_C1IRSfs_LT (pSrc, srcStep, pSrcDst, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_8u_C4IRSfs_LT, (const Ipp8u* pSrc, IppSizeL srcStep, Ipp8u* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize, int scaleFactor))
{
    roiSize.width *= 4;
    return ippiAdd_8u_C1IRSfs_LT (pSrc, srcStep, pSrcDst, srcDstStep, roiSize, scaleFactor);
}

IppStatus ippiAdd_8u_AC4IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmetics_8u_LT_Str *ts = (ippiSimpleArithmetics_8u_LT_Str *)arg;
    const Ipp8u* pSrc = (const Ipp8u*)ts->pSrc1;
    IppSizeL srcStep = ts->src1Step;
    Ipp8u* pSrcDst = ts->pDst;
    IppSizeL srcDstStep = ts->dstStep;
    IppiSizeL roiSize = ts->roiSize;
    int scaleFactor = ts->scaleFactor;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;

    const Ipp8u *pSrcRoi;
    Ipp8u       *pSrcDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_8u_AC4 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pSrcDstRoi = owniGetImagePointer_8u_AC4 (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y);

    return ippiAdd_8u_AC4IRSfs_L (pSrcRoi, srcStep, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_8u_AC4IRSfs_LT, (const Ipp8u* pSrc, IppSizeL srcStep, Ipp8u* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp8u) * 4;

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   minTileSize = IPP_MIN (IPP64_MIN_ADD_2D / pixelSize, IPP_MAX_32S / pixelSize);

    if (pSrc == 0 || pSrcDst == 0)     return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    owniSplitUniform2D_LT (roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiAdd_8u_AC4IRSfs_L (pSrc, srcStep, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmetics_8u_LT_Str ts;
        simpleArithmeticsThreadingStructureEncode_8u ((Ipp8u*)pSrc, srcStep, (Ipp8u*)0, (IppSizeL)0, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiAdd_8u_AC4IRSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiAdd_16u_C1IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmetics_16u_LT_Str *ts = (ippiSimpleArithmetics_16u_LT_Str *)arg;
    const Ipp16u* pSrc = (const Ipp16u*)ts->pSrc1;
    IppSizeL srcStep = ts->src1Step;
    Ipp16u* pSrcDst = ts->pDst;
    IppSizeL srcDstStep = ts->dstStep;
    IppiSizeL roiSize = ts->roiSize;
    int scaleFactor = ts->scaleFactor;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;

    const Ipp16u *pSrcRoi;
    Ipp16u       *pSrcDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);
    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_16u_C1 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pSrcDstRoi = owniGetImagePointer_16u_C1 (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y);

    return ippiAdd_16u_C1IRSfs_L (pSrcRoi, srcStep, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_16u_C1IRSfs_LT, (const Ipp16u* pSrc, IppSizeL srcStep, Ipp16u* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp16u);

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   minTileSize = IPP_MIN (IPP64_MIN_ADD_2D / pixelSize, IPP_MAX_32S / pixelSize);

    if (pSrc == 0 || pSrcDst == 0)              return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    owniSplitUniform2D_LT (roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiAdd_16u_C1IRSfs_L (pSrc, srcStep, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmetics_16u_LT_Str ts;
        simpleArithmeticsThreadingStructureEncode_16u ((Ipp16u*)pSrc, srcStep, (Ipp16u*)0, (IppSizeL)0, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiAdd_16u_C1IRSfs_LT_Fun);
    }

    return status;
}

IPPFUN (IppStatus, ippiAdd_16u_C3IRSfs_LT, (const Ipp16u* pSrc, IppSizeL srcStep, Ipp16u* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize, int scaleFactor))
{
    roiSize.width *= 3;
    return ippiAdd_16u_C1IRSfs_LT (pSrc, srcStep, pSrcDst, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_16u_C4IRSfs_LT, (const Ipp16u* pSrc, IppSizeL srcStep, Ipp16u* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize, int scaleFactor))
{
    roiSize.width *= 4;
    return ippiAdd_16u_C1IRSfs_LT (pSrc, srcStep, pSrcDst, srcDstStep, roiSize, scaleFactor);
}

IppStatus ippiAdd_16u_AC4IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmetics_16u_LT_Str *ts = (ippiSimpleArithmetics_16u_LT_Str *)arg;
    const Ipp16u* pSrc = (const Ipp16u*)ts->pSrc1;
    IppSizeL srcStep = ts->src1Step;
    Ipp16u* pSrcDst = ts->pDst;
    IppSizeL srcDstStep = ts->dstStep;
    IppiSizeL roiSize = ts->roiSize;
    int scaleFactor = ts->scaleFactor;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;

    const Ipp16u *pSrcRoi;
    Ipp16u       *pSrcDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_16u_AC4 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pSrcDstRoi = owniGetImagePointer_16u_AC4 (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y);

    return ippiAdd_16u_AC4IRSfs_L (pSrcRoi, srcStep, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_16u_AC4IRSfs_LT, (const Ipp16u* pSrc, IppSizeL srcStep, Ipp16u* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp16u) * 4;

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   minTileSize = IPP_MIN (IPP64_MIN_ADD_2D / pixelSize, IPP_MAX_32S / pixelSize);

    if (pSrc == 0 || pSrcDst == 0)     return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    owniSplitUniform2D_LT (roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiAdd_16u_AC4IRSfs_L (pSrc, srcStep, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmetics_16u_LT_Str ts;
        simpleArithmeticsThreadingStructureEncode_16u ((Ipp16u*)pSrc, srcStep, (Ipp16u*)0, (IppSizeL)0, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiAdd_16u_AC4IRSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiAdd_16s_C1IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmetics_16s_LT_Str *ts = (ippiSimpleArithmetics_16s_LT_Str *)arg;
    const Ipp16s* pSrc = (const Ipp16s*)ts->pSrc1;
    IppSizeL srcStep = ts->src1Step;
    Ipp16s* pSrcDst = ts->pDst;
    IppSizeL srcDstStep = ts->dstStep;
    IppiSizeL roiSize;
    roiSize.width = ts->roiSize.width;
    roiSize.height = ts->roiSize.height;
    int scaleFactor = ts->scaleFactor;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;

    const Ipp16s *pSrcRoi;
    Ipp16s       *pSrcDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);
    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_16s_C1 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pSrcDstRoi = owniGetImagePointer_16s_C1 (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y);

    return ippiAdd_16s_C1IRSfs_L (pSrcRoi, srcStep, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_16s_C1IRSfs_LT, (const Ipp16s* pSrc, IppSizeL srcStep, Ipp16s* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp16s);

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   minTileSize = IPP_MIN (IPP64_MIN_ADD_2D / pixelSize, IPP_MAX_32S / pixelSize);

    if (pSrc == 0 || pSrcDst == 0)              return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    owniSplitUniform2D_LT (roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiAdd_16s_C1IRSfs_L (pSrc, srcStep, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmetics_16s_LT_Str ts;
        simpleArithmeticsThreadingStructureEncode_16s ((Ipp16s*)pSrc, srcStep, (Ipp16s*)0, (IppSizeL)0, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiAdd_16s_C1IRSfs_LT_Fun);
    }

    return status;
}

IPPFUN (IppStatus, ippiAdd_16s_C3IRSfs_LT, (const Ipp16s* pSrc, IppSizeL srcStep, Ipp16s* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize, int scaleFactor))
{
    roiSize.width *= 3;
    return ippiAdd_16s_C1IRSfs_LT (pSrc, srcStep, pSrcDst, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_16s_C4IRSfs_LT, (const Ipp16s* pSrc, IppSizeL srcStep, Ipp16s* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize, int scaleFactor))
{
    roiSize.width *= 4;
    return ippiAdd_16s_C1IRSfs_LT (pSrc, srcStep, pSrcDst, srcDstStep, roiSize, scaleFactor);
}

IppStatus ippiAdd_16s_AC4IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmetics_16s_LT_Str *ts = (ippiSimpleArithmetics_16s_LT_Str *)arg;
    const Ipp16s* pSrc = (const Ipp16s*)ts->pSrc1;
    IppSizeL srcStep = ts->src1Step;
    Ipp16s* pSrcDst = ts->pDst;
    IppSizeL srcDstStep = ts->dstStep;
    IppiSizeL roiSize = ts->roiSize;
    int scaleFactor = ts->scaleFactor;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;

    const Ipp16s *pSrcRoi;
    Ipp16s       *pSrcDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_16s_AC4 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pSrcDstRoi = owniGetImagePointer_16s_AC4 (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y);

    return ippiAdd_16s_AC4IRSfs_L (pSrcRoi, srcStep, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiAdd_16s_AC4IRSfs_LT, (const Ipp16s* pSrc, IppSizeL srcStep, Ipp16s* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp16s) * 4;

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   minTileSize = IPP_MIN (IPP64_MIN_ADD_2D / pixelSize, IPP_MAX_32S / pixelSize);

    if (pSrc == 0 || pSrcDst == 0)     return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    owniSplitUniform2D_LT (roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiAdd_16s_AC4IRSfs_L (pSrc, srcStep, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmetics_16s_LT_Str ts;
        simpleArithmeticsThreadingStructureEncode_16s ((Ipp16s*)pSrc, srcStep, (Ipp16s*)0, (IppSizeL)0, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiAdd_16s_AC4IRSfs_LT_Fun);
    }

    return status;
}

/* ////////////// -32f_CXR////////////////////// */

IppStatus ippiAdd_32f_C1R_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmetics_32f_LT_Str *ts = (ippiSimpleArithmetics_32f_LT_Str *)arg;
    const Ipp32f *pSrc1 = (const Ipp32f *)ts->pSrc1;
    IppSizeL src1Step = ts->src1Step;
    const Ipp32f *pSrc2 = (const Ipp32f *)ts->pSrc2;
    IppSizeL src2Step = ts->src2Step;
    Ipp32f *pDst = ts->pDst;
    IppSizeL dstStep = ts->dstStep;
    IppiSizeL roiSize = ts->roiSize;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;
    Ipp32s nCh = (Ipp32s)ts->nCh;

    const Ipp32f *pSrc1Roi, *pSrc2Roi;
    Ipp32f       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrc1Roi = owniGetImagePointer_32f (pSrc1, src1Step, roiOffset.x, roiOffset.y, nCh);
    pSrc2Roi = owniGetImagePointer_32f (pSrc2, src2Step, roiOffset.x, roiOffset.y, nCh);
    pDstRoi = owniGetImagePointer_32f (pDst, dstStep, roiOffset.x, roiOffset.y, nCh);

    return ippiAdd_32f_C1R_L (pSrc1Roi, src1Step, pSrc2Roi, src2Step, pDstRoi, dstStep, roiSize);
}

IPPFUN (IppStatus, ippiAdd_32f_C1R_LT, (const Ipp32f* pSrc1, IppSizeL src1Step, const Ipp32f* pSrc2,
                                        IppSizeL src2Step, Ipp32f* pDst, IppSizeL dstStep, IppiSizeL roiSize))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp32f);
    Ipp32s nCh = 1;

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   minTileSize = IPP_MIN (IPP64_MIN_ADD_2D / pixelSize, IPP_MAX_32S / pixelSize);

    if (pSrc1 == 0 || pSrc2 == 0 || pDst == 0)     return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    owniSplitUniform2D_LT (roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiAdd_32f_C1R_L (pSrc1, src1Step, pSrc2, src2Step, pDst, dstStep, roiSize);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmetics_32f_LT_Str ts;
        simpleArithmeticsThreadingStructureEncode_32f ((Ipp32f *)pSrc1, src1Step, (Ipp32f *)pSrc2, src2Step, pDst, dstStep, roiSize, splitImage, tileSize, tailSize, nCh, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiAdd_32f_C1R_LT_Fun);
    }

    return status;
}
IPPFUN (IppStatus, ippiAdd_32f_C3R_LT, (const Ipp32f* pSrc1, IppSizeL src1Step, const Ipp32f* pSrc2,
                                        IppSizeL src2Step, Ipp32f* pDst, IppSizeL dstStep, IppiSizeL roiSize))
{
    roiSize.width *= 3;
    return ippiAdd_32f_C1R_LT (pSrc1, src1Step, pSrc2, src2Step, pDst, dstStep, roiSize);
}

IPPFUN (IppStatus, ippiAdd_32f_C4R_LT, (const Ipp32f* pSrc1, IppSizeL src1Step, const Ipp32f* pSrc2,
                                        IppSizeL src2Step, Ipp32f* pDst, IppSizeL dstStep, IppiSizeL roiSize))
{
    roiSize.width *= 4;
    return ippiAdd_32f_C1R_LT (pSrc1, src1Step, pSrc2, src2Step, pDst, dstStep, roiSize);
}

IppStatus ippiAdd_32f_AC4R_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmetics_32f_LT_Str *ts = (ippiSimpleArithmetics_32f_LT_Str *)arg;
    const Ipp32f *pSrc1 = (const Ipp32f *)ts->pSrc1;
    IppSizeL src1Step = ts->src1Step;
    const Ipp32f *pSrc2 = (const Ipp32f *)ts->pSrc2;
    IppSizeL src2Step = ts->src2Step;
    Ipp32f *pDst = ts->pDst;
    IppSizeL dstStep = ts->dstStep;
    IppiSizeL roiSize = ts->roiSize;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;
    Ipp32s nCh = (Ipp32s)ts->nCh;

    const Ipp32f *pSrc1Roi, *pSrc2Roi;
    Ipp32f       *pDstRoi;
    IppiPointL    roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrc1Roi = owniGetImagePointer_32f (pSrc1, src1Step, roiOffset.x, roiOffset.y, (int)nCh);
    pSrc2Roi = owniGetImagePointer_32f (pSrc2, src2Step, roiOffset.x, roiOffset.y, (int)nCh);
    pDstRoi = owniGetImagePointer_32f (pDst, dstStep, roiOffset.x, roiOffset.y, (int)nCh);
    return ippiAdd_32f_AC4R_L (pSrc1Roi, src1Step, pSrc2Roi, src2Step, pDstRoi, dstStep, roiSize);
}

IPPFUN (IppStatus, ippiAdd_32f_AC4R_LT, (const Ipp32f* pSrc1, IppSizeL src1Step, const Ipp32f* pSrc2,
                                         IppSizeL src2Step, Ipp32f* pDst, IppSizeL dstStep, IppiSizeL roiSize))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0, nCh = 4;
    IppSizeL pixelSize = sizeof (Ipp32f) * 4;

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   minTileSize = IPP_MIN (IPP64_MIN_ADD_2D / pixelSize, IPP_MAX_32S / pixelSize);

    if (pSrc1 == 0 || pSrc2 == 0 || pDst == 0)     return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    owniSplitUniform2D_LT (roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiAdd_32f_AC4R_L (pSrc1, src1Step, pSrc2, src2Step, pDst, dstStep, roiSize);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmetics_32f_LT_Str ts;
        simpleArithmeticsThreadingStructureEncode_32f ((Ipp32f *)pSrc1, src1Step, (Ipp32f *)pSrc2, src2Step, pDst, dstStep, roiSize, splitImage, tileSize, tailSize, (Ipp32s)nCh, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiAdd_32f_AC4R_LT_Fun);
    }

    return status;
}
/* //////////////////////////Add_32f_CXIR////////////////////////////////////// */

IppStatus ippiAdd_32f_C1IR_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmetics_32f_LT_Str *ts = (ippiSimpleArithmetics_32f_LT_Str *)arg;
    const Ipp32f *pSrc = (const Ipp32f*)ts->pSrc1;
    IppSizeL srcStep = ts->src1Step;
    Ipp32f *pSrcDst = ts->pDst;
    IppSizeL srcDstStep = ts->dstStep;
    IppiSizeL roiSize = ts->roiSize;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;
    Ipp32s nCh = (Ipp32s)ts->nCh;

    const Ipp32f *pSrcRoi;
    Ipp32f       *pSrcDstRoi;
    IppiPointL    roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_32f (pSrc, srcStep, roiOffset.x, roiOffset.y, nCh);
    pSrcDstRoi = owniGetImagePointer_32f (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y, nCh);
    return ippiAdd_32f_C1IR_L (pSrcRoi, srcStep, pSrcDstRoi, srcDstStep, roiSize);
}

IPPFUN (IppStatus, ippiAdd_32f_C1IR_LT, (const Ipp32f* pSrc, IppSizeL srcStep, Ipp32f* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0, nCh = 1;
    IppSizeL pixelSize = sizeof (Ipp32f);

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL minTileSize = IPP_MIN (IPP64_MIN_ADD_2D / pixelSize, IPP_MAX_32S / pixelSize);

    if (pSrc == 0 || pSrcDst == 0)              return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    owniSplitUniform2D_LT (roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiAdd_32f_C1IR_L (pSrc, srcStep, pSrcDst, srcDstStep, roiSize);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmetics_32f_LT_Str ts;
        simpleArithmeticsThreadingStructureEncode_32f ((Ipp32f*)pSrc, srcStep, (Ipp32f*)0, (IppSizeL)0, pSrcDst, srcDstStep, roiSize, splitImage, tileSize, tailSize, nCh, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiAdd_32f_C1IR_LT_Fun);
    }

    return status;
}
IPPFUN (IppStatus, ippiAdd_32f_C3IR_LT, (const Ipp32f* pSrc, IppSizeL srcStep, Ipp32f* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize))
{
    roiSize.width *= 3;
    return ippiAdd_32f_C1IR_LT (pSrc, srcStep, pSrcDst, srcDstStep, roiSize);
}

IPPFUN (IppStatus, ippiAdd_32f_C4IR_LT, (const Ipp32f* pSrc, IppSizeL srcStep, Ipp32f* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize))
{
    roiSize.width *= 4;
    return ippiAdd_32f_C1IR_LT (pSrc, srcStep, pSrcDst, srcDstStep, roiSize);
}

IppStatus ippiAdd_32f_AC4IR_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmetics_32f_LT_Str *ts = (ippiSimpleArithmetics_32f_LT_Str *)arg;
    const Ipp32f* pSrc = (const Ipp32f*)ts->pSrc1;
    IppSizeL srcStep = ts->src1Step;
    Ipp32f* pSrcDst = ts->pDst;
    IppSizeL srcDstStep = ts->dstStep;
    IppiSizeL roiSize = ts->roiSize;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;
    Ipp32s nCh = (Ipp32s)ts->nCh;

    const Ipp32f *pSrcRoi;
    Ipp32f       *pSrcDstRoi;
    IppiPointL    roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_32f (pSrc, srcStep, roiOffset.x, roiOffset.y, nCh);
    pSrcDstRoi = owniGetImagePointer_32f (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y, nCh);

    return ippiAdd_32f_AC4IR_L (pSrcRoi, srcStep, pSrcDstRoi, srcDstStep, roiSize);
}

IPPFUN (IppStatus, ippiAdd_32f_AC4IR_LT, (const Ipp32f* pSrc, IppSizeL srcStep, Ipp32f* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0, nCh = 4;
    IppSizeL pixelSize = sizeof (Ipp32f) * nCh;

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   minTileSize = IPP_MIN (IPP64_MIN_ADD_2D / pixelSize, IPP_MAX_32S / pixelSize);

    if (pSrc == 0 || pSrcDst == 0)     return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    owniSplitUniform2D_LT (roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiAdd_32f_AC4IR_L (pSrc, srcStep, pSrcDst, srcDstStep, roiSize);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmetics_32f_LT_Str ts;
        simpleArithmeticsThreadingStructureEncode_32f ((Ipp32f*)pSrc, srcStep, (Ipp32f*)0, (IppSizeL)0, pSrcDst, srcDstStep, roiSize, splitImage, tileSize, tailSize, nCh, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiAdd_32f_AC4IR_LT_Fun);
    }

    return status;
}
