#include <ctype.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <wchar.h>
#include "nmod_types.h"
#include "fmpz.h"
#include "fmpz_mod.h"
#include "fmpq_types.h"
#include "fmpq.h"
#include "arf_types.h"
#include "arb.h"
#include "acb.h"
#define STRING_SIZE(x) (sizeof(x) - 1)
#define STRING_LENGTH(x) (STRING_SIZE(x) / sizeof(char))
static inline void __arb_neg_readonly(arb_ptr op, arb_srcptr ip)
{
arf_ptr op_arf;
op->mid = ip->mid;
op->rad = ip->rad;
op_arf = &(op->mid);
if (arf_is_special(op_arf))
{
if (arf_is_pos_inf(op_arf))
{
ARF_EXP(op_arf) = ARF_EXP_NEG_INF;
}
else if (arf_is_neg_inf(op_arf))
{
ARF_EXP(op_arf) = ARF_EXP_POS_INF;
}
}
else
{
ARF_NEG(op_arf);
}
}
static char * __mag_get_str(mag_srcptr ip, slong digits)
{
arf_t ip_arf;
char * str;
arf_init(ip_arf);
arf_set_mag(ip_arf, ip);
str = arf_get_str(ip_arf, digits);
arf_clear(ip_arf);
return str;
}
static int __never_is(const void * FLINT_UNUSED(ip))
{
return 0;
}
static int __ulong_is_pm1(const void * ip)
{
return *((const ulong *) ip) == 1;
}
static int __arb_is_pm1(const void * ip)
{
return arb_is_one(ip) || arb_equal_si(ip, -1);
}
static int __acb_is_pm1(const void * ip)
{
return acb_is_one(ip) || acb_equal_si(ip, -1);
}
static int __ulong_is_zero(const void * ip)
{
return *((ulong *) ip) == 0;
}
static int __fmpz_is_neg(const void * ip)
{
return fmpz_sgn(ip) < 0;
}
static int __fmpq_is_neg(const void * ip)
{
return __fmpz_is_neg(fmpq_numref((const fmpq *) ip));
}
static int __acb_is_neg(const void * ip)
{
acb_srcptr zp = ip;
arb_srcptr realzp = acb_realref(zp), imagzp = acb_imagref(zp);
return (arb_is_zero(imagzp) && arb_is_negative(realzp))
|| (arb_is_zero(realzp) && arb_is_negative(imagzp));
}
typedef enum
{
ulong_type = 0,
fmpz_type,
fmpq_type,
arb_type,
acb_type,
slong_type,
mag_type,
arf_type
} flint_type_t;
static inline size_t flint_type_size_in_chars(flint_type_t type)
{
if (type == ulong_type)
return sizeof(ulong) / sizeof(char);
else if (type == fmpz_type)
return sizeof(fmpz) / sizeof(char);
else if (type == fmpq_type)
return sizeof(fmpq) / sizeof(char);
else if (type == arb_type)
return sizeof(arb_struct) / sizeof(char);
else if (type == acb_type)
return sizeof(acb_struct) / sizeof(char);
else if (type == slong_type)
return sizeof(slong) / sizeof(char);
else if (type == mag_type)
return sizeof(mag_struct) / sizeof(char);
else
return sizeof(arf_struct) / sizeof(char);
}
#define FLAG_NONE (0)
#define FLAG_NEG (1)
#define FLAG_PAREN (1 << 1)
#define FLAG_IS_NEG(flag) ((flag) & FLAG_NEG)
#define FLAG_IS_PAREN(flag) ((flag) & FLAG_PAREN)
static size_t __ulong_fprint(FILE *, const ulong *, int);
static size_t __slong_fprint(FILE *, const slong *, int);
static size_t __fmpz_fprint(FILE *, const fmpz *, int);
static size_t __fmpq_fprint(FILE *, const fmpq *, int);
static size_t __mpz_fprint(FILE *, mpz_srcptr);
static size_t __mpq_fprint(FILE *, mpq_srcptr);
static size_t __mag_fprint(FILE *, mag_srcptr, int);
static size_t __arf_fprint(FILE *, arf_srcptr, int);
static size_t __arb_fprint(FILE *, arb_srcptr, int);
static size_t __acb_fprint(FILE *, acb_srcptr, int);
static size_t __nmod_fprint(FILE *, nmod_t);
static size_t __fmpz_mod_ctx_fprint(FILE *, const fmpz_mod_ctx_struct *);
static size_t __flint_vec_fprint(FILE *, const void *, slong, flint_type_t);
static size_t __flint_mat_fprint(FILE *, const void *, flint_type_t);
static size_t __flint_poly_fprint(FILE *, const void *, flint_type_t);
#define IS_FLINT_BASE_TYPE(ip, str) (memcmp(ip, str, sizeof(str) - sizeof(char)) == 0)
#define IS_FLINT_TYPE(ip, str) (memcmp(ip, str "}", sizeof(str)) == 0)
#define IS_PRINTF_FLAG(chr) \
( (chr) == '-' \
|| (chr) == '+' \
|| (chr) == ' ' \
|| (chr) == '#' \
|| (chr) == '0')
#define JUMP_FLAGS(str) \
do \
{ \
(str)++; \
} while (IS_PRINTF_FLAG(*(str)))
#define JUMP_MINIMAL_FIELD_WIDTH_WITH_POP(str, vlist) \
do \
{ \
if (isdigit(*(str))) \
{ \
(str)++; \
while (isdigit(*(str))) \
(str)++; \
} \
else if (*(str) == '*') \
{ \
va_arg((vlist), int); \
(str)++; \
} \
} while (0)
#define JUMP_PRECISION_WITH_POP(str, vlist) \
do \
{ \
if (*(str) == '.') \
{ \
(str)++; \
if (isdigit(*(str))) \
{ \
(str)++; \
while (isdigit(*(str))) \
(str)++; \
} \
else if (*(str) == '*') \
{ \
va_arg((vlist), int); \
(str)++; \
} \
} \
} while (0)
#define _IS_PRINTF_INTEGERFMT(chr) \
( (chr) == 'd' || (chr) == 'i' \
|| (chr) == 'o' \
|| (chr) == 'x' || (chr) == 'X' \
|| (chr) == 'u')
#define _IS_PRINTF_FLOATFMT(chr) \
( (chr) == 'f' || (chr) == 'F' \
|| (chr) == 'e' || (chr) == 'E' \
|| (chr) == 'a' || (chr) == 'A' \
|| (chr) == 'g' || (chr) == 'G')
#define IS_PRINTF_CHARFMT(str) \
((str)[0] == 'h' && (str)[1] == 'h' && _IS_PRINTF_INTEGERFMT((str)[2]))
#define IS_PRINTF_SHORTFMT(str) \
((str)[0] == 'h' && _IS_PRINTF_INTEGERFMT((str)[1]))
#define IS_PRINTF_INTFMT(str) \
((str)[0] == 'c' || _IS_PRINTF_INTEGERFMT((str)[0]))
#define IS_PRINTF_LONGFMT(str) \
((str)[0] == 'l' && _IS_PRINTF_INTEGERFMT((str)[1]))
#define IS_PRINTF_LONGLONGFMT(str) \
((str)[0] == 'l' && (str)[1] == 'l' && _IS_PRINTF_INTEGERFMT((str)[2]))
#define IS_PRINTF_INTMAXFMT(str) \
((str)[0] == 'j' && _IS_PRINTF_INTEGERFMT((str)[1]))
#define IS_PRINTF_SIZEFMT(str) \
((str)[0] == 'z' && _IS_PRINTF_INTEGERFMT((str)[1]))
#define IS_PRINTF_PTRDIFFFMT(str) \
((str)[0] == 't' && _IS_PRINTF_INTEGERFMT((str)[1]))
#define IS_FLINT_PRINTF_ULONGFMT(str) \
((str)[0] == 'w' && _IS_PRINTF_INTEGERFMT((str)[1]))
#define IS_PRINTF_DOUBLEFMT(str) \
(_IS_PRINTF_FLOATFMT((str)[0]) \
|| ((str)[0] == 'l' && _IS_PRINTF_FLOATFMT((str)[1])))
#define IS_PRINTF_LONGDOUBLEFMT(str) \
((str)[0] == 'L' && _IS_PRINTF_FLOATFMT((str)[1]))
#define IS_PRINTF_POINTERFMT(str) \
((str)[0] == 'p')
#define IS_PRINTF_CHARPFMT(str) \
((str)[0] == 's')
#define IS_PRINTF_WINTFMT(str) \
((str)[0] == 'l' && (str)[1] == 'c')
#define IS_PRINTF_WCHARPFMT(str) \
((str)[0] == 'l' && (str)[1] == 's')
int flint_vfprintf(FILE * fs, const char * ip, va_list vlist)
{
size_t iplen;
const char * ipcur;
char * op, * opcur;
size_t res;
va_list vlist_cpy;
int tmp;
TMP_INIT;
res = 0;
iplen = strlen(ip);
TMP_START;
#if FLINT_LONG_LONG
op = TMP_ALLOC(sizeof(char) * (iplen + iplen / 3 + 1));
#else
op = TMP_ALLOC(sizeof(char) * (iplen + 1));
#endif
opcur = op;
while (1)
{
continue_while_from_flint_type:
ipcur = ip;
va_copy(vlist_cpy, vlist);
continue_while:
ipcur = strchr(ipcur, '%');
if (ipcur == NULL)
break;
if (ipcur[1] == '%')
{
ipcur += 2;
goto continue_while;
}
if (ipcur[1] == '{')
goto print_flint_type;
JUMP_FLAGS(ipcur);
JUMP_MINIMAL_FIELD_WIDTH_WITH_POP(ipcur, vlist);
JUMP_PRECISION_WITH_POP(ipcur, vlist);
if (IS_FLINT_PRINTF_ULONGFMT(ipcur))
{
size_t cpsz;
ipcur += 2;
cpsz = ipcur - ip;
memcpy(opcur, ip, sizeof(char) * cpsz);
ip = ipcur;
#if FLINT_LONG_LONG
opcur += cpsz + 1;
opcur[-1] = opcur[-2];
opcur[-2] = 'l';
opcur[-3] = 'l';
#else
opcur += cpsz;
opcur[-2] = 'l';
#endif
va_arg(vlist, ulong);
}
else if (IS_PRINTF_INTFMT(ipcur)
|| IS_PRINTF_CHARFMT(ipcur)
|| IS_PRINTF_SHORTFMT(ipcur))
va_arg(vlist, int);
else if (IS_PRINTF_DOUBLEFMT(ipcur))
va_arg(vlist, double);
else if (IS_PRINTF_SIZEFMT(ipcur))
va_arg(vlist, size_t);
else if (IS_PRINTF_CHARPFMT(ipcur))
va_arg(vlist, char *);
else if (IS_PRINTF_LONGFMT(ipcur))
va_arg(vlist, long int);
else if (IS_PRINTF_LONGLONGFMT(ipcur))
va_arg(vlist, long long int);
else if (IS_PRINTF_INTMAXFMT(ipcur))
va_arg(vlist, intmax_t);
else if (IS_PRINTF_PTRDIFFFMT(ipcur))
va_arg(vlist, ptrdiff_t);
else if (IS_PRINTF_LONGDOUBLEFMT(ipcur))
va_arg(vlist, long double);
else if (IS_PRINTF_POINTERFMT(ipcur))
va_arg(vlist, void *);
else if (IS_PRINTF_WCHARPFMT(ipcur))
va_arg(vlist, wchar_t *);
else if (IS_PRINTF_WINTFMT(ipcur))
{
if (sizeof(wint_t) >= sizeof(int))
va_arg(vlist, wint_t);
else
va_arg(vlist, int);
}
goto continue_while;
}
{
size_t cpsz = strlen(ip);
memcpy(opcur, ip, sizeof(char) * cpsz);
opcur[cpsz] = '\0';
}
tmp = vfprintf(fs, op, vlist_cpy);
if (tmp < 0)
res = tmp;
else
res += tmp;
end:
TMP_END;
va_end(vlist_cpy);
return (int) res;
print_flint_type:
{
size_t cpsz = ipcur - ip;
memcpy(opcur, ip, sizeof(char) * cpsz);
opcur[cpsz] = '\0';
}
tmp = vfprintf(fs, op, vlist_cpy);
if (tmp < 0)
{
res = tmp;
goto end;
}
else
res += tmp;
va_end(vlist_cpy);
opcur = op;
ip = ipcur + 2;
if (IS_FLINT_BASE_TYPE(ip, "ulong"))
{
if (IS_FLINT_TYPE(ip, "ulong"))
{
res += fprintf(fs, WORD_FMT "u", va_arg(vlist, ulong));
ip += STRING_LENGTH("ulong}");
}
else if (IS_FLINT_TYPE(ip, "ulong*"))
{
const ulong * vec = va_arg(vlist, const ulong *);
slong len = va_arg(vlist, slong);
res += __flint_vec_fprint(fs, vec, len, ulong_type);
ip += STRING_LENGTH("ulong*}");
}
else
goto printpercentcurlybracket;
}
else if (IS_FLINT_BASE_TYPE(ip, "slong"))
{
if (IS_FLINT_TYPE(ip, "slong"))
{
res += fprintf(fs, WORD_FMT "d", va_arg(vlist, slong));
ip += STRING_LENGTH("slong}");
}
else if (IS_FLINT_TYPE(ip, "slong*"))
{
const slong * vec = va_arg(vlist, const slong *);
slong len = va_arg(vlist, slong);
res += __flint_vec_fprint(fs, vec, len, slong_type);
ip += STRING_LENGTH("slong*}");
}
else
goto printpercentcurlybracket;
}
else if (IS_FLINT_BASE_TYPE(ip, "nmod"))
{
if (IS_FLINT_TYPE(ip, "nmod"))
{
res += __nmod_fprint(fs, va_arg(vlist, nmod_t));
ip += STRING_LENGTH("nmod}");
}
else if (IS_FLINT_TYPE(ip, "nmod_mat"))
{
res += __flint_mat_fprint(fs, va_arg(vlist, const nmod_mat_struct *), ulong_type);
ip += STRING_LENGTH("nmod_mat}");
}
else if (IS_FLINT_TYPE(ip, "nmod_poly"))
{
res += __flint_poly_fprint(fs, va_arg(vlist, const nmod_poly_struct *), ulong_type);
ip += STRING_LENGTH("nmod_poly}");
}
else
goto printpercentcurlybracket;
}
else if (IS_FLINT_BASE_TYPE(ip, "fmpz"))
{
if (IS_FLINT_TYPE(ip, "fmpz"))
{
res += __fmpz_fprint(fs, va_arg(vlist, const fmpz *), FLAG_NONE);
ip += STRING_LENGTH("fmpz}");
}
else if (IS_FLINT_TYPE(ip, "fmpz*"))
{
const fmpz * vec = va_arg(vlist, const fmpz *);
slong len = va_arg(vlist, slong);
res += __flint_vec_fprint(fs, vec, len, fmpz_type);
ip += STRING_LENGTH("fmpz*}");
}
else if (IS_FLINT_TYPE(ip, "fmpz_mat"))
{
res += __flint_mat_fprint(fs, va_arg(vlist, const fmpz_mat_struct *), fmpz_type);
ip += STRING_LENGTH("fmpz_mat}");
}
else if (IS_FLINT_TYPE(ip, "fmpz_poly"))
{
res += __flint_poly_fprint(fs, va_arg(vlist, const fmpz_poly_struct *), fmpz_type);
ip += STRING_LENGTH("fmpz_poly}");
}
else if (IS_FLINT_TYPE(ip, "fmpz_mod_ctx"))
{
res += __fmpz_mod_ctx_fprint(fs, va_arg(vlist, const fmpz_mod_ctx_struct *));
ip += STRING_LENGTH("fmpz_mod_ctx}");
}
else if (IS_FLINT_TYPE(ip, "fmpz_mod_mat"))
{
res += __flint_mat_fprint(fs, va_arg(vlist, const fmpz_mod_mat_struct *), fmpz_type);
ip += STRING_LENGTH("fmpz_mod_mat}");
}
else if (IS_FLINT_TYPE(ip, "fmpz_mod_poly"))
{
res += __flint_poly_fprint(fs, va_arg(vlist, const fmpz_mod_poly_struct *), fmpz_type);
ip += STRING_LENGTH("fmpz_mod_poly}");
}
else
goto printpercentcurlybracket;
}
else if (IS_FLINT_BASE_TYPE(ip, "fmpq"))
{
if (IS_FLINT_TYPE(ip, "fmpq"))
{
res += __fmpq_fprint(fs, va_arg(vlist, const fmpq *), FLAG_NONE);
ip += STRING_LENGTH("fmpq}");
}
else if (IS_FLINT_TYPE(ip, "fmpq*"))
{
const fmpq * vec = va_arg(vlist, const fmpq *);
slong len = va_arg(vlist, slong);
res += __flint_vec_fprint(fs, vec, len, fmpq_type);
ip += STRING_LENGTH("fmpq*}");
}
else if (IS_FLINT_TYPE(ip, "fmpq_mat"))
{
res += __flint_mat_fprint(fs, va_arg(vlist, const fmpq_mat_struct *), fmpq_type);
ip += STRING_LENGTH("fmpq_mat}");
}
else if (IS_FLINT_TYPE(ip, "fmpq_poly"))
{
res += __flint_poly_fprint(fs, va_arg(vlist, const fmpq_poly_struct *), fmpq_type);
ip += STRING_LENGTH("fmpq_poly}");
}
else
goto printpercentcurlybracket;
}
else if (IS_FLINT_BASE_TYPE(ip, "arf"))
{
if (IS_FLINT_TYPE(ip, "arf"))
{
res += __arf_fprint(fs, va_arg(vlist, arf_srcptr), 0);
ip += STRING_LENGTH("arf}");
}
else if (IS_FLINT_TYPE(ip, "arf*"))
{
arf_srcptr vec = va_arg(vlist, arf_srcptr);
slong len = va_arg(vlist, slong);
res += __flint_vec_fprint(fs, vec, len, arf_type);
ip += STRING_LENGTH("arf*}");
}
else
goto printpercentcurlybracket;
}
else if (IS_FLINT_BASE_TYPE(ip, "mag"))
{
if (IS_FLINT_TYPE(ip, "mag"))
{
res += __mag_fprint(fs, va_arg(vlist, mag_srcptr), 0);
ip += STRING_LENGTH("mag}");
}
else if (IS_FLINT_TYPE(ip, "mag*"))
{
mag_srcptr vec = va_arg(vlist, mag_srcptr);
slong len = va_arg(vlist, slong);
res += __flint_vec_fprint(fs, vec, len, mag_type);
ip += STRING_LENGTH("mag*}");
}
else
goto printpercentcurlybracket;
}
else if (IS_FLINT_BASE_TYPE(ip, "arb"))
{
if (IS_FLINT_TYPE(ip, "arb"))
{
res += __arb_fprint(fs, va_arg(vlist, arb_srcptr), FLAG_NONE);
ip += STRING_LENGTH("arb}");
}
else if (IS_FLINT_TYPE(ip, "arb*"))
{
arb_srcptr vec = va_arg(vlist, arb_srcptr);
slong len = va_arg(vlist, slong);
res += __flint_vec_fprint(fs, vec, len, arb_type);
ip += STRING_LENGTH("arb*}");
}
else if (IS_FLINT_TYPE(ip, "arb_mat"))
{
res += __flint_mat_fprint(fs, va_arg(vlist, const arb_mat_struct *), arb_type);
ip += STRING_LENGTH("arb_mat}");
}
else if (IS_FLINT_TYPE(ip, "arb_poly"))
{
res += __flint_poly_fprint(fs, va_arg(vlist, const arb_poly_struct *), arb_type);
ip += STRING_LENGTH("arb_poly}");
}
else
goto printpercentcurlybracket;
}
else if (IS_FLINT_BASE_TYPE(ip, "acb"))
{
if (IS_FLINT_TYPE(ip, "acb"))
{
res += __acb_fprint(fs, va_arg(vlist, acb_srcptr), FLAG_NONE);
ip += STRING_LENGTH("acb}");
}
else if (IS_FLINT_TYPE(ip, "acb*"))
{
acb_srcptr vec = va_arg(vlist, acb_srcptr);
slong len = va_arg(vlist, slong);
res += __flint_vec_fprint(fs, vec, len, acb_type);
ip += STRING_LENGTH("acb*}");
}
else if (IS_FLINT_TYPE(ip, "acb_mat"))
{
res += __flint_mat_fprint(fs, va_arg(vlist, const acb_mat_struct *), acb_type);
ip += STRING_LENGTH("acb_mat}");
}
else if (IS_FLINT_TYPE(ip, "acb_poly"))
{
res += __flint_poly_fprint(fs, va_arg(vlist, const acb_poly_struct *), acb_type);
ip += STRING_LENGTH("acb_poly}");
}
else
goto printpercentcurlybracket;
}
else if (IS_FLINT_TYPE(ip, "mpz"))
{
res += __mpz_fprint(fs, va_arg(vlist, mpz_srcptr));
ip += STRING_LENGTH("mpz}");
}
else if (IS_FLINT_TYPE(ip, "mpq"))
{
res += __mpq_fprint(fs, va_arg(vlist, mpq_srcptr));
ip += STRING_LENGTH("mpq}");
}
else
{
printpercentcurlybracket:
#ifdef __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wformat"
#endif
tmp = fprintf(fs, "%{");
#ifdef __GNUC__
# pragma GCC diagnostic pop
#endif
if (tmp < 0)
{
res = tmp;
goto end;
}
else
res += tmp;
}
goto continue_while_from_flint_type;
}
int flint_printf(const char * str, ...)
{
va_list vlist;
int ret;
va_start(vlist, str);
ret = flint_vfprintf(stdout, str, vlist);
va_end(vlist);
return ret;
}
int flint_fprintf(FILE * fs, const char * str, ...)
{
va_list vlist;
int ret;
va_start(vlist, str);
ret = flint_vfprintf(fs, str, vlist);
va_end(vlist);
return ret;
}
int flint_vprintf(const char * str, va_list vlist)
{
return flint_vfprintf(stdout, str, vlist);
}
static size_t __ulong_fprint(FILE * fs, const ulong * ip, int FLINT_UNUSED(flag))
{
return fprintf(fs, WORD_FMT "u", *ip);
}
static size_t __slong_fprint(FILE * fs, const slong * ip, int FLINT_UNUSED(flag))
{
return fprintf(fs, WORD_FMT "d", *ip);
}
#define BASE 10
static size_t __fmpz_fprint(FILE * fs, const fmpz * ip, int flag)
{
size_t res = 0;
char * str;
size_t skipminus = __fmpz_is_neg(ip) ? FLAG_IS_NEG(flag) : 0;
str = fmpz_get_str(NULL, BASE, ip);
res += fwrite(str + skipminus, sizeof(char), strlen(str + skipminus), fs);
flint_free(str);
return res;
}
#undef BASE
static size_t __mpz_fprint(FILE * fs, mpz_srcptr ip)
{
fmpz_t fip;
if ((ip->_mp_size == 1 || ip->_mp_size == -1) && ip->_mp_d[0] <= COEFF_MAX)
*fip = ip->_mp_size > 0 ? ip->_mp_d[0] : -ip->_mp_d[0];
else
*fip = PTR_TO_COEFF(ip);
return __fmpz_fprint(fs, fip, FLAG_NONE);
}
static size_t __fmpq_fprint(FILE * fs, const fmpq * ip, int flag)
{
size_t res = 0;
res += __fmpz_fprint(fs, fmpq_numref(ip), flag);
if (!fmpz_is_one(fmpq_denref(ip)))
{
res += fwrite(" / ", sizeof(char), STRING_LENGTH(" / "), fs);
res += __fmpz_fprint(fs, fmpq_denref(ip), FLAG_NONE);
}
return res;
}
static size_t __mpq_fprint(FILE * fs, mpq_srcptr ip)
{
fmpq_t fip;
if ((ip->_mp_num._mp_size == 1 || ip->_mp_num._mp_size == -1) && ip->_mp_num._mp_d[0] <= COEFF_MAX)
*fmpq_numref(fip) = ip->_mp_num._mp_size > 0 ? ip->_mp_num._mp_d[0] : -ip->_mp_num._mp_d[0];
else
*fmpq_numref(fip) = PTR_TO_COEFF(&(ip->_mp_num));
if ((ip->_mp_den._mp_size == 1 || ip->_mp_den._mp_size == -1) && ip->_mp_den._mp_d[0] <= COEFF_MAX)
*fmpq_denref(fip) = ip->_mp_den._mp_size > 0 ? ip->_mp_den._mp_d[0] : -ip->_mp_den._mp_d[0];
else
*fmpq_denref(fip) = PTR_TO_COEFF(&(ip->_mp_den));
return __fmpq_fprint(fs, fip, FLAG_NONE);
}
#define DIGITS 6
static size_t __mag_fprint(FILE * fs, mag_srcptr ip, int FLINT_UNUSED(flag))
{
size_t res;
char * str;
#if DIGITS != 6
# error Change fwrite below
#endif
if (mag_is_zero(ip))
return fwrite("0.00000", sizeof(char), STRING_SIZE("0.00000"), fs);
str = __mag_get_str(ip, DIGITS);
res = fwrite(str, sizeof(char), strlen(str), fs);
flint_free(str);
return res;
}
static size_t __arf_fprint(FILE * fs, arf_srcptr ip, int FLINT_UNUSED(flag))
{
size_t res;
char * str;
#if DIGITS != 6
# error Change fwrite below
#endif
if (arf_is_zero(ip))
return fwrite("0.00000", sizeof(char), STRING_SIZE("0.00000"), fs);
str = arf_get_str(ip, DIGITS);
res = fwrite(str, sizeof(char), strlen(str), fs);
flint_free(str);
return res;
}
#define MAX_INT_SIZE 64
static size_t __arb_fprint(FILE * fs, arb_srcptr ip, int flag)
{
size_t res;
if (arb_is_zero(ip))
{
return (fputc('0', fs) != EOF);
}
else if (arb_is_int(ip) && ARF_EXP(arb_midref(ip)) <= MAX_INT_SIZE)
{
fmpz_t fip;
fmpz_init(fip);
arf_get_fmpz(fip, arb_midref(ip), ARF_RND_DOWN);
res = __fmpz_fprint(fs, fip, flag);
fmpz_clear(fip);
}
else
{
char * str;
arb_struct ip2;
if (FLAG_IS_NEG(flag))
__arb_neg_readonly(&ip2, ip);
else
ip2 = *ip;
str = arb_get_str(&ip2, DIGITS, 0);
res = fwrite(str, sizeof(char), strlen(str), fs);
flint_free(str);
}
return res;
}
#undef MAX_INT_SIZE
#undef DIGITS
static size_t __acb_fprint(FILE * fs, acb_srcptr ip, int flag)
{
size_t res = 0;
int realiszero, imagiszero;
realiszero = arb_is_zero(acb_realref(ip));
imagiszero = arb_is_zero(acb_imagref(ip));
if (realiszero && imagiszero)
return (fputc('0', fs) != EOF);
if (FLAG_IS_PAREN(flag) && !realiszero && !imagiszero)
res += (fputc('(', fs) != EOF);
if (!realiszero)
res += __arb_fprint(fs, acb_realref(ip), flag);
if (!imagiszero)
{
int imagisneg = arb_is_negative(acb_imagref(ip));
if (!realiszero)
res += fwrite(FLAG_IS_NEG(flag) ^ imagisneg ? " - " : " + ", sizeof(char), STRING_SIZE(" - "), fs);
if (!__arb_is_pm1(acb_imagref(ip)))
{
res += __arb_fprint(fs, acb_imagref(ip), (FLAG_IS_NEG(flag) ^ imagisneg) & (~realiszero));
res += fwrite(" * ", sizeof(char), STRING_LENGTH(" * "), fs);
}
res += (fputc('i', fs) != EOF);
}
if (FLAG_IS_PAREN(flag) && !realiszero && !imagiszero)
res += (fputc(')', fs) != EOF);
return res;
}
static size_t __nmod_fprint(FILE * fs, nmod_t ip)
{
return fprintf(fs, "mod " WORD_FMT "u", ip.n);
}
static size_t __fmpz_mod_ctx_fprint(FILE * fs, const fmpz_mod_ctx_struct * ip)
{
size_t res = 0;
res += fwrite("mod ", sizeof(char), STRING_LENGTH("mod "), fs);
res += fmpz_fprint(fs, fmpz_mod_ctx_modulus(ip));
return res;
}
typedef size_t (* print_func_t)(FILE *, const void *, int);
static print_func_t print_functions[] =
{
(print_func_t) __ulong_fprint,
(print_func_t) __fmpz_fprint,
(print_func_t) __fmpq_fprint,
(print_func_t) __arb_fprint,
(print_func_t) __acb_fprint,
(print_func_t) __slong_fprint,
(print_func_t) __mag_fprint,
(print_func_t) __arf_fprint
};
static size_t __flint_vec_fprint(FILE * fs, const void * ip, slong len, flint_type_t type)
{
size_t res = 0;
slong ix;
const char * vec = ip;
size_t type_size = flint_type_size_in_chars(type);
print_func_t print = print_functions[type];
res += (fputc('[', fs) != EOF);
if (len > 0)
res += print(fs, vec, FLAG_NONE);
for (ix = 1; ix < len; ix++)
{
res += fwrite(", ", sizeof(char), STRING_LENGTH(", "), fs);
res += print(fs, vec + type_size * ix, FLAG_NONE);
}
res += (fputc(']', fs) != EOF);
return res;
}
static size_t __flint_mat_fprint(FILE * fs, const void * ip, flint_type_t type)
{
size_t res = 0;
slong ix;
slong nr, nc;
const void ** rows;
rows = (const void **) ((const fmpz_mat_struct *) ip)->rows;
nr = ((const fmpz_mat_struct *) ip)->r;
nc = ((const fmpz_mat_struct *) ip)->c;
if (nr == 0 || nc == 0)
return fprintf(fs, WORD_FMT "d by " WORD_FMT "d empty matrix", nr, nc);
res += (fputc('[', fs) != EOF);
res += __flint_vec_fprint(fs, rows[0], nc, type);
for (ix = 1; ix < nr; ix++)
{
res += fwrite(", ", sizeof(char), STRING_LENGTH(", "), fs);
res += __flint_vec_fprint(fs, rows[ix], nc, type);
}
res += (fputc(']', fs) != EOF);
return res;
}
typedef int (* is_func_t)(const void *);
static is_func_t is_pm1_functions[] =
{
__ulong_is_pm1,
(is_func_t) fmpz_is_pm1,
__never_is,
__arb_is_pm1,
__acb_is_pm1
};
static is_func_t is_zero_functions[] =
{
__ulong_is_zero,
(is_func_t) fmpz_is_zero,
__never_is,
(is_func_t) arb_is_zero,
(is_func_t) acb_is_zero
};
static is_func_t is_neg_functions[] =
{
__never_is,
__fmpz_is_neg,
__never_is,
(is_func_t) arb_is_negative,
__acb_is_neg
};
static size_t __flint_poly_fprint(FILE * fs, const void * ip, flint_type_t type)
{
size_t res = 0;
slong ix;
slong len;
len = ((const fmpz_poly_struct *) ip)->length;
if (len == 0)
return fputc('0', fs) != EOF;
if (type != fmpq_type)
{
size_t type_size = flint_type_size_in_chars(type);
const char * coeffs = (const char *) ((const fmpz_poly_struct *) ip)->coeffs;
print_func_t print = print_functions[type];
is_func_t is_pm1 = is_pm1_functions[type];
is_func_t is_zero = is_zero_functions[type];
is_func_t is_neg = is_neg_functions[type];
if (len == 1)
return print(fs, coeffs, FLAG_NONE);
if (!is_pm1(coeffs + type_size * (len - 1)))
{
res += print(fs, coeffs + type_size * (len - 1), FLAG_PAREN);
res += fwrite(" * ", sizeof(char), STRING_LENGTH(" * "), fs);
}
else if (is_neg(coeffs + type_size * (len - 1)))
res += (fputc('-', fs) != EOF);
if (len != 2)
res += fprintf(fs, "x^" WORD_FMT "d", len - 1);
else
res += (fputc('x', fs) != EOF);
for (ix = len - 2; ix > 0; ix--)
{
if (!is_zero(coeffs + type_size * ix))
{
res += fwrite(is_neg(coeffs + type_size * ix) ? " - " : " + ", sizeof(char), STRING_LENGTH(" - "), fs);
if (!is_pm1(coeffs + type_size * ix))
{
res += print(fs, coeffs + type_size * ix, is_neg(coeffs + type_size * ix) | FLAG_PAREN);
res += fwrite(" * ", sizeof(char), STRING_LENGTH(" * "), fs);
}
if (ix != 1)
res += fprintf(fs, "x^" WORD_FMT "d", ix);
else
res += (fputc('x', fs) != EOF);
}
}
if (!is_zero(coeffs + 0))
{
res += fwrite(is_neg(coeffs + 0) ? " - " : " + ", sizeof(char), STRING_LENGTH(" - "), fs);
res += print(fs, coeffs + 0, is_neg(coeffs + 0));
}
}
else
{
const fmpz * coeffs = ((const fmpq_poly_struct *) ip)->coeffs;
const fmpz * den = ((const fmpq_poly_struct *) ip)->den;
fmpq_t canonical;
fmpq_init(canonical);
fmpq_set_fmpz_frac(canonical, coeffs + len - 1, den);
if (len == 1)
{
res += __fmpq_fprint(fs, canonical, FLAG_NONE);
fmpq_clear(canonical);
return res;
}
if (!fmpq_is_pm1(canonical))
{
res += __fmpq_fprint(fs, canonical, FLAG_NONE);
res += fwrite(" * ", sizeof(char), STRING_LENGTH(" * "), fs);
}
else if (__fmpq_is_neg(canonical))
res += (fputc('-', fs) != EOF);
if (len != 2)
res += fprintf(fs, "x^" WORD_FMT "d", len - 1);
else
res += (fputc('x', fs) != EOF);
for (ix = len - 2; ix > 0; ix--)
{
if (!fmpz_is_zero(coeffs + ix))
{
fmpq_set_fmpz_frac(canonical, coeffs + ix, den);
res += fwrite(__fmpq_is_neg(canonical) ? " - " : " + ", sizeof(char), STRING_LENGTH(" - "), fs);
if (!fmpq_is_pm1(canonical))
{
res += __fmpq_fprint(fs, canonical, __fmpq_is_neg(canonical));
res += fwrite(" * ", sizeof(char), STRING_LENGTH(" * "), fs);
}
if (ix != 1)
res += fprintf(fs, "x^" WORD_FMT "d", ix);
else
res += (fputc('x', fs) != EOF);
}
}
fmpq_set_fmpz_frac(canonical, coeffs + 0, den);
if (!fmpq_is_zero(canonical))
{
res += fwrite(__fmpq_is_neg(canonical) ? " - " : " + ", sizeof(char), STRING_LENGTH(" - "), fs);
res += __fmpq_fprint(fs, canonical, __fmpq_is_neg(canonical));
}
fmpq_clear(canonical);
}
return res;
}