#ifndef _SMALLJAC_INTERNAL_
#define _SMALLJAC_INTERNAL_
#include "gmp.h"
#include "smalljac.h"
#include "ffpoly.h"
#define SMALLJAC_MAX_BAD_PRIMES 32
#define SMALLJAC_MAX_FACTOR_BITS 64
#define SMALLJAC_SMALL_INTERVAL 1000
#define SMALLJAC_SPECIAL_X6PA 1
#define SMALLJAC_QCURVE_DELTA 0x1
#define SMALLJAC_QCURVE_WS 0x2
#define SMALLJAC_QCURVE_2G 0x4
#define SMALLJAC_GROUP_FLAG 0x1000
typedef struct smalljac_Qcurve_struct {
mpz_t f[SMALLJAC_MAX_DEGREE+1];
mpz_t Deltas[SMALLJAC_MAX_DEGREE+1];
mpz_t denom;
mpz_t disc;
mpz_t D;
int f_inits;
int Delta_inits;
int degree;
int genus;
unsigned flags;
unsigned ws2;
unsigned ws3;
long a[SMALLJAC_MAX_GENUS];
int n;
int special;
unsigned long pts;
unsigned long p;
char str[1024];
} smalljac_Qcurve;
int padic_charpoly(long a[], long f[], int n, unsigned long p);
int smalljac_internal_Lpoly (long a[], smalljac_Qcurve *qc, unsigned long p, unsigned long flags);
unsigned long smalljac_pointcount (smalljac_Qcurve *qc, unsigned long p);
int smalljac_padic_Lpoly (long a[], smalljac_Qcurve *qc, unsigned long p, unsigned long flags);
int smalljac_generic_Lpoly (long a[], smalljac_Qcurve *qc, unsigned long p, unsigned long pts, unsigned long flags);
int smalljac_tiny_Lpoly (long a[], smalljac_Qcurve *qc, int p, unsigned long flags);
int smalljac_x6pa_Lpoly (long a[], smalljac_Qcurve *qc, long p, unsigned long flags);
int smalljac_Lpoly_extend (long a[], int n, unsigned long p, int h);
int smalljac_Qcurve_set_str (smalljac_Qcurve *qc, char *str, int *err);
int smalljac_Qcurve_set_mpz (smalljac_Qcurve *qc, mpz_t f[], int degree, mpz_t denom, mpz_t disc, char *str);
int smalljac_Qcurve_set_i (smalljac_Qcurve *qc, long f[], int degree, char *str);
smalljac_Qcurve *smalljac_Qcurve_alloc ();
static inline void smalljac_Qcurve_init_f (smalljac_Qcurve *qc, int degree)
{ qc->degree = degree; qc->genus = (degree-1)>>1; while ( qc->f_inits <= qc->degree ) mpz_init (qc->f[qc->f_inits++]); }
static inline void smalljac_Qcurve_init_Deltas(smalljac_Qcurve *qc)
{ while ( qc->Delta_inits <= qc->degree ) mpz_init (qc->Deltas[qc->Delta_inits++]); }
static inline int smalljac_Qcurve_reduce (ff_t f[], smalljac_Qcurve *qc)
{ return ff_poly_set_rational_mpz (f, qc->f, qc->degree, qc->denom); }
static inline int smalljac_Qcurve_degree (smalljac_Qcurve *qc)
{ return qc->degree; }
static inline int smalljac_Qcurve_special (smalljac_Qcurve *qc)
{ return qc->special; }
void smalljac_init (void);
static inline unsigned long smalljac_Lp1_ui (long a[], int genus, unsigned long p)
{
switch (genus) {
case 1: return (unsigned long)((long)(p+1)+a[0]);
case 2: return (unsigned long)((long)(p*p+1)+(long)(p+1)*a[0]+a[1]);
case 3: return (unsigned long)((long)(p*p*p+1)+(long)(p*p+1)*a[0]+(long)(p+1)*a[1]+a[2]);
default: printf ("unhandled genus %d\n", genus); exit (0);
}
}
static inline int smalljac_last_Lpoly (long a[], smalljac_Qcurve *qc)
{ register int i; for ( i = 0 ; i < qc->n ; i++ ) a[i] = qc->a[i]; return qc->n; }
static inline unsigned long smalljac_last_p (smalljac_Qcurve *qc)
{ return qc->p; }
static inline unsigned long smalljac_last_pts (smalljac_Qcurve *qc)
{ return qc->pts; }
#endif