/*
Copyright (C) 2010 Sebastian Pancratz
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 .
*/
#include
#include
#include
#include
#include
#include "flint.h"
#include "fmpz.h"
#include "fmpz_poly.h"
static __inline__
int is_varsymbol0(char c)
{
return isalpha((unsigned char) c);
}
static __inline__
int is_varsymbol1(char c)
{
return isalnum((unsigned char) c) || (c == '_');
}
#define next_event() \
do { \
c = fgetc(file); \
if (c == EOF && !feof(file)) \
goto s_ioe; \
++r; \
if (i == N) \
{ \
buf = flint_realloc(buf, N = 2*N); \
} \
buf[i++] = c; \
} while (0)
#define add_coeff() \
do { \
fmpz_set_mpz(f_coeff, z_coeff); \
fmpz_poly_fit_length(poly, exp + 1); \
fmpz_add(poly->coeffs + exp, poly->coeffs + exp, f_coeff); \
if (poly->length < exp + 1) \
poly->length = exp + 1; \
} while (0)
int fmpz_poly_fread_pretty(FILE *file, fmpz_poly_t poly, char **x)
{
/*
var - variable name
buf - buffer of size N, at write position i, with c == buf[i-1]
z_coeff - mpz_t for the coefficient, f_coeff is the fmpz_t version
z_exp - mpz_t for the exponent, exp is the slong version
r - return value
*/
char *var = NULL;
char c, *buf;
int i, N;
fmpz_t f_coeff;
mpz_t z_coeff, z_exp;
slong exp;
int r = 0;
fmpz_poly_zero(poly);
if (poly->alloc)
flint_mpn_zero((mp_ptr) poly->coeffs, poly->alloc);
i = 0;
N = 80;
buf = flint_malloc(N);
fmpz_init(f_coeff);
mpz_init(z_coeff);
mpz_init(z_exp);
/* s_0 : */
next_event();
if (c == '-')
goto s_1;
if (isdigit((unsigned char) c))
goto s_2;
if (is_varsymbol0(c))
{
flint_mpz_set_si(z_coeff, 1);
goto s_3;
}
goto s_parse_error;
s_1 :
next_event();
if (isdigit((unsigned char) c))
goto s_2;
if (is_varsymbol0(c))
{
if (i == 1)
flint_mpz_set_si(z_coeff, 1);
else /* i == 2 */
{
flint_mpz_set_si(z_coeff, -1);
buf[0] = c;
i = 1;
}
goto s_3;
}
goto s_parse_error;
s_2 :
next_event();
if (isdigit((unsigned char) c))
goto s_2;
if (c == '*')
{
buf[i-1] = '\0';
mpz_set_str(z_coeff, buf, 10);
i = 0;
goto s_4;
}
{
buf[i-1] = '\0';
mpz_set_str(z_coeff, buf, 10);
exp = 0;
add_coeff();
if (c == '+' || c == '-')
{
i = 0;
if (c == '-')
buf[i++] = '-';
goto s_1;
}
else
goto s_end;
}
s_3 :
next_event();
if (is_varsymbol1(c))
goto s_3;
{
buf[i-1] = '\0';
if (var)
{
if (strcmp(buf, var)) /* Parse error */
goto s_parse_error;
}
else
{
var = flint_malloc(i);
strcpy(var, buf);
}
if (c == '^')
{
i = 0;
goto s_5;
}
else if (c == '+' || c == '-')
{
exp = 1;
add_coeff();
i = 0;
if (c == '-')
buf[i++] = '-';
goto s_1;
}
else
{
exp = 1;
add_coeff();
goto s_end;
}
}
s_4 :
next_event();
if (is_varsymbol0(c))
goto s_3;
goto s_parse_error;
s_5 :
next_event();
if (isdigit((unsigned char) c))
goto s_6;
goto s_parse_error;
s_6 :
next_event();
if (isdigit((unsigned char) c))
goto s_6;
{
buf[i-1] = '\0';
mpz_set_str(z_exp, buf, 10);
if (!mpz_fits_slong_p(z_exp))
{
goto s_parse_error;
}
exp = flint_mpz_get_si(z_exp);
add_coeff();
if (c == '+' || c == '-')
{
i = 0;
if (c == '-')
buf[i++] = '-';
goto s_1;
}
else
goto s_end;
}
s_parse_error :
r = -2;
goto s_end;
s_ioe :
r = -1;
goto s_end;
s_end :
_fmpz_poly_normalise(poly);
if (var)
*x = var;
else
{
*x = flint_malloc(1);
**x = '\0';
}
fmpz_clear(f_coeff);
mpz_clear(z_coeff);
mpz_clear(z_exp);
flint_free(buf);
return r;
}
#undef next_event
#undef add_coeff