/*
 * This file is part of the openHiTLS project.
 *
 * openHiTLS is licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include "hitls_build.h"
#ifdef HITLS_CRYPTO_MLDSA
#include "ml_dsa_local.h"

/*
 * ZETAS is NIST.FIPS.204 Zetas converted to Plantard domin
 * x = (zeta * (-2^(2l)) mod q) * (q^-1 mod 2^(2l))
 * quotient = round(x / 2^(2l))
 * x -= quotient * 2^(2l)
 */
static const int64_t ZETAS[MLDSA_N] = {
    0, -7863079302046539641, 8288750859434465318, 8279739258909364132, -7047040794213066872,
    -6347578587163640000, -6924180145725268194, -7046899919168219174, -1324408118892148701, 7797620831989026436,
    5904178785850661821, 4688259859699270849, 8287121991728413809, -2212704518869611853, 1227061261729813591,
    -2688021322530896626, -7418719789490536518, -8943480837399596562, 5862554612443318533, -3686116612931685950,
    -7757905075204854306, -955584044445420686, 1489291353023500565, -2940625686150849480, -7105112129106378910,
    3773459140737258754, 5401640080945135142, 3215292402497497299, -1414535130006039286, -7891419398959260151,
    6197707349998870964, 5026890449924500827, 7929103473456019385, 7006063765542992697, 6032408094250703243,
    -7894386579591364791, -6847447269734787653, 4625566062396893718, 8154954785590364077, 2553085041292559330,
    867587768384851536, 2044336828550855209, 2411314119206532932, -7718147496141743017, 4560453176433772522,
    -8846488369021956441, 7136139857734084411, 4745838131935615944, 7517156227077865544, 3872626367619735213,
    -1799537822884495125, -7868016532133936309, 8269343120834119164, -4261027670955141767, -3779386898483740798,
    -8694748336340379660, -6377488120122866896, 7026922076870754993, 1225736155839214932, 8519235639840753830,
    6421564399779590430, 4080546927952058835, 7365041995058412064, 4090694333526244587, 6764223135818434274,
    2812273112086566323, -5801130891717146429, 8478949779359463673, 9208323720540693186, -7093954385319926074,
    -6870828124834354041, -603253356108752072, 5522697969093398433, 4464237721975370487, 4264925947586786663,
    -8399069226585667376, 6188136651639530476, -6567816909229834223, -2442236191550602657, 9152669273135549468,
    3363536973128790573, 1062393742510884766, 2528834723025573555, -6520454278917522983, -1244989812359258915,
    373512572033065467, 5420264202108515975, -7339552416631281694, -9171020448899537885, -7678532993296055171,
    4375521662482532628, -7037694615456452403, 3821924558510018380, 518171432538469675, -7154149851748832310,
    7172426187645245390, -5677380969508746657, 3935571098595747306, -5263199532966211354, -4963043238192433167,
    7664936350295676563, -9207317784673577591, -2861559567230078939, -5199308297782628790, -2900436677262892115,
    5417937562695953212, 6682715916511162215, 1367289161840242547, 8587813171438098100, -2700092552936283754,
    6440225940876758934, 7427306563708518865, 2985776138024536712, -6109915782987846123, 5906340337320043689,
    -6116591939410081564, -7632929099871764412, 5090955577741567269, -1437971014419999306, -1010697003396931065,
    767795408490863417, -721650026612939317, 2225876335562871623, -5182033495408179814, -8405457029400480185,
    -4231210587244096173, -4923419930656442340, 3839960966595675223, 3858655525281480, -4260193426548934305,
    -5854073494508971959, -3204665141301799075, 5856017129893355044, -3918586851001296706, -130194955510181958,
    6102971083511369758, 2602320869466829805, 191959857985594581, 1401986245151715432, -8728322821638222451,
    -8709478583217267089, -5054766099423739081, -7230664811654314068, -8181639600726124134, -61219011676627791,
    1810554691626100264, 2221786556917136888, -5401996670902405876, -4357214510170059114, 3514880794746733204,
    -8709916616559840400, -8275231257474237793, -3709312569534889735, -7507248749314436028, 5895352083821923239,
    -8296104977010030305, -7816377023506951986, 1399848906580666763, -551274866905102975, -5404708515515724064,
    -9126642608599937249, -3901772093695178495, 4827034985909707919, -3801618741498768149, 5255328139835346226,
    -7950085050448023415, -590917984994275510, -7000732525564537623, 8248343934461509170, 5054110149996166988,
    2729258089564908746, -8449154707374175530, 7034234372167380821, 5817655094243266264, 2760688632773975632,
    -27331959873029170, 6599597438878444610, 312203312280832118, -196566912186629456, 5531586303954257883,
    -2982351113496677051, 1349842668004885439, -2884110580268589356, -4883228720595909230, -1009765907397390811,
    -4230640483546978145, 8893168635835786645, -7642623063895346636, 4488507850795537970, -4137935899346889835,
    -1802234259289783096, -4796278001508819088, -3573282305526407033, 4634097807300482433, -5226468566194749828,
    -4476760192758785397, 1290417611977490052, -2596531785592619712, 1162177297714569905, -6038721057197940712,
    -3251098876787145805, 4389239369974577228, 5483836267268615474, -3066583384452721770, 1118034982880574013,
    -2614739885139184687, -1595418687590483605, -4038108320691689791, -6677789692286644273, -744920823083718442,
    5828691773538053110, 6624974757504211970, -5751340368053788143, 9131496194129455597, 1649948335809421485,
    -8854766979079334448, 8761985353839095054, 5654836559987963476, -3556060331293775944, 3793124416528967106,
    3665652311494982061, 4464061628169310864, 2561280006792059016, -7416351327799034594, 8792960254324982667,
    -26147729027278208, -3016744434992697087, 6648406239573020500, 7403736407767438382, 472987963076146265,
    1200466694669659091, -1695873600429771055, 6835869101986367469, -2428650554413102774, 1118514838502086484,
    -1218828876296526235, 1893325383991850115, 7550981646049343298, 308701246712821374, -3332909857909870713,
    -4809746976499804470, 6875939247555234588, 5191185970978128699, -4827362960623493965, -6635258635778093928,
    -3779003894455561119, 6440749819949786311, -864415878703202583, -666966296313699269, 7772844433476437539,
    -8748527384710988397, -8306633185439819990, 4182342354889975161, -1721041807660842613, 2321088055326733810,
    -1610012461767674827,
};

