/* lsmul.h
 * Daniel S. Roche, January 2009
 * http://www.cs.uwaterloo.ca/~droche
 *
 * Header file for low-space multiplication routines
 *
 * See LICENSE.txt for copyright and permissions.
 */

#ifndef LSMUL_LSMUL_H
#define LSMUL_LSMUL_H

#include <assert.h>
#include <stdio.h>

typedef int lsmul_ele;

extern const lsmul_ele LSMUL_MAX_P;
#define LSMUL_READ_ELE "%d"
#define LSMUL_WRITE_ELE "%d"

// Functions to read in a polynomial from the given input stream.
// Integers are *not* reduced modulo p.
// Format: [a_0 a_1 a_2 ... a_n], from low- to high-degree coefficients

// Assume there is enough space in the given array.
// The return value is the size of the actual polynomial read in.
long read_poly_prealloc (FILE*, lsmul_ele*);

// Dynamically create an array and return a pointer to it.
// The integer sp points to will be set to the size of the polynomial.
lsmul_ele* read_poly (FILE*, long*);

// Writes the given polynomial to the given output stream.
// (same format as read_poly methods)
void write_poly (FILE*, const lsmul_ele*, long);

// Performs low-space classical/Karatsuba multiplication, as appropriate
void mul_ck (lsmul_ele*, const lsmul_ele*, long, 
	const lsmul_ele*, long, lsmul_ele);

// Performs low-space FFT-based multiplication.
// If n is the next power of two greater than (sa+sb-2),
// then the output array c must have space for at least n elements,
// 2^k must be at least n, and omega must be a 2^k-PRU in Z/pZ.
void mul_fft (lsmul_ele *c, const lsmul_ele *a, long sa,
	const lsmul_ele *b, long sb, lsmul_ele p, int k, lsmul_ele omega);

#endif
