#!/usr/bin/env python3

import sys
import datetime

# (C) 2018,2023 Jack Lloyd
# Botan is released under the Simplified BSD License (see license.txt)

# Used to generate src/lib/math/mp/mp_monty_n.cpp

def monty_redc_code(n):

    lines = []

    lines.append("word w2 = 0, w1 = 0, w0 = 0;")
    lines.append("w0 = z[0];")
    lines.append("ws[0] = w0 * p_dash;")

    lines.append("word3_muladd(&w2, &w1, &w0, ws[0], p[0]);")
    lines.append("w0 = w1;")
    lines.append("w1 = w2;")
    lines.append("w2 = 0;")

    for i in range(1, n):
        for j in range(0, i):
            lines.append("word3_muladd(&w2, &w1, &w0, ws[%d], p[%d]);" % (j, i-j))

        lines.append("word3_add(&w2, &w1, &w0, z[%d]);" % (i))
        lines.append("ws[%d] = w0 * p_dash;" % (i))

        lines.append("word3_muladd(&w2, &w1, &w0, ws[%d], p[0]);" % (i))
        lines.append("w0 = w1;")
        lines.append("w1 = w2;")
        lines.append("w2 = 0;")

    for i in range(0, n - 1):
        for j in range(i + 1, n):
            lines.append("word3_muladd(&w2, &w1, &w0, ws[%d], p[%d]);" % (j, n + i-j))

        lines.append("word3_add(&w2, &w1, &w0, z[%d]);" % (n+i))
        lines.append("ws[%d] = w0;" % (i))
        lines.append("w0 = w1;")
        lines.append("w1 = w2;")
        lines.append("w2 = 0;")

    lines.append("word3_add(&w2, &w1, &w0, z[%d]);" % (2*n-1));

    lines.append("ws[%d] = w0;" % (n - 1))
    lines.append("ws[%d] = w1;" % (n))

    lines.append("word borrow = bigint_sub3(z, ws, %d + 1, p, %d);" % (n, n))

    lines.append("CT::conditional_assign_mem(borrow, z, ws, %d);" % (n))
    lines.append("clear_mem(z + %d, %d);" % (n, n))

    for line in lines:
        print("   %s" % (line))

def main(args = None):
    if args is None:
        args = sys.argv

    if len(args) <= 1:
        sizes = [4, 6, 8, 16, 24, 32]
    else:
        sizes = map(int, args[1:])

    print("""/*
* This file was automatically generated by %s on %s
* All manual changes will be lost. Edit the script instead.
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/internal/mp_core.h>

#include <botan/internal/ct_utils.h>

namespace Botan {
""" % (sys.argv[0], datetime.date.today().strftime("%Y-%m-%d")))

    for n in sizes:
        print("void bigint_monty_redc_%d(word z[%d], const word p[%d], word p_dash, word ws[]) {" % (n, 2*n, n))

        monty_redc_code(n)

        print("}\n")

    print("}  // namespace Botan")

    return 0

if __name__ == '__main__':
    sys.exit(main())


