packages feed

KpqC-0.1.0: cbits/third_party/SMAUG-T/src/poly.c

// SPDX-License-Identifier: MIT

#include "poly.h"
#include "toomcook.h"
#include <string.h>

#if SMAUGT_MODE == SMAUGT_MODET
/*************************************************
 * Name:        flipabs
 *
 * Description: Computes |(x mod q) - Q/2|
 *
 * Arguments:   - uint16_t x: input coefficient
 *
 * Return: |(x mod q) - Q/2|
 **************************************************/
uint16_t flipabs(uint16_t x) {
    int16_t r, m;
    r = x - (SMAUGT_MODULUS_SCALED_Q_HALF);
    m = r >> 15;
    return (r + m) ^ m;
}

/*************************************************
 * Name:        d2_ecd
 *
 * Description: Convert 16-byte message to polynomial
 *
 * Arguments:   - poly *r: pointer to output polynomial
 *              - const uint8_t msg[SMAUGT_MSG_BYTES]: pointer to input message
 **************************************************/
void d2_ecd(poly *r, const uint8_t msg[SMAUGT_MSG_BYTES]) {
    unsigned int mask;
    for (size_t i = 0; i < SMAUGT_MSG_BYTES; i++) {
        for (size_t j = 0; j < 8; j++) {
            mask = (msg[i] >> j) & 1;
            mask = (mask * SMAUGT_MODULUS_SCALED_Q_HALF) &
                   SMAUGT_MODULUS_SCALED_Q_HALF;
            r->coeffs[8 * i + j] = mask;
            r->coeffs[8 * i + j + 128] = mask;
        }
    }
}

/*************************************************
 * Name:        d2_dcd
 *
 * Description: Convert polynomial to 16-byte message
 *
 * Arguments:   - uint8_t msg[SMAUGT_MSG_BYTES]: pointer to output message
 *              - const poly *x: pointer to input polynomial
 **************************************************/
void d2_dcd(uint8_t msg[SMAUGT_MSG_BYTES], const poly *x) {
    uint16_t t;
    for (size_t i = 0; i < SMAUGT_MSG_BYTES; i++)
        msg[i] = 0;

    for (size_t i = 0; i < SMAUGT_N / 2; i++) {
        t = flipabs(x->coeffs[i]);
        t += flipabs(x->coeffs[i + 128]);
        t = t - SMAUGT_MODULUS_SCALED_Q_HALF;
        t >>= 15;
        msg[i >> 3] |= t << (i & 7);
    }
}
#endif
/*************************************************
 * Name:        poly_add
 *
 * Description: Add two polynomials. no modular reduction is performed
 *
 * Arguments: - poly *r: pointer to output polynomial
 *            - const poly *a: pointer to first input polynomial
 *            - const poly *b: pointer to second input polynomial
 **************************************************/
static inline void poly_add(poly *r, const poly *a, const poly *b) {
    unsigned int i;
    for (i = 0; i < SMAUGT_N; i++)
        r->coeffs[i] = a->coeffs[i] + b->coeffs[i];
}

/*************************************************
 * Name:        poly_sub
 *
 * Description: Subtract two polynomials. no modular reduction is performed
 *
 * Arguments: - poly *r: pointer to output polynomial
 *            - const poly *a: pointer to first input polynomial
 *            - const poly *b: pointer to second input polynomial
 **************************************************/
static inline void poly_sub(poly *r, const poly *a, const poly *b) {
    unsigned int i;
    for (i = 0; i < SMAUGT_N; i++)
        r->coeffs[i] = a->coeffs[i] - b->coeffs[i];
}

#define vec_vec_mult SMAUGT_NAMESPACE(vec_vec_mult)
/*************************************************
 * Name:        vec_vec_mult
 *
 * Description: Multiply two vector of polynomials.
 *
 * Arguments:   - poly *r: pointer to output polynomial
 *              - const polyvec *a: pointer to input vector of polynomials
 *              - const polyvec *b: pointer to input vector of polynomials
 **************************************************/
