/*******************************************************************************
* 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 Subtraction operation
//   Contents:
//       ippiSubC_8u_C1RSfs_LT
//       ippiSubC_8u_C3RSfs_LT
//       ippiSubC_8u_C4RSfs_LT
//       ippiSubC_16u_C1RSfs_LT
//       ippiSubC_16u_C3RSfs_LT
//       ippiSubC_16u_C4RSfs_LT
//       ippiSubC_16s_C1RSfs_LT
//       ippiSubC_16s_C3RSfs_LT
//       ippiSubC_16s_C4RSfs_LT
//       ippiSubC_32f_C1R_LT
//       ippiSubC_32f_C3R_LT
//       ippiSubC_32f_C4R_LT
//       ippiSubC_8u_C1IRSfs_LT
//       ippiSubC_8u_C3IRSfs_LT
//       ippiSubC_8u_C4IRSfs_LT
//       ippiSubC_16u_C1IRSfs_LT
//       ippiSubC_16u_C3IRSfs_LT
//       ippiSubC_16u_C4IRSfs_LT
//       ippiSubC_16s_C1IRSfs_LT
//       ippiSubC_16s_C3IRSfs_LT
//       ippiSubC_16s_C4IRSfs_LT
//       ippiSubC_32f_C1IR_LT
//       ippiSubC_32f_C3IR_LT
//       ippiSubC_32f_C4IR_LT
*/

#include "pisimplearithmc_tl.h"