// Algorithm 41 NTT(w)
void MLDSA_ComputesNTT(int32_t w[MLDSA_N])
{
    uint32_t m = 0;
    for (uint32_t len = MLDSA_N / 2; len > 0; len >>= 1) {
        for (uint32_t start = 0; start < MLDSA_N;) {
            m++;
            int64_t z = ZETAS[m];
            for (uint32_t j = start; j < start + len; ++j) {
                int32_t t = MLDSA_PlantardMulReduce((uint64_t)z * (uint64_t)w[j + len]);
                w[j + len] = w[j] - t;
                w[j] = w[j] + t;
            }
            start = start + 2 * len;
        }
    }
}

// Algorithm 42 NTT^−1(w)
void MLDSA_ComputesINVNTT(int32_t w[MLDSA_N])
{
    uint32_t m = MLDSA_N;
    for (uint32_t len = 1; len < MLDSA_N_HALF; len <<= 1) {
        for (uint32_t start = 0; start < MLDSA_N;) {
            m--;
            int64_t zeta = -ZETAS[m];
            for (uint32_t j = start; j < start + len; j++) {
                int32_t t = w[j];
                w[j] = t + w[j + len];
                w[j + len] = t - w[j + len];
                w[j + len] = MLDSA_PlantardMulReduce((uint64_t)zeta * (uint64_t)w[j + len]);
            }
            start = start + 2 * len;
        }
    }

    for (uint32_t j = 0; j < MLDSA_N_HALF; j++) {
        const int32_t t = w[j];
        w[j] = MLDSA_PlantardMulReduce((uint64_t)MLDSA_PLANTARD_8338439 * (uint64_t)(t + w[j + MLDSA_N_HALF]));
        w[j + MLDSA_N_HALF] = MLDSA_PlantardMulReduce((uint64_t)MLDSA_LAST_ROUND_ZETA *
                                                      (uint64_t)(t - w[j + MLDSA_N_HALF]));
    }
}

#endif