void vec_vec_mult(poly *r, const polyvec *a, const polyvec *b) {
    unsigned int i;
    for (i = 0; i < SMAUGT_K; i++)
        poly_mul_acc(a->vec[i].coeffs, b->vec[i].coeffs, r->coeffs);
}

/*************************************************
 * Name:        vec_vec_mult_add
 *
 * Description: Multiply two vectors of polynomials and add the result to output
 *              polynomial
 *
 * Arguments:   - poly *r: pointer to output polynomial
 *              - const polyvec *a: pointer to input vector of polynomials
 *              - const polyvec *b: pointer to input vector of polynomials
 *              - uint8_t mod: modulus (16-SMAUGT_LOG_P) or (16-SMAUGT_LOG_Q)
 **************************************************/
void vec_vec_mult_add(poly *r, const polyvec *a, const polyvec *b,
                      uint8_t mod) {
    unsigned int i, j;
    polyvec al;
    poly res;

    for (i = 0; i < SMAUGT_K; ++i)
        for (j = 0; j < SMAUGT_N; ++j)
            al.vec[i].coeffs[j] = a->vec[i].coeffs[j] >> mod;

    memset(&res, 0, sizeof(poly));
    vec_vec_mult(&res, &al, b);
    for (j = 0; j < SMAUGT_N; ++j)
        res.coeffs[j] = (int16_t)((uint16_t)res.coeffs[j] << mod);

    poly_add(r, r, &res);
}

/*************************************************
 * Name:        matrix_vec_mult_add
 *
 * Description: Transpose the matrix of polynomial and multiply it with the
 *              vector of polynomials.
 *
 * Arguments:   - polyvec *r: pointer to output vector of polynomials
 *              - const polyvec a[SMAUGT_K]: pointer to input matrix of
 *              polynomials
 *              - const polyvec *b: pointer to input vector of polynomials
 **************************************************/
void matrix_vec_mult_add(polyvec *r, const polyvec a[SMAUGT_K],
                         const polyvec *b) {
    unsigned int i, j, k;
    polyvec at;

    for (i = 0; i < SMAUGT_K; ++i) {
        for (j = 0; j < SMAUGT_K; ++j)
            for (k = 0; k < SMAUGT_N; ++k)
                at.vec[j].coeffs[k] =
                    a[j].vec[i].coeffs[k] >> SMAUGT_MODULUS_16_LOG_Q;

        vec_vec_mult(&r->vec[i], &at, b);
        for (j = 0; j < SMAUGT_N; ++j)
            r->vec[i].coeffs[j] =
                (int16_t)((uint16_t)r->vec[i].coeffs[j]
                          << SMAUGT_MODULUS_16_LOG_Q);
    }
}

/*************************************************
 * Name:        matrix_vec_mult_sub
 *
 * Description: Multiply the matrix of polynomial with the vector of polynomial
 *              and subtract the result to output vector of polynomials.
 *
 * Arguments:   - polyvec *r: pointer to input/output vector of polynomials
 *              - const polyvec a[SMAUGT_K]: pointer to input matrix of
 *              polynomials
 *              - const polyvec *b: pointer to input vector of polynomials
 **************************************************/
void matrix_vec_mult_sub(polyvec *r, const polyvec a[SMAUGT_K],
                         const polyvec *b) {
    unsigned int i, j, k;
    polyvec al;
    poly res;

    for (i = 0; i < SMAUGT_K; ++i) {
        for (j = 0; j < SMAUGT_K; ++j)
            for (k = 0; k < SMAUGT_N; ++k)
                al.vec[j].coeffs[k] =
                    a[i].vec[j].coeffs[k] >> SMAUGT_MODULUS_16_LOG_Q;

        memset(&res, 0, sizeof(poly));
        vec_vec_mult(&res, &al, b);
        for (j = 0; j < SMAUGT_N; ++j)
            res.coeffs[j] =
                (int16_t)((uint16_t)res.coeffs[j]
                          << SMAUGT_MODULUS_16_LOG_Q);

        poly_sub(&r->vec[i], &r->vec[i], &res);
    }
}