/*************************************************************************
* Copyright (C) 2017 Intel Corporation
*
* Licensed under the Apache License,  Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 	http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law  or agreed  to  in  writing,  software
* distributed under  the License  is  distributed  on  an  "AS IS"  BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the  specific  language  governing  permissions  and
* limitations under the License.
*************************************************************************/

#if !defined(_GS_MOD_METHOD_H)
#define _GS_MOD_METHOD_H

//#include "owndefs.h"
#include "owncp.h"

#include "pcpbnuimpl.h"
//#include "gsmodstuff.h"

typedef struct _gsModEngine gsEngine;

/* clang-format off */
/* modular arith methods */
IPP_OWN_FUNPTR(BNU_CHUNK_T*, mod_encode, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pMA))
IPP_OWN_FUNPTR(BNU_CHUNK_T*, mod_decode, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pMA))
IPP_OWN_FUNPTR(BNU_CHUNK_T*, mod_red,    (BNU_CHUNK_T* pR,       BNU_CHUNK_T* pA, gsEngine* pMA))
IPP_OWN_FUNPTR(BNU_CHUNK_T*, mod_sqr,    (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pMA))
IPP_OWN_FUNPTR(BNU_CHUNK_T*, mod_mul,    (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pMA))
IPP_OWN_FUNPTR(BNU_CHUNK_T*, mod_add,    (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pMA))
IPP_OWN_FUNPTR(BNU_CHUNK_T*, mod_sub,    (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pMA))
IPP_OWN_FUNPTR(BNU_CHUNK_T*, mod_neg,    (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pMA))
IPP_OWN_FUNPTR(BNU_CHUNK_T*, mod_div2,   (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pMA))
IPP_OWN_FUNPTR(BNU_CHUNK_T*, mod_mul2,   (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pMA))
IPP_OWN_FUNPTR(BNU_CHUNK_T*, mod_mul3,   (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pMA))
/* clang-format on */

typedef struct _gsModMethod {
    mod_encode encode;
    mod_decode decode;
    mod_mul mul;
    mod_sqr sqr;
    mod_red red;
    mod_add add;
    mod_sub sub;
    mod_neg neg;
    mod_div2 div2;
    mod_mul2 mul2;
    mod_mul3 mul3;
} gsModMethod;

/* These functions should not be used, because they have non-constant execution time, see their safe analogues in pcpmask_ct.h */
#if 0
IPPCP_INLINE BNU_CHUNK_T cpIsZero(BNU_CHUNK_T x)
{  return x==0; }
IPPCP_INLINE BNU_CHUNK_T cpIsNonZero(BNU_CHUNK_T x)
{  return x!=0; }
IPPCP_INLINE BNU_CHUNK_T cpIsOdd(BNU_CHUNK_T x)
{  return x&1; }
IPPCP_INLINE BNU_CHUNK_T cpIsEven(BNU_CHUNK_T x)
{  return 1-cpIsOdd(x); }

/* dst[] = (flag)? src[] : dst[] */
IPPCP_INLINE void cpMaskMove_gs(BNU_CHUNK_T* dst, const BNU_CHUNK_T* src, int len, BNU_CHUNK_T moveFlag)
{
   BNU_CHUNK_T srcMask = 0-cpIsNonZero(moveFlag);
   BNU_CHUNK_T dstMask = ~srcMask;
   int n;
   for(n=0; n<len; n++)
      dst[n] = (src[n] & srcMask) ^  (dst[n] & dstMask);
}
#endif

/* common available pre-defined methods */
#define gsModArith OWNAPI(gsModArith)
IPP_OWN_DECL(gsModMethod*, gsModArith, (void))

/* available pre-defined methods for RSA */
#define gsModArithRSA OWNAPI(gsModArithRSA)
IPP_OWN_DECL(gsModMethod*, gsModArithRSA, (void))

/* available pre-defined methods for ippsMont* */
#define gsModArithMont OWNAPI(gsModArithMont)
IPP_OWN_DECL(gsModMethod*, gsModArithMont, (void))

/* available pre-defined methods for DLP * */
#define gsModArithDLP OWNAPI(gsModArithDLP)
IPP_OWN_DECL(gsModMethod*, gsModArithDLP, (void))

/* available pre-defined common methods for GF over prime * */
#define gsArithGFp OWNAPI(gsArithGFp)
IPP_OWN_DECL(gsModMethod*, gsArithGFp, (void))

/* ... and etc ... */

#endif /* _GS_MOD_METHOD_H */
