/*============================================================================= This file is part of Antic. Antic is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . =============================================================================*/ /****************************************************************************** Copyright (C) 2012 William Hart ******************************************************************************/ #ifndef QFB_H #define QFB_H #include #include "flint/flint.h" #include "flint/fmpz.h" #ifdef __cplusplus extern "C" { #endif typedef struct qfb { fmpz_t a; fmpz_t b; fmpz_t c; } qfb; typedef qfb qfb_t[1]; typedef struct { qfb_t q; qfb_t q2; slong iter; } qfb_hash_t; static __inline__ void qfb_init(qfb_t q) { fmpz_init(q->a); fmpz_init(q->b); fmpz_init(q->c); } static __inline__ void qfb_clear(qfb_t q) { fmpz_clear(q->a); fmpz_clear(q->b); fmpz_clear(q->c); } static __inline__ int qfb_equal(qfb_t f, qfb_t g) { return (fmpz_equal(f->a, g->a) && fmpz_equal(f->b, g->b) && fmpz_equal(f->c, g->c)); } static __inline__ void qfb_set(qfb_t f, qfb_t g) { fmpz_set(f->a, g->a); fmpz_set(f->b, g->b); fmpz_set(f->c, g->c); } static __inline__ void qfb_discriminant(fmpz_t D, qfb_t f) { fmpz_t t; fmpz_init(t); fmpz_mul(t, f->a, f->c); fmpz_mul_2exp(t, t, 2); fmpz_mul(D, f->b, f->b); fmpz_sub(D, D, t); fmpz_clear(t); } static __inline__ void qfb_print(qfb_t q) { printf("("); fmpz_print(q->a); printf(", "); fmpz_print(q->b); printf(", "); fmpz_print(q->c); printf(")"); } static __inline__ void qfb_array_clear(qfb ** forms, slong num) { slong k; for (k = 0; k < num; k++) { fmpz_clear((*forms)[k].a); fmpz_clear((*forms)[k].b); fmpz_clear((*forms)[k].c); } flint_free(*forms); } qfb_hash_t * qfb_hash_init(slong depth); void qfb_hash_clear(qfb_hash_t * qhash, slong depth); void qfb_hash_insert(qfb_hash_t * qhash, qfb_t q, qfb_t q2, slong iter, slong depth); slong qfb_hash_find(qfb_hash_t * qhash, qfb_t q, slong depth); void qfb_reduce(qfb_t r, qfb_t f, fmpz_t D); int qfb_is_reduced(qfb_t r); slong qfb_reduced_forms(qfb ** forms, slong d); slong qfb_reduced_forms_large(qfb ** forms, slong d); void qfb_nucomp(qfb_t r, const qfb_t f, const qfb_t g, fmpz_t D, fmpz_t L); void qfb_nudupl(qfb_t r, const qfb_t f, fmpz_t D, fmpz_t L); void qfb_pow_ui(qfb_t r, qfb_t f, fmpz_t D, ulong exp); void qfb_pow(qfb_t r, qfb_t f, fmpz_t D, fmpz_t exp); void qfb_pow_with_root(qfb_t r, qfb_t f, fmpz_t D, fmpz_t e, fmpz_t L); static __inline__ void qfb_inverse(qfb_t r, qfb_t f) { qfb_set(r, f); if (fmpz_equal(f->a, f->c) || fmpz_equal(f->a, f->b)) return; fmpz_neg(r->b, r->b); } static __inline__ int qfb_is_principal_form(qfb_t f, fmpz_t D) { if (!fmpz_is_one(f->a)) return 0; if (fmpz_is_odd(D)) /* D = 1 mod 4 */ return fmpz_is_one(f->b); return fmpz_is_zero(f->b); /* D = 0 mod 4 */ } static __inline__ void qfb_principal_form(qfb_t f, fmpz_t D) { fmpz_set_ui(f->a, 1); if (fmpz_is_odd(D)) /* D = 1 mod 4 */ fmpz_set_ui(f->b, 1); else /* D = 0 mod 4 */ fmpz_set_ui(f->b, 0); fmpz_sub(f->c, f->b, D); fmpz_fdiv_q_2exp(f->c, f->c, 2); } static __inline__ int qfb_is_primitive(qfb_t f) { fmpz_t g; int res; fmpz_init(g); fmpz_gcd(g, f->a, f->b); fmpz_gcd(g, g, f->c); res = fmpz_is_pm1(g); fmpz_clear(g); return res; } void qfb_prime_form(qfb_t r, fmpz_t D, fmpz_t p); int qfb_exponent_element(fmpz_t exponent, qfb_t f, fmpz_t n, ulong B1, ulong B2_sqrt); int qfb_exponent(fmpz_t exponent, fmpz_t n, ulong B1, ulong B2_sqrt, slong c); int qfb_exponent_grh(fmpz_t exponent, fmpz_t n, ulong B1, ulong B2_sqrt); #ifdef __cplusplus } #endif #endif