/*
Copyright (C) 2009 William Hart
This file is part of FLINT.
FLINT 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 .
*/
#ifndef FLINT_H
#define FLINT_H
#undef ulong
#define ulong ulongxx /* ensure vendor doesn't typedef ulong */
#if !defined(_MSC_VER)
#include /* for BSD define */
#endif
#include
#include
#include
#include
#include /* for alloca on FreeBSD */
#if (!defined(BSD) && !defined(__MINGW64__) && !defined(__MINGW32__) && !defined(_MSC_VER)) || defined(__GNU__)
/* MinGW and FreeBSD have alloca, but not alloca.h */
#include
#endif
#if defined(__MINGW32__)
#include /* for alloca on MinGW */
#endif
#include "limits.h"
#include "longlong.h"
#include "flint-config.h"
#undef ulong
#ifdef FLINT_INLINES_C
#define FLINT_INLINE FLINT_DLL
#else
#define FLINT_INLINE static __inline__
#endif
#if FLINT_USES_GC
#include "gc.h"
#endif
#if FLINT_WANT_ASSERT
#include
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* flint version number */
#define __FLINT_VERSION 2
#define __FLINT_VERSION_MINOR 8
#define __FLINT_VERSION_PATCHLEVEL 5
#define FLINT_VERSION "2.8.5"
#define __FLINT_RELEASE (__FLINT_VERSION * 10000 + \
__FLINT_VERSION_MINOR * 100 + \
__FLINT_VERSION_PATCHLEVEL)
/*
Check mpir and mpfr version numbers
*/
#if __GNU_MP_VERSION < 5
#error GMP 5.0.0 or MPIR 2.6.0 or later are required
#endif
#if MPFR_VERSION_MAJOR < 3
#error MPFR 3.0.0 or later is required
#endif
/*
We define alternative key words for "asm" and "inline", allowing
the code to be compiled with the "-ansi" flag under GCC
*/
#ifndef __GNUC__
#define __asm__ asm
#define __inline__ inline
#endif
extern char flint_version[];
#define ulong mp_limb_t
#define slong mp_limb_signed_t
FLINT_DLL void * flint_malloc(size_t size);
FLINT_DLL void * flint_realloc(void * ptr, size_t size);
FLINT_DLL void * flint_calloc(size_t num, size_t size);
FLINT_DLL void flint_free(void * ptr);
typedef void (*flint_cleanup_function_t)(void);
FLINT_DLL void flint_register_cleanup_function(flint_cleanup_function_t cleanup_function);
FLINT_DLL void flint_cleanup(void);
FLINT_DLL void flint_cleanup_master(void);
FLINT_DLL void __flint_set_memory_functions(void *(*alloc_func) (size_t),
void *(*calloc_func) (size_t, size_t), void *(*realloc_func) (void *, size_t),
void (*free_func) (void *));
#ifdef __GNUC__
#define FLINT_NORETURN __attribute__ ((noreturn))
#else
#define FLINT_NORETURN
#endif
FLINT_DLL FLINT_NORETURN void flint_abort(void);
FLINT_DLL void flint_set_abort(FLINT_NORETURN void (*func)(void));
/* flint_abort is calling abort by default
* if flint_set_abort is used, then instead of abort this function
* is called. EXPERIMENTALLY use at your own risk!
* May disappear in future versions.
*/
#if defined(_WIN64) || defined(__mips64)
#if defined(__MINGW64__)
#define WORD_FMT "%I64"
#define WORD_WIDTH_FMT "%*I64"
#else
#define WORD_FMT "%ll"
#define WORD_WIDTH_FMT "%*ll"
#endif
#define WORD(xx) (xx##LL)
#define UWORD(xx) (xx##ULL)
#ifndef FLINT_NO_WORDMAC
#define UWORD_MAX ULLONG_MAX
#define UWORD_MIN ULLONG_MIN
#define WORD_MAX LLONG_MAX
#define WORD_MIN LLONG_MIN
#endif
#else
#define WORD_FMT "%l"
#define WORD_WIDTH_FMT "%*l"
#define WORD(xx) (xx##L)
#define UWORD(xx) (xx##UL)
#ifndef FLINT_NO_WORDMAC
#define UWORD_MAX ULONG_MAX
#define UWORD_MIN ULONG_MIN
#define WORD_MAX LONG_MAX
#define WORD_MIN LONG_MIN
#endif
#endif
#if GMP_LIMB_BITS == 64
#define FLINT_BITS 64
#define FLINT_D_BITS 53
#define FLINT64 1
#else
#define FLINT_BITS 32
#define FLINT_D_BITS 31
#endif
#define flint_bitcnt_t ulong
#if FLINT_USES_TLS
#if __STDC_VERSION__ >= 201112L
#define FLINT_TLS_PREFIX _Thread_local
#elif defined(_MSC_VER)
#define FLINT_TLS_PREFIX __declspec(thread)
#elif defined(__GNUC__)
#define FLINT_TLS_PREFIX __thread
#else
#error "thread local prefix defined in C11 or later"
#endif
#else
#define FLINT_TLS_PREFIX
#endif
FLINT_DLL int flint_get_num_threads(void);
FLINT_DLL void flint_set_num_threads(int num_threads);
FLINT_DLL void _flint_set_num_workers(int num_workers);
FLINT_DLL int flint_set_num_workers(int num_workers);
FLINT_DLL void flint_reset_num_workers(int max_workers);
FLINT_DLL int flint_set_thread_affinity(int * cpus, slong length);
FLINT_DLL int flint_restore_thread_affinity();
int flint_test_multiplier(void);
typedef struct
{
gmp_randstate_t gmp_state;
int gmp_init;
mp_limb_t __randval;
mp_limb_t __randval2;
} flint_rand_s;
typedef flint_rand_s flint_rand_t[1];
FLINT_INLINE
void flint_randinit(flint_rand_t state)
{
state->gmp_init = 0;
#if FLINT64
state->__randval = UWORD(13845646450878251009);
state->__randval2 = UWORD(13142370077570254774);
#else
state->__randval = UWORD(4187301858);
state->__randval2 = UWORD(3721271368);
#endif
}
FLINT_INLINE
void flint_randseed(flint_rand_t state, ulong seed1, ulong seed2)
{
state->__randval = seed1;
state->__randval2 = seed2;
}
FLINT_INLINE
void flint_get_randseed(ulong * seed1, ulong * seed2, flint_rand_t state)
{
*seed1 = state->__randval;
*seed2 = state->__randval2;
}
FLINT_INLINE
void _flint_rand_init_gmp(flint_rand_t state)
{
if (!state->gmp_init)
{
gmp_randinit_default(state->gmp_state);
state->gmp_init = 1;
}
}
FLINT_INLINE
void flint_randclear(flint_rand_t state)
{
if (state->gmp_init)
gmp_randclear(state->gmp_state);
}
FLINT_INLINE
flint_rand_s * flint_rand_alloc(void)
{
return (flint_rand_s *) flint_malloc(sizeof(flint_rand_s));
}
FLINT_INLINE
void flint_rand_free(flint_rand_s * state)
{
flint_free(state);
}
#if FLINT_USES_GC
#define FLINT_GC_INIT() GC_init()
#else
#define FLINT_GC_INIT()
#endif
#define FLINT_TEST_INIT(xxx) \
flint_rand_t xxx; \
FLINT_GC_INIT(); \
flint_randinit(xxx)
#define FLINT_TEST_CLEANUP(xxx) \
flint_randclear(xxx); \
flint_cleanup_master();
/*
We define this here as there is no mpfr.h
*/
typedef __mpfr_struct flint_mpfr;
#if FLINT_WANT_ASSERT
#define FLINT_ASSERT(param) assert(param)
#else
#define FLINT_ASSERT(param)
#endif
#if defined(__GNUC__)
#define FLINT_UNUSED(x) UNUSED_ ## x __attribute__((unused))
#define FLINT_SET_BUT_UNUSED(x) x __attribute__((unused))
#if __GNUC__ >= 4
#define FLINT_WARN_UNUSED __attribute__((warn_unused_result))
#else
#define FLINT_WARN_UNUSED
#endif
#else
#define __attribute__(x)
#define FLINT_UNUSED(x) x
#define FLINT_SET_BUT_UNUSED(x) x
#define FLINT_WARN_UNUSED
#endif
#define FLINT_MAX(x, y) ((x) > (y) ? (x) : (y))
#define FLINT_MIN(x, y) ((x) > (y) ? (y) : (x))
#define FLINT_ABS(x) ((slong)(x) < 0 ? (-(x)) : (x))
#define FLINT_SIGN_EXT(x) (-(ulong)((slong)(x) < 0))
#define FLINT_SGN(x) ((0 < (slong)(x)) - ((slong)(x) < 0))
#define MP_PTR_SWAP(x, y) \
do { \
mp_limb_t * __txxx; \
__txxx = x; \
x = y; \
y = __txxx; \
} while (0)
#define SLONG_SWAP(A, B) \
do { \
slong __t_m_p_ = A; \
A = B; \
B = __t_m_p_; \
} while (0)
#define ULONG_SWAP(A, B) \
do { \
ulong __t_m_p_ = A; \
A = B; \
B = __t_m_p_; \
} while (0)
#define MP_LIMB_SWAP(A, B) \
do { \
mp_limb_t __t_m_p_ = A; \
A = B; \
B = __t_m_p_; \
} while (0)
#define DOUBLE_SWAP(A, B) \
do { \
double __t_m_p_ = A; \
A = B; \
B = __t_m_p_; \
} while (0)
#define r_shift(in, shift) \
((shift == FLINT_BITS) ? WORD(0) : ((in) >> (shift)))
#define l_shift(in, shift) \
((shift == FLINT_BITS) ? WORD(0) : ((in) << (shift)))
#ifdef NEED_CLZ_TAB
FLINT_DLL extern const unsigned char __flint_clz_tab[128];
#endif
/* Beware when using the unsigned return value in signed arithmetic */
static __inline__
mp_limb_t FLINT_BIT_COUNT(mp_limb_t x)
{
mp_limb_t zeros = FLINT_BITS;
if (x) count_leading_zeros(zeros, x);
return FLINT_BITS - zeros;
}
#define FLINT_FLOG2(k) (FLINT_BIT_COUNT(k) - 1)
#define FLINT_CLOG2(k) FLINT_BIT_COUNT((k) - 1)
#define flint_mpn_zero(xxx, nnn) \
do \
{ \
slong ixxx; \
for (ixxx = 0; ixxx < (nnn); ixxx++) \
(xxx)[ixxx] = UWORD(0); \
} while (0)
#define flint_mpn_copyi(xxx, yyy, nnn) \
do { \
slong ixxx; \
for (ixxx = 0; ixxx < (nnn); ixxx++) \
(xxx)[ixxx] = (yyy)[ixxx]; \
} while (0)
#define flint_mpn_copyd(xxx, yyy, nnn) \
do { \
slong ixxx; \
for (ixxx = nnn - 1; ixxx >= 0; ixxx--) \
(xxx)[ixxx] = (yyy)[ixxx]; \
} while (0)
#define flint_mpn_store(xxx, nnn, yyy) \
do \
{ \
slong ixxx; \
for (ixxx = 0; ixxx < nnn; ixxx++) \
(xxx)[ixxx] = yyy; \
} while (0)
/* common usage of flint_malloc */
#define FLINT_ARRAY_ALLOC(n, T) (T *) flint_malloc((n)*sizeof(T))
#define FLINT_ARRAY_REALLOC(p, n, T) (T *) flint_realloc(p, (n)*sizeof(T))
/* temporary allocation */
#define TMP_INIT \
typedef struct __tmp_struct { \
void * block; \
struct __tmp_struct * next; \
} __tmp_t; \
__tmp_t * __tmp_root; \
__tmp_t * __tpx
#define TMP_START \
__tmp_root = NULL
#if FLINT_WANT_ASSERT
#define TMP_ALLOC(size) \
(__tpx = (__tmp_t *) alloca(sizeof(__tmp_t)), \
__tpx->next = __tmp_root, \
__tmp_root = __tpx, \
__tpx->block = flint_malloc(size))
#else
#define TMP_ALLOC(size) \
(((size) > 8192) ? \
(__tpx = (__tmp_t *) alloca(sizeof(__tmp_t)), \
__tpx->next = __tmp_root, \
__tmp_root = __tpx, \
__tpx->block = flint_malloc(size)) : \
alloca(size))
#endif
#define TMP_ARRAY_ALLOC(n, T) (T *) TMP_ALLOC((n)*sizeof(T))
#define TMP_END \
while (__tmp_root) { \
flint_free(__tmp_root->block); \
__tmp_root = __tmp_root->next; \
}
/* compatibility between gmp and mpir */
#ifndef mpn_com_n
#define mpn_com_n mpn_com
#endif
#ifndef mpn_neg_n
#define mpn_neg_n mpn_neg
#endif
#ifndef mpn_tdiv_q
/* substitute for mpir's mpn_tdiv_q */
static __inline__ void
mpn_tdiv_q(mp_ptr qp, mp_srcptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn)
{
mp_ptr _scratch;
TMP_INIT;
TMP_START;
_scratch = (mp_ptr) TMP_ALLOC(dn * sizeof(mp_limb_t));
mpn_tdiv_qr(qp, _scratch, 0, np, nn, dp, dn);
TMP_END;
}
#endif
/* Newton iteration macros */
#define FLINT_NEWTON_INIT(from, to) \
{ \
slong __steps[FLINT_BITS], __i, __from, __to; \
__steps[__i = 0] = __to = (to); \
__from = (from); \
while (__to > __from) \
__steps[++__i] = (__to = (__to + 1) / 2); \
#define FLINT_NEWTON_BASECASE(bc_to) { slong bc_to = __to;
#define FLINT_NEWTON_END_BASECASE }
#define FLINT_NEWTON_LOOP(step_from, step_to) \
{ \
for (__i--; __i >= 0; __i--) \
{ \
slong step_from = __steps[__i+1]; \
slong step_to = __steps[__i]; \
#define FLINT_NEWTON_END_LOOP }}
#define FLINT_NEWTON_END }
FLINT_DLL int parse_fmt(int * floating, const char * fmt);
FLINT_DLL int flint_printf(const char * str, ...); /* flint version of printf */
FLINT_DLL int flint_vprintf(const char * str, va_list ap); /* va_list version of flint_printf */
FLINT_DLL int flint_fprintf(FILE * f, const char * str, ...); /* flint version of fprintf */
FLINT_DLL int flint_sprintf(char * s, const char * str, ...); /* flint version of sprintf */
FLINT_DLL int flint_scanf(const char * str, ...); /* flint version of scanf */
FLINT_DLL int flint_fscanf(FILE * f, const char * str, ...); /* flint version of fscanf */
FLINT_DLL int flint_sscanf(const char * s, const char * str, ...); /* flint version of sscanf */
FLINT_INLINE slong flint_mul_sizes(slong x, slong y)
{
ulong hi, lo;
umul_ppmm(hi, lo, (ulong) x, (ulong) y);
if (hi != 0 || lo > WORD_MAX)
{
flint_printf("Exception (flint). Overflow creating size %wd x %wd object.\n", x, y);
flint_abort();
}
return lo;
}
#include "gmpcompat.h"
#include "exception.h"
#ifdef __cplusplus
}
#endif
#endif