IppStatus ippiSubC_8u_C1RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_C1_8u_LT_Str *ts = (ippiSimpleArithmeticsC_C1_8u_LT_Str *)arg;
    const Ipp8u* pSrc = (const Ipp8u *)ts->pSrc;
    IppSizeL srcStep = ts->srcStep;
    Ipp8u value = ts->value;
    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 *pSrcRoi;
    Ipp8u       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_8u_C1 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_8u_C1 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_8u_C1RSfs_L (pSrcRoi, srcStep, value, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_8u_C1RSfs_LT, (const Ipp8u* pSrc, IppSizeL srcStep, Ipp8u value, 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 = IPP_MIN (IPP64_MIN_ADD_2D / pixelSize, IPP_MAX_32S / pixelSize);

    if (pSrc == 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 = ippiSubC_8u_C1RSfs_L (pSrc, srcStep, value, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_C1_8u_LT_Str ts;
        simpleArithmeticsC_C1_ThreadingStructureEncode_8u ((Ipp8u *)pSrc, srcStep, value, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_8u_C1RSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_8u_C3RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_8u_LT_Str *ts = (ippiSimpleArithmeticsC_CX_8u_LT_Str *)arg;
    const Ipp8u* pSrc = (const Ipp8u *)ts->pSrc;
    IppSizeL srcStep = ts->srcStep;
    const Ipp8u value[3] = {ts->value[0], ts->value[1], ts->value[2]};
    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 *pSrcRoi;
    Ipp8u       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_8u_C3 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_8u_C3 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_8u_C3RSfs_L (pSrcRoi, srcStep, value, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_8u_C3RSfs_LT, (const Ipp8u* pSrc, IppSizeL srcStep, const Ipp8u value[3], Ipp8u* pDst, IppSizeL dstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp8u) * 3;

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

    if (pSrc == 0 || pDst == 0 || value == 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 = ippiSubC_8u_C3RSfs_L (pSrc, srcStep, value, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_8u_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_8u ((Ipp8u *)pSrc, srcStep, (Ipp8u *)value, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_8u_C3RSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_8u_C4RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_8u_LT_Str *ts = (ippiSimpleArithmeticsC_CX_8u_LT_Str *)arg;
    const Ipp8u* pSrc = (const Ipp8u *)ts->pSrc;
    IppSizeL srcStep = ts->srcStep;
    const Ipp8u value[4] = {ts->value[0], ts->value[1], ts->value[2], ts->value[3]};
    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 *pSrcRoi;
    Ipp8u       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_8u_C4 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_8u_C4 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_8u_C4RSfs_L (pSrcRoi, srcStep, value, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_8u_C4RSfs_LT, (const Ipp8u* pSrc, IppSizeL srcStep, const Ipp8u value[4], 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 (pSrc == 0 || pDst == 0 || value == 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 = ippiSubC_8u_C4RSfs_L (pSrc, srcStep, value, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_8u_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_8u ((Ipp8u *)pSrc, srcStep, (Ipp8u *)value, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_8u_C4RSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_8u_AC4RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_8u_LT_Str *ts = (ippiSimpleArithmeticsC_CX_8u_LT_Str *)arg;
    const Ipp8u* pSrc = (const Ipp8u *)ts->pSrc;
    IppSizeL srcStep = ts->srcStep;
    const Ipp8u value[4] = {ts->value[0], ts->value[1], ts->value[2], ts->value[3]};
    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 *pSrcRoi;
    Ipp8u       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_8u_AC4 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_8u_AC4 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_8u_AC4RSfs_L (pSrcRoi, srcStep, value, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_8u_AC4RSfs_LT, (const Ipp8u* pSrc, IppSizeL srcStep, const Ipp8u value[4], 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 (pSrc == 0 || pDst == 0 || value == 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 = ippiSubC_8u_AC4RSfs_L (pSrc, srcStep, value, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_8u_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_8u ((Ipp8u *)pSrc, srcStep, (Ipp8u *)value, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_8u_AC4RSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_16u_C1RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_C1_16u_LT_Str *ts = (ippiSimpleArithmeticsC_C1_16u_LT_Str *)arg;
    const Ipp16u* pSrc = (const Ipp16u *)ts->pSrc;
    IppSizeL srcStep = ts->srcStep;
    Ipp16u value = ts->value;
    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 *pSrcRoi;
    Ipp16u       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_16u_C1 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_16u_C1 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_16u_C1RSfs_L (pSrcRoi, srcStep, value, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_16u_C1RSfs_LT, (const Ipp16u* pSrc, IppSizeL srcStep, Ipp16u value, 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 = IPP_MIN (IPP64_MIN_ADD_2D / pixelSize, IPP_MAX_32S / pixelSize);

    if (pSrc == 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 = ippiSubC_16u_C1RSfs_L (pSrc, srcStep, value, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_C1_16u_LT_Str ts;
        simpleArithmeticsC_C1_ThreadingStructureEncode_16u ((Ipp16u *)pSrc, srcStep, value, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_16u_C1RSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_16u_C3RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_16u_LT_Str *ts = (ippiSimpleArithmeticsC_CX_16u_LT_Str *)arg;
    const Ipp16u* pSrc = (const Ipp16u *)ts->pSrc;
    IppSizeL srcStep = ts->srcStep;
    const Ipp16u value[3] = {ts->value[0], ts->value[1], ts->value[2]};
    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 *pSrcRoi;
    Ipp16u       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_16u_C3 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_16u_C3 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_16u_C3RSfs_L (pSrcRoi, srcStep, value, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_16u_C3RSfs_LT, (const Ipp16u* pSrc, IppSizeL srcStep, const Ipp16u value[3], Ipp16u* pDst, IppSizeL dstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp16u) * 3;

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

    if (pSrc == 0 || pDst == 0 || value == 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 = ippiSubC_16u_C3RSfs_L (pSrc, srcStep, value, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_16u_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_16u ((Ipp16u *)pSrc, srcStep, (Ipp16u *)value, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_16u_C3RSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_16u_C4RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_16u_LT_Str *ts = (ippiSimpleArithmeticsC_CX_16u_LT_Str *)arg;
    const Ipp16u* pSrc = (const Ipp16u *)ts->pSrc;
    IppSizeL srcStep = ts->srcStep;
    const Ipp16u value[4] = {ts->value[0], ts->value[1], ts->value[2], ts->value[3]};
    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 *pSrcRoi;
    Ipp16u       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_16u_C4 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_16u_C4 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_16u_C4RSfs_L (pSrcRoi, srcStep, value, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_16u_C4RSfs_LT, (const Ipp16u* pSrc, IppSizeL srcStep, const Ipp16u value[4], 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 (pSrc == 0 || pDst == 0 || value == 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 = ippiSubC_16u_C4RSfs_L (pSrc, srcStep, value, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_16u_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_16u ((Ipp16u *)pSrc, srcStep, (Ipp16u *)value, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_16u_C4RSfs_LT_Fun);
    }
    return status;
}

IppStatus ippiSubC_16u_AC4RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_16u_LT_Str *ts = (ippiSimpleArithmeticsC_CX_16u_LT_Str *)arg;
    const Ipp16u* pSrc = (const Ipp16u *)ts->pSrc;
    IppSizeL srcStep = ts->srcStep;
    const Ipp16u value[4] = {ts->value[0], ts->value[1], ts->value[2], ts->value[3]};
    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 *pSrcRoi;
    Ipp16u       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_16u_AC4 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_16u_AC4 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_16u_AC4RSfs_L (pSrcRoi, srcStep, value, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_16u_AC4RSfs_LT, (const Ipp16u* pSrc, IppSizeL srcStep, const Ipp16u value[4], 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 (pSrc == 0 || pDst == 0 || value == 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 = ippiSubC_16u_AC4RSfs_L (pSrc, srcStep, value, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_16u_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_16u ((Ipp16u *)pSrc, srcStep, (Ipp16u *)value, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_16u_AC4RSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_16s_C1RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_C1_16s_LT_Str *ts = (ippiSimpleArithmeticsC_C1_16s_LT_Str *)arg;
    const Ipp16s* pSrc = (const Ipp16s *)ts->pSrc;
    IppSizeL srcStep = ts->srcStep;
    Ipp16s value = ts->value;
    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 *pSrcRoi;
    Ipp16s       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_16s_C1 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_16s_C1 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_16s_C1RSfs_L (pSrcRoi, srcStep, value, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_16s_C1RSfs_LT, (const Ipp16s* pSrc, IppSizeL srcStep, Ipp16s value, 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 = IPP_MIN (IPP64_MIN_ADD_2D / pixelSize, IPP_MAX_32S / pixelSize);

    if (pSrc == 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 = ippiSubC_16s_C1RSfs_L (pSrc, srcStep, value, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_C1_16s_LT_Str ts;
        simpleArithmeticsC_C1_ThreadingStructureEncode_16s ((Ipp16s *)pSrc, srcStep, value, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_16s_C1RSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_16s_C3RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_16s_LT_Str *ts = (ippiSimpleArithmeticsC_CX_16s_LT_Str *)arg;
    const Ipp16s* pSrc = (const Ipp16s *)ts->pSrc;
    IppSizeL srcStep = ts->srcStep;
    const Ipp16s value[3] = {ts->value[0], ts->value[1], ts->value[2]};
    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 *pSrcRoi;
    Ipp16s       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_16s_C3 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_16s_C3 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_16s_C3RSfs_L (pSrcRoi, srcStep, value, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_16s_C3RSfs_LT, (const Ipp16s* pSrc, IppSizeL srcStep, const Ipp16s value[3], Ipp16s* pDst, IppSizeL dstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp16s) * 3;

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

    if (pSrc == 0 || pDst == 0 || value == 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 = ippiSubC_16s_C3RSfs_L (pSrc, srcStep, value, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_16s_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_16s ((Ipp16s *)pSrc, srcStep, (Ipp16s *)value, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_16s_C3RSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_16s_C4RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_16s_LT_Str *ts = (ippiSimpleArithmeticsC_CX_16s_LT_Str *)arg;
    const Ipp16s* pSrc = (const Ipp16s *)ts->pSrc;
    IppSizeL srcStep = ts->srcStep;
    const Ipp16s value[4] = {ts->value[0], ts->value[1], ts->value[2], ts->value[3]};
    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 *pSrcRoi;
    Ipp16s       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_16s_C4 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_16s_C4 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_16s_C4RSfs_L (pSrcRoi, srcStep, value, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_16s_C4RSfs_LT, (const Ipp16s* pSrc, IppSizeL srcStep, const Ipp16s value[4], 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 (pSrc == 0 || pDst == 0 || value == 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 = ippiSubC_16s_C4RSfs_L (pSrc, srcStep, value, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_16s_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_16s ((Ipp16s *)pSrc, srcStep, (Ipp16s *)value, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_16s_C4RSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_16s_AC4RSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_16s_LT_Str *ts = (ippiSimpleArithmeticsC_CX_16s_LT_Str *)arg;
    const Ipp16s* pSrc = (const Ipp16s *)ts->pSrc;
    IppSizeL srcStep = ts->srcStep;
    const Ipp16s value[4] = {ts->value[0], ts->value[1], ts->value[2], ts->value[3]};
    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 *pSrcRoi;
    Ipp16s       *pDstRoi;
    IppiPointL   roiOffset;
    owniGetTileParamsByIndex_LT (i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_16s_AC4 (pSrc, srcStep, roiOffset.x, roiOffset.y);
    pDstRoi = owniGetImagePointer_16s_AC4 (pDst, dstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_16s_AC4RSfs_L (pSrcRoi, srcStep, value, pDstRoi, dstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_16s_AC4RSfs_LT, (const Ipp16s* pSrc, IppSizeL srcStep, const Ipp16s value[4], 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 (pSrc == 0 || pDst == 0 || value == 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 = ippiSubC_16s_AC4RSfs_L (pSrc, srcStep, value, pDst, dstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_16s_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_16s ((Ipp16s *)pSrc, srcStep, (Ipp16s *)value, pDst, dstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_16s_AC4RSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_8u_C1IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_C1_8u_LT_Str *ts = (ippiSimpleArithmeticsC_C1_8u_LT_Str *)arg;
    Ipp8u value = ts->value;
    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;

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

    /* compute pointers to ROIs */
    pSrcDstRoi = owniGetImagePointer_8u_C1 (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y);
    return ippiSubC_8u_C1IRSfs_L (value, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_8u_C1IRSfs_LT, (Ipp8u value, 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 (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 = ippiSubC_8u_C1IRSfs_L (value, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_C1_8u_LT_Str ts;
        simpleArithmeticsC_C1_ThreadingStructureEncode_8u ((Ipp8u *)0, (IppSizeL)0, value, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_8u_C1IRSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_8u_C3IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_8u_LT_Str *ts = (ippiSimpleArithmeticsC_CX_8u_LT_Str *)arg;
    const Ipp8u value[3] = {ts->value[0], ts->value[1], ts->value[2]};
    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;

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

    /* compute pointers to ROIs */
    pSrcDstRoi = owniGetImagePointer_8u_C3 (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_8u_C3IRSfs_L (value, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_8u_C3IRSfs_LT, (const Ipp8u value[3], Ipp8u* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp8u) * 3;

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

    if (pSrcDst == 0 || value == 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 = ippiSubC_8u_C3IRSfs_L (value, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_8u_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_8u ((Ipp8u *)0, (IppSizeL)0, (Ipp8u *)value, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_8u_C3IRSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_8u_C4IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_8u_LT_Str *ts = (ippiSimpleArithmeticsC_CX_8u_LT_Str *)arg;
    const Ipp8u value[4] = {ts->value[0], ts->value[1], ts->value[2], ts->value[3]};
    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;

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

    /* compute pointers to ROIs */
    pSrcDstRoi = owniGetImagePointer_8u_C4 (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_8u_C4IRSfs_L (value, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_8u_C4IRSfs_LT, (const Ipp8u value[4], 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 (pSrcDst == 0 || value == 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 = ippiSubC_8u_C4IRSfs_L (value, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_8u_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_8u ((Ipp8u *)0, (IppSizeL)0, (Ipp8u *)value, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_8u_C4IRSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_8u_AC4IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_8u_LT_Str *ts = (ippiSimpleArithmeticsC_CX_8u_LT_Str *)arg;
    const Ipp8u value[4] = {ts->value[0], ts->value[1], ts->value[2], ts->value[3]};
    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;

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

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

    return ippiSubC_8u_AC4IRSfs_L (value, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_8u_AC4IRSfs_LT, (const Ipp8u value[4], 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 (pSrcDst == 0 || value == 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 = ippiSubC_8u_AC4IRSfs_L (value, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_8u_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_8u ((Ipp8u *)0, (IppSizeL)0, (Ipp8u *)value, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_8u_AC4IRSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_16u_C1IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_C1_16u_LT_Str *ts = (ippiSimpleArithmeticsC_C1_16u_LT_Str *)arg;
    Ipp16u value = ts->value;
    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;

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

    /* compute pointers to ROIs */
    pSrcDstRoi = owniGetImagePointer_16u_C1 (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y);
    return ippiSubC_16u_C1IRSfs_L (value, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_16u_C1IRSfs_LT, (Ipp16u value, 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 (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 = ippiSubC_16u_C1IRSfs_L (value, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_C1_16u_LT_Str ts;
        simpleArithmeticsC_C1_ThreadingStructureEncode_16u ((Ipp16u *)0, (IppSizeL)0, value, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_16u_C1IRSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_16u_C3IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_16u_LT_Str *ts = (ippiSimpleArithmeticsC_CX_16u_LT_Str *)arg;
    const Ipp16u value[3] = {ts->value[0], ts->value[1], ts->value[2]};
    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;

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

    /* compute pointers to ROIs */
    pSrcDstRoi = owniGetImagePointer_16u_C3 (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_16u_C3IRSfs_L (value, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_16u_C3IRSfs_LT, (const Ipp16u value[3], Ipp16u* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp16u) * 3;

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

    if (pSrcDst == 0 || value == 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 = ippiSubC_16u_C3IRSfs_L (value, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_16u_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_16u ((Ipp16u *)0, (IppSizeL)0, (Ipp16u *)value, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_16u_C3IRSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_16u_C4IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_16u_LT_Str *ts = (ippiSimpleArithmeticsC_CX_16u_LT_Str *)arg;
    const Ipp16u value[4] = {ts->value[0], ts->value[1], ts->value[2], ts->value[3]};
    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;

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

    /* compute pointers to ROIs */
    pSrcDstRoi = owniGetImagePointer_16u_C4 (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_16u_C4IRSfs_L (value, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_16u_C4IRSfs_LT, (const Ipp16u value[4], 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 (pSrcDst == 0 || value == 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 = ippiSubC_16u_C4IRSfs_L (value, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_16u_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_16u ((Ipp16u *)0, (IppSizeL)0, (Ipp16u *)value, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_16u_C4IRSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_16u_AC4IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_16u_LT_Str *ts = (ippiSimpleArithmeticsC_CX_16u_LT_Str *)arg;
    const Ipp16u value[4] = {ts->value[0], ts->value[1], ts->value[2], ts->value[3]};
    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;

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

    /* compute pointers to ROIs */
    pSrcDstRoi = owniGetImagePointer_16u_AC4 (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y);
    return ippiSubC_16u_AC4IRSfs_L (value, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_16u_AC4IRSfs_LT, (const Ipp16u value[4], 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 (pSrcDst == 0 || value == 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 = ippiSubC_16u_AC4IRSfs_L (value, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_16u_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_16u ((Ipp16u *)0, (IppSizeL)0, (Ipp16u *)value, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_16u_AC4IRSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_16s_C1IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_C1_16s_LT_Str *ts = (ippiSimpleArithmeticsC_C1_16s_LT_Str *)arg;
    Ipp16s value = ts->value;
    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;

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

    /* compute pointers to ROIs */
    pSrcDstRoi = owniGetImagePointer_16s_C1 (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y);
    return ippiSubC_16s_C1IRSfs_L (value, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_16s_C1IRSfs_LT, (Ipp16s value, 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 (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 = ippiSubC_16s_C1IRSfs_L (value, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_C1_16s_LT_Str ts;
        simpleArithmeticsC_C1_ThreadingStructureEncode_16s ((Ipp16s *)0, (IppSizeL)0, value, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_16s_C1IRSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_16s_C3IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_16s_LT_Str *ts = (ippiSimpleArithmeticsC_CX_16s_LT_Str *)arg;
    const Ipp16s value[3] = {ts->value[0], ts->value[1], ts->value[2]};
    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;

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

    /* compute pointers to ROIs */
    pSrcDstRoi = owniGetImagePointer_16s_C3 (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_16s_C3IRSfs_L (value, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_16s_C3IRSfs_LT, (const Ipp16s value[3], Ipp16s* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize, int scaleFactor))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp16s) * 3;

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

    if (pSrcDst == 0 || value == 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 = ippiSubC_16s_C3IRSfs_L (value, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_16s_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_16s ((Ipp16s *)0, (IppSizeL)0, (Ipp16s *)value, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_16s_C3IRSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_16s_C4IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_16s_LT_Str *ts = (ippiSimpleArithmeticsC_CX_16s_LT_Str *)arg;
    const Ipp16s value[4] = {ts->value[0], ts->value[1], ts->value[2], ts->value[3]};
    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;

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

    /* compute pointers to ROIs */
    pSrcDstRoi = owniGetImagePointer_16s_C4 (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y);

    return ippiSubC_16s_C4IRSfs_L (value, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_16s_C4IRSfs_LT, (const Ipp16s value[4], 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 (pSrcDst == 0 || value == 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 = ippiSubC_16s_C4IRSfs_L (value, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_16s_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_16s ((Ipp16s *)0, (IppSizeL)0, (Ipp16s *)value, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_16s_C4IRSfs_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_16s_AC4IRSfs_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_16s_LT_Str *ts = (ippiSimpleArithmeticsC_CX_16s_LT_Str *)arg;
    const Ipp16s value[4] = {ts->value[0], ts->value[1], ts->value[2], ts->value[3]};
    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;

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

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

    return ippiSubC_16s_AC4IRSfs_L (value, pSrcDstRoi, srcDstStep, roiSize, scaleFactor);
}

IPPFUN (IppStatus, ippiSubC_16s_AC4IRSfs_LT, (const Ipp16s value[4], 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 (pSrcDst == 0 || value == 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 = ippiSubC_16s_AC4IRSfs_L (value, pSrcDst, srcDstStep, roiSize, scaleFactor);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_16s_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_16s ((Ipp16s *)0, (IppSizeL)0, (Ipp16s *)value, pSrcDst, srcDstStep, roiSize, scaleFactor, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_16s_AC4IRSfs_LT_Fun);
    }

    return status;
}

/* ////////////////////////////////// SubC_32f ////////////////////////////////////////////// */

IppStatus ippiSubC_32f_C1R_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_C1_32f_LT_Str *ts = (ippiSimpleArithmeticsC_C1_32f_LT_Str *)arg;
    const Ipp32f* pSrc = (const Ipp32f *)ts->pSrc;
    IppSizeL srcStep = ts->srcStep;
    Ipp32f value = ts->value;
    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 = ts->nCh;

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

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_32f (pSrc, srcStep, roiOffset.x, roiOffset.y, nCh);
    pDstRoi = owniGetImagePointer_32f (pDst, dstStep, roiOffset.x, roiOffset.y, nCh);

    return ippiSubC_32f_C1R_L (pSrcRoi, srcStep, value, pDstRoi, dstStep, roiSize);
}

IPPFUN (IppStatus, ippiSubC_32f_C1R_LT, (const Ipp32f* pSrc, IppSizeL srcStep, Ipp32f value, 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 (pSrc == 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 = ippiSubC_32f_C1R_L (pSrc, srcStep, value, pDst, dstStep, roiSize);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_C1_32f_LT_Str ts;
        simpleArithmeticsC_C1_ThreadingStructureEncode_32f ((Ipp32f *)pSrc, srcStep, value, pDst, dstStep, roiSize, splitImage, tileSize, tailSize, nCh, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_32f_C1R_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_32f_C3R_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_32f_LT_Str *ts = (ippiSimpleArithmeticsC_CX_32f_LT_Str *)arg;
    const Ipp32f* pSrc = (const Ipp32f *)ts->pSrc;
    IppSizeL srcStep = ts->srcStep;
    const Ipp32f value[3] = {ts->value[0], ts->value[1], ts->value[2]};
    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 = ts->nCh;

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

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_32f (pSrc, srcStep, roiOffset.x, roiOffset.y, nCh);
    pDstRoi = owniGetImagePointer_32f (pDst, dstStep, roiOffset.x, roiOffset.y, nCh);

    return ippiSubC_32f_C3R_L (pSrcRoi, srcStep, value, pDstRoi, dstStep, roiSize);
}

IPPFUN (IppStatus, ippiSubC_32f_C3R_LT, (const Ipp32f* pSrc, IppSizeL srcStep, const Ipp32f value[3], Ipp32f* pDst, IppSizeL dstStep, IppiSizeL roiSize))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp32f) * 3;
    Ipp32s nCh = 3;

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

    if (pSrc == 0 || pDst == 0 || value == 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 = ippiSubC_32f_C3R_L (pSrc, srcStep, value, pDst, dstStep, roiSize);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_32f_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_32f ((Ipp32f *)pSrc, srcStep, (Ipp32f *)value, pDst, dstStep, roiSize, splitImage, tileSize, tailSize, nCh, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_32f_C3R_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_32f_C4R_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_32f_LT_Str *ts = (ippiSimpleArithmeticsC_CX_32f_LT_Str *)arg;
    const Ipp32f* pSrc = (const Ipp32f *)ts->pSrc;
    IppSizeL srcStep = ts->srcStep;
    const Ipp32f value[4] = {ts->value[0], ts->value[1], ts->value[2], ts->value[3]};
    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 = ts->nCh;

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

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_32f (pSrc, srcStep, roiOffset.x, roiOffset.y, nCh);
    pDstRoi = owniGetImagePointer_32f (pDst, dstStep, roiOffset.x, roiOffset.y, nCh);

    return ippiSubC_32f_C4R_L (pSrcRoi, srcStep, value, pDstRoi, dstStep, roiSize);
}

IPPFUN (IppStatus, ippiSubC_32f_C4R_LT, (const Ipp32f* pSrc, IppSizeL srcStep, const Ipp32f value[4], Ipp32f* pDst, IppSizeL dstStep, IppiSizeL roiSize))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp32f) * 4;
    Ipp32s nCh = 4;

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

    if (pSrc == 0 || pDst == 0 || value == 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 = ippiSubC_32f_C4R_L (pSrc, srcStep, value, pDst, dstStep, roiSize);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_32f_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_32f ((Ipp32f *)pSrc, srcStep, (Ipp32f *)value, pDst, dstStep, roiSize, splitImage, tileSize, tailSize, nCh, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_32f_C4R_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_32f_AC4R_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_32f_LT_Str *ts = (ippiSimpleArithmeticsC_CX_32f_LT_Str *)arg;
    const Ipp32f* pSrc = (const Ipp32f *)ts->pSrc;
    IppSizeL srcStep = ts->srcStep;
    const Ipp32f value[4] = {ts->value[0], ts->value[1], ts->value[2], ts->value[3]};
    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 = ts->nCh;

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

    /* compute pointers to ROIs */
    pSrcRoi = owniGetImagePointer_32f (pSrc, srcStep, roiOffset.x, roiOffset.y, nCh);
    pDstRoi = owniGetImagePointer_32f (pDst, dstStep, roiOffset.x, roiOffset.y, nCh);

    return ippiSubC_32f_AC4R_L (pSrcRoi, srcStep, value, pDstRoi, dstStep, roiSize);
}

IPPFUN (IppStatus, ippiSubC_32f_AC4R_LT, (const Ipp32f* pSrc, IppSizeL srcStep, const Ipp32f value[4], Ipp32f* pDst, IppSizeL dstStep, IppiSizeL roiSize))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp32f) * 4;
    Ipp32s nCh = 4;

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

    if (pSrc == 0 || pDst == 0 || value == 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 = ippiSubC_32f_AC4R_L (pSrc, srcStep, value, pDst, dstStep, roiSize);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_32f_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_32f ((Ipp32f *)pSrc, srcStep, (Ipp32f *)value, pDst, dstStep, roiSize, splitImage, tileSize, tailSize, nCh, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_32f_AC4R_LT_Fun);
    }

    return status;
}

/* ////////////////////////////////// SubC_32f_CXI ////////////////////////////////////////////// */

IppStatus ippiSubC_32f_C1IR_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_C1_32f_LT_Str *ts = (ippiSimpleArithmeticsC_C1_32f_LT_Str *)arg;
    Ipp32f value = ts->value;
    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 = ts->nCh;

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

    /* compute pointers to ROIs */
    pSrcDstRoi = owniGetImagePointer_32f (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y, nCh);
    return ippiSubC_32f_C1IR_L (value, pSrcDstRoi, srcDstStep, roiSize);
}

IPPFUN (IppStatus, ippiSubC_32f_C1IR_LT, (Ipp32f value, Ipp32f* pSrcDst, IppSizeL srcDstStep, 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 (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 = ippiSubC_32f_C1IR_L (value, pSrcDst, srcDstStep, roiSize);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_C1_32f_LT_Str ts;
        simpleArithmeticsC_C1_ThreadingStructureEncode_32f ((Ipp32f *)0, (IppSizeL)0, value, pSrcDst, srcDstStep, roiSize, splitImage, tileSize, tailSize, nCh, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_32f_C1IR_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_32f_C3IR_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_32f_LT_Str *ts = (ippiSimpleArithmeticsC_CX_32f_LT_Str *)arg;
    const Ipp32f value[3] = {ts->value[0], ts->value[1], ts->value[2]};
    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 = ts->nCh;

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

    /* compute pointers to ROIs */
    pSrcDstRoi = owniGetImagePointer_32f (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y, nCh);
    return ippiSubC_32f_C3IR_L (value, pSrcDstRoi, srcDstStep, roiSize);
}

IPPFUN (IppStatus, ippiSubC_32f_C3IR_LT, (const Ipp32f value[3], Ipp32f* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp32f) * 3;
    Ipp32s nCh = 3;

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

    if (pSrcDst == 0 || value == 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 = ippiSubC_32f_C3IR_L (value, pSrcDst, srcDstStep, roiSize);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_32f_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_32f ((Ipp32f *)0, (IppSizeL)0, (Ipp32f *)value, pSrcDst, srcDstStep, roiSize, splitImage, tileSize, tailSize, nCh, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_32f_C3IR_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_32f_C4IR_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_32f_LT_Str *ts = (ippiSimpleArithmeticsC_CX_32f_LT_Str *)arg;
    const Ipp32f value[4] = {ts->value[0], ts->value[1], ts->value[2], ts->value[3]};
    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 = ts->nCh;

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

    /* compute pointers to ROIs */
    pSrcDstRoi = owniGetImagePointer_32f (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y, nCh);
    return ippiSubC_32f_C4IR_L (value, pSrcDstRoi, srcDstStep, roiSize);
}

IPPFUN (IppStatus, ippiSubC_32f_C4IR_LT, (const Ipp32f value[4], Ipp32f* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp32f) * 4;
    Ipp32s   nCh = 4;

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

    if (pSrcDst == 0 || value == 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 = ippiSubC_32f_C4IR_L (value, pSrcDst, srcDstStep, roiSize);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_32f_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_32f ((Ipp32f *)0, (IppSizeL)0, (Ipp32f *)value, pSrcDst, srcDstStep, roiSize, splitImage, tileSize, tailSize, nCh, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_32f_C4IR_LT_Fun);
    }

    return status;
}

IppStatus ippiSubC_32f_AC4IR_LT_Fun (IppSizeL i, void *arg)
{
    ippiSimpleArithmeticsC_CX_32f_LT_Str *ts = (ippiSimpleArithmeticsC_CX_32f_LT_Str *)arg;
    const Ipp32f value[4] = {ts->value[0], ts->value[1], ts->value[2], ts->value[3]};
    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 = ts->nCh;

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

    /* compute pointers to ROIs */
    pSrcDstRoi = owniGetImagePointer_32f (pSrcDst, srcDstStep, roiOffset.x, roiOffset.y, nCh);
    return ippiSubC_32f_AC4IR_L (value, pSrcDstRoi, srcDstStep, roiSize);
}

IPPFUN (IppStatus, ippiSubC_32f_AC4IR_LT, (const Ipp32f value[4], Ipp32f* pSrcDst, IppSizeL srcDstStep, IppiSizeL roiSize))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = sizeof (Ipp32f) * 4;
    Ipp32s nCh = 4;

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

    if (pSrcDst == 0 || value == 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 = ippiSubC_32f_AC4IR_L (value, pSrcDst, srcDstStep, roiSize);
    } else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiSimpleArithmeticsC_CX_32f_LT_Str ts;
        simpleArithmeticsC_CX_ThreadingStructureEncode_32f ((Ipp32f *)0, (IppSizeL)0, (Ipp32f *)value, pSrcDst, srcDstStep, roiSize, splitImage, tileSize, tailSize, nCh, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiSubC_32f_AC4IR_LT_Fun);
    }

    return status;
}
