Commit 5eda5bad by Ian Lance Taylor Committed by Ian Lance Taylor

compiler: Use MPC library for complex numbers.

	* go-gcc.cc (Gcc_backend::complex_constant_expression): Take one
	mpc_t parameter instead of two mpfr_t parameters.

From-SVN: r216611
parent 3c765286
2014-10-23 Ian Lance Taylor <iant@google.com>
* go-gcc.cc (Gcc_backend::complex_constant_expression): Take one
mpc_t parameter instead of two mpfr_t parameters.
2014-09-15 Jakub Jelinek <jakub@redhat.com> 2014-09-15 Jakub Jelinek <jakub@redhat.com>
* Make-lang.in (check_go_parallelize): Change to just an upper bound * Make-lang.in (check_go_parallelize): Change to just an upper bound
......
...@@ -247,7 +247,7 @@ class Gcc_backend : public Backend ...@@ -247,7 +247,7 @@ class Gcc_backend : public Backend
float_constant_expression(Btype* btype, mpfr_t val); float_constant_expression(Btype* btype, mpfr_t val);
Bexpression* Bexpression*
complex_constant_expression(Btype* btype, mpfr_t real, mpfr_t imag); complex_constant_expression(Btype* btype, mpc_t val);
Bexpression* Bexpression*
string_constant_expression(const std::string& val); string_constant_expression(const std::string& val);
...@@ -1241,7 +1241,7 @@ Gcc_backend::float_constant_expression(Btype* btype, mpfr_t val) ...@@ -1241,7 +1241,7 @@ Gcc_backend::float_constant_expression(Btype* btype, mpfr_t val)
// Return a typed real and imaginary value as a constant complex number. // Return a typed real and imaginary value as a constant complex number.
Bexpression* Bexpression*
Gcc_backend::complex_constant_expression(Btype* btype, mpfr_t real, mpfr_t imag) Gcc_backend::complex_constant_expression(Btype* btype, mpc_t val)
{ {
tree t = btype->get_tree(); tree t = btype->get_tree();
tree ret; tree ret;
...@@ -1249,12 +1249,12 @@ Gcc_backend::complex_constant_expression(Btype* btype, mpfr_t real, mpfr_t imag) ...@@ -1249,12 +1249,12 @@ Gcc_backend::complex_constant_expression(Btype* btype, mpfr_t real, mpfr_t imag)
return this->error_expression(); return this->error_expression();
REAL_VALUE_TYPE r1; REAL_VALUE_TYPE r1;
real_from_mpfr(&r1, real, TREE_TYPE(t), GMP_RNDN); real_from_mpfr(&r1, mpc_realref(val), TREE_TYPE(t), GMP_RNDN);
REAL_VALUE_TYPE r2; REAL_VALUE_TYPE r2;
real_convert(&r2, TYPE_MODE(TREE_TYPE(t)), &r1); real_convert(&r2, TYPE_MODE(TREE_TYPE(t)), &r1);
REAL_VALUE_TYPE r3; REAL_VALUE_TYPE r3;
real_from_mpfr(&r3, imag, TREE_TYPE(t), GMP_RNDN); real_from_mpfr(&r3, mpc_imagref(val), TREE_TYPE(t), GMP_RNDN);
REAL_VALUE_TYPE r4; REAL_VALUE_TYPE r4;
real_convert(&r4, TYPE_MODE(TREE_TYPE(t)), &r3); real_convert(&r4, TYPE_MODE(TREE_TYPE(t)), &r3);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <gmp.h> #include <gmp.h>
#include <mpfr.h> #include <mpfr.h>
#include <mpc.h>
#include "operator.h" #include "operator.h"
...@@ -277,9 +278,9 @@ class Backend ...@@ -277,9 +278,9 @@ class Backend
virtual Bexpression* virtual Bexpression*
float_constant_expression(Btype* btype, mpfr_t val) = 0; float_constant_expression(Btype* btype, mpfr_t val) = 0;
// Return an expression for the complex value REAL/IMAG in BTYPE. // Return an expression for the complex value VAL in BTYPE.
virtual Bexpression* virtual Bexpression*
complex_constant_expression(Btype* btype, mpfr_t real, mpfr_t imag) = 0; complex_constant_expression(Btype* btype, mpc_t val) = 0;
// Return an expression for the string value VAL. // Return an expression for the string value VAL.
virtual Bexpression* virtual Bexpression*
......
...@@ -436,16 +436,14 @@ Expression::backend_numeric_constant_expression(Translate_context* context, ...@@ -436,16 +436,14 @@ Expression::backend_numeric_constant_expression(Translate_context* context,
} }
else if (type->complex_type() != NULL) else if (type->complex_type() != NULL)
{ {
mpfr_t real; mpc_t cval;
mpfr_t imag; if (!val->to_complex(&cval))
if (!val->to_complex(&real, &imag))
{ {
go_assert(saw_errors()); go_assert(saw_errors());
return gogo->backend()->error_expression(); return gogo->backend()->error_expression();
} }
ret = gogo->backend()->complex_constant_expression(btype, real, imag); ret = gogo->backend()->complex_constant_expression(btype, cval);
mpfr_clear(real); mpc_clear(cval);
mpfr_clear(imag);
} }
else else
go_unreachable(); go_unreachable();
...@@ -2016,10 +2014,13 @@ Integer_expression::do_import(Import* imp) ...@@ -2016,10 +2014,13 @@ Integer_expression::do_import(Import* imp)
imag_str.c_str()); imag_str.c_str());
return Expression::make_error(imp->location()); return Expression::make_error(imp->location());
} }
Expression* ret = Expression::make_complex(&real, &imag, NULL, mpc_t cval;
imp->location()); mpc_init2(cval, mpc_precision);
mpc_set_fr_fr(cval, real, imag, MPC_RNDNN);
mpfr_clear(real); mpfr_clear(real);
mpfr_clear(imag); mpfr_clear(imag);
Expression* ret = Expression::make_complex(&cval, NULL, imp->location());
mpc_clear(cval);
return ret; return ret;
} }
else if (num.find('.') == std::string::npos else if (num.find('.') == std::string::npos
...@@ -2297,23 +2298,21 @@ Expression::make_float(const mpfr_t* val, Type* type, Location location) ...@@ -2297,23 +2298,21 @@ Expression::make_float(const mpfr_t* val, Type* type, Location location)
class Complex_expression : public Expression class Complex_expression : public Expression
{ {
public: public:
Complex_expression(const mpfr_t* real, const mpfr_t* imag, Type* type, Complex_expression(const mpc_t* val, Type* type, Location location)
Location location)
: Expression(EXPRESSION_COMPLEX, location), : Expression(EXPRESSION_COMPLEX, location),
type_(type) type_(type)
{ {
mpfr_init_set(this->real_, *real, GMP_RNDN); mpc_init2(this->val_, mpc_precision);
mpfr_init_set(this->imag_, *imag, GMP_RNDN); mpc_set(this->val_, *val, MPC_RNDNN);
} }
// Write REAL/IMAG to string dump. // Write VAL to string dump.
static void static void
export_complex(String_dump* exp, const mpfr_t real, const mpfr_t val); export_complex(String_dump* exp, const mpc_t val);
// Write REAL/IMAG to dump context. // Write REAL/IMAG to dump context.
static void static void
dump_complex(Ast_dump_context* ast_dump_context, dump_complex(Ast_dump_context* ast_dump_context, const mpc_t val);
const mpfr_t real, const mpfr_t val);
protected: protected:
bool bool
...@@ -2327,7 +2326,7 @@ class Complex_expression : public Expression ...@@ -2327,7 +2326,7 @@ class Complex_expression : public Expression
bool bool
do_numeric_constant_value(Numeric_constant* nc) const do_numeric_constant_value(Numeric_constant* nc) const
{ {
nc->set_complex(this->type_, this->real_, this->imag_); nc->set_complex(this->type_, this->val_);
return true; return true;
} }
...@@ -2343,7 +2342,7 @@ class Complex_expression : public Expression ...@@ -2343,7 +2342,7 @@ class Complex_expression : public Expression
Expression* Expression*
do_copy() do_copy()
{ {
return Expression::make_complex(&this->real_, &this->imag_, this->type_, return Expression::make_complex(&this->val_, this->type_,
this->location()); this->location());
} }
...@@ -2357,10 +2356,8 @@ class Complex_expression : public Expression ...@@ -2357,10 +2356,8 @@ class Complex_expression : public Expression
do_dump_expression(Ast_dump_context*) const; do_dump_expression(Ast_dump_context*) const;
private: private:
// The real part. // The complex value.
mpfr_t real_; mpc_t val_;
// The imaginary part;
mpfr_t imag_;
// The type if known. // The type if known.
Type* type_; Type* type_;
}; };
...@@ -2400,7 +2397,7 @@ Complex_expression::do_check_types(Gogo*) ...@@ -2400,7 +2397,7 @@ Complex_expression::do_check_types(Gogo*)
if (type == NULL) if (type == NULL)
return; return;
Numeric_constant nc; Numeric_constant nc;
nc.set_complex(NULL, this->real_, this->imag_); nc.set_complex(NULL, this->val_);
if (!nc.set_type(this->type_, true, this->location())) if (!nc.set_type(this->type_, true, this->location()))
this->set_is_error(); this->set_is_error();
} }
...@@ -2432,23 +2429,22 @@ Complex_expression::do_get_backend(Translate_context* context) ...@@ -2432,23 +2429,22 @@ Complex_expression::do_get_backend(Translate_context* context)
} }
Numeric_constant nc; Numeric_constant nc;
nc.set_complex(resolved_type, this->real_, this->imag_); nc.set_complex(resolved_type, this->val_);
return Expression::backend_numeric_constant_expression(context, &nc); return Expression::backend_numeric_constant_expression(context, &nc);
} }
// Write REAL/IMAG to export data. // Write REAL/IMAG to export data.
void void
Complex_expression::export_complex(String_dump* exp, const mpfr_t real, Complex_expression::export_complex(String_dump* exp, const mpc_t val)
const mpfr_t imag)
{ {
if (!mpfr_zero_p(real)) if (!mpfr_zero_p(mpc_realref(val)))
{ {
Float_expression::export_float(exp, real); Float_expression::export_float(exp, mpc_realref(val));
if (mpfr_sgn(imag) > 0) if (mpfr_sgn(mpc_imagref(val)) > 0)
exp->write_c_string("+"); exp->write_c_string("+");
} }
Float_expression::export_float(exp, imag); Float_expression::export_float(exp, mpc_imagref(val));
exp->write_c_string("i"); exp->write_c_string("i");
} }
...@@ -2457,7 +2453,7 @@ Complex_expression::export_complex(String_dump* exp, const mpfr_t real, ...@@ -2457,7 +2453,7 @@ Complex_expression::export_complex(String_dump* exp, const mpfr_t real,
void void
Complex_expression::do_export(Export* exp) const Complex_expression::do_export(Export* exp) const
{ {
Complex_expression::export_complex(exp, this->real_, this->imag_); Complex_expression::export_complex(exp, this->val_);
// A trailing space lets us reliably identify the end of the number. // A trailing space lets us reliably identify the end of the number.
exp->write_c_string(" "); exp->write_c_string(" ");
} }
...@@ -2467,18 +2463,15 @@ Complex_expression::do_export(Export* exp) const ...@@ -2467,18 +2463,15 @@ Complex_expression::do_export(Export* exp) const
void void
Complex_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const Complex_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{ {
Complex_expression::export_complex(ast_dump_context, Complex_expression::export_complex(ast_dump_context, this->val_);
this->real_,
this->imag_);
} }
// Make a complex expression. // Make a complex expression.
Expression* Expression*
Expression::make_complex(const mpfr_t* real, const mpfr_t* imag, Type* type, Expression::make_complex(const mpc_t* val, Type* type, Location location)
Location location)
{ {
return new Complex_expression(real, imag, type, location); return new Complex_expression(val, type, location);
} }
// Find a named object in an expression. // Find a named object in an expression.
...@@ -3774,18 +3767,14 @@ Unary_expression::eval_constant(Operator op, const Numeric_constant* unc, ...@@ -3774,18 +3767,14 @@ Unary_expression::eval_constant(Operator op, const Numeric_constant* unc,
} }
else if (unc->is_complex()) else if (unc->is_complex())
{ {
mpfr_t ureal, uimag; mpc_t uval;
unc->get_complex(&ureal, &uimag); unc->get_complex(&uval);
mpfr_t real, imag; mpc_t val;
mpfr_init(real); mpc_init2(val, mpc_precision);
mpfr_init(imag); mpc_neg(val, uval, MPC_RNDNN);
mpfr_neg(real, ureal, GMP_RNDN); nc->set_complex(unc->type(), val);
mpfr_neg(imag, uimag, GMP_RNDN); mpc_clear(uval);
nc->set_complex(unc->type(), real, imag); mpc_clear(val);
mpfr_clear(ureal);
mpfr_clear(uimag);
mpfr_clear(real);
mpfr_clear(imag);
return true; return true;
} }
else else
...@@ -4505,14 +4494,13 @@ Binary_expression::compare_complex(const Numeric_constant* left_nc, ...@@ -4505,14 +4494,13 @@ Binary_expression::compare_complex(const Numeric_constant* left_nc,
const Numeric_constant* right_nc, const Numeric_constant* right_nc,
int* cmp) int* cmp)
{ {
mpfr_t left_real, left_imag; mpc_t left_val;
if (!left_nc->to_complex(&left_real, &left_imag)) if (!left_nc->to_complex(&left_val))
return false; return false;
mpfr_t right_real, right_imag; mpc_t right_val;
if (!right_nc->to_complex(&right_real, &right_imag)) if (!right_nc->to_complex(&right_val))
{ {
mpfr_clear(left_real); mpc_clear(left_val);
mpfr_clear(left_imag);
return false; return false;
} }
...@@ -4522,19 +4510,16 @@ Binary_expression::compare_complex(const Numeric_constant* left_nc, ...@@ -4522,19 +4510,16 @@ Binary_expression::compare_complex(const Numeric_constant* left_nc,
if (!type->is_abstract() && type->complex_type() != NULL) if (!type->is_abstract() && type->complex_type() != NULL)
{ {
int bits = type->complex_type()->bits(); int bits = type->complex_type()->bits();
mpfr_prec_round(left_real, bits / 2, GMP_RNDN); mpfr_prec_round(mpc_realref(left_val), bits / 2, GMP_RNDN);
mpfr_prec_round(left_imag, bits / 2, GMP_RNDN); mpfr_prec_round(mpc_imagref(left_val), bits / 2, GMP_RNDN);
mpfr_prec_round(right_real, bits / 2, GMP_RNDN); mpfr_prec_round(mpc_realref(right_val), bits / 2, GMP_RNDN);
mpfr_prec_round(right_imag, bits / 2, GMP_RNDN); mpfr_prec_round(mpc_imagref(right_val), bits / 2, GMP_RNDN);
} }
*cmp = (mpfr_cmp(left_real, right_real) != 0 *cmp = mpc_cmp(left_val, right_val) != 0;
|| mpfr_cmp(left_imag, right_imag) != 0);
mpfr_clear(left_real); mpc_clear(left_val);
mpfr_clear(left_imag); mpc_clear(right_val);
mpfr_clear(right_real);
mpfr_clear(right_imag);
return true; return true;
} }
...@@ -4805,31 +4790,27 @@ Binary_expression::eval_complex(Operator op, const Numeric_constant* left_nc, ...@@ -4805,31 +4790,27 @@ Binary_expression::eval_complex(Operator op, const Numeric_constant* left_nc,
const Numeric_constant* right_nc, const Numeric_constant* right_nc,
Location location, Numeric_constant* nc) Location location, Numeric_constant* nc)
{ {
mpfr_t left_real, left_imag; mpc_t left_val;
if (!left_nc->to_complex(&left_real, &left_imag)) if (!left_nc->to_complex(&left_val))
return false; return false;
mpfr_t right_real, right_imag; mpc_t right_val;
if (!right_nc->to_complex(&right_real, &right_imag)) if (!right_nc->to_complex(&right_val))
{ {
mpfr_clear(left_real); mpc_clear(left_val);
mpfr_clear(left_imag);
return false; return false;
} }
mpfr_t real, imag; mpc_t val;
mpfr_init(real); mpc_init2(val, mpc_precision);
mpfr_init(imag);
bool ret = true; bool ret = true;
switch (op) switch (op)
{ {
case OPERATOR_PLUS: case OPERATOR_PLUS:
mpfr_add(real, left_real, right_real, GMP_RNDN); mpc_add(val, left_val, right_val, MPC_RNDNN);
mpfr_add(imag, left_imag, right_imag, GMP_RNDN);
break; break;
case OPERATOR_MINUS: case OPERATOR_MINUS:
mpfr_sub(real, left_real, right_real, GMP_RNDN); mpc_sub(val, left_val, right_val, MPC_RNDNN);
mpfr_sub(imag, left_imag, right_imag, GMP_RNDN);
break; break;
case OPERATOR_OR: case OPERATOR_OR:
case OPERATOR_XOR: case OPERATOR_XOR:
...@@ -4838,310 +4819,30 @@ Binary_expression::eval_complex(Operator op, const Numeric_constant* left_nc, ...@@ -4838,310 +4819,30 @@ Binary_expression::eval_complex(Operator op, const Numeric_constant* left_nc,
case OPERATOR_MOD: case OPERATOR_MOD:
case OPERATOR_LSHIFT: case OPERATOR_LSHIFT:
case OPERATOR_RSHIFT: case OPERATOR_RSHIFT:
mpfr_set_ui(real, 0, GMP_RNDN); mpc_set_ui(val, 0, MPC_RNDNN);
mpfr_set_ui(imag, 0, GMP_RNDN);
ret = false; ret = false;
break; break;
case OPERATOR_MULT: case OPERATOR_MULT:
{ mpc_mul(val, left_val, right_val, MPC_RNDNN);
// You might think that multiplying two complex numbers would
// be simple, and you would be right, until you start to think
// about getting the right answer for infinity. If one
// operand here is infinity and the other is anything other
// than zero or NaN, then we are going to wind up subtracting
// two infinity values. That will give us a NaN, but the
// correct answer is infinity.
mpfr_t lrrr;
mpfr_init(lrrr);
mpfr_mul(lrrr, left_real, right_real, GMP_RNDN);
mpfr_t lrri;
mpfr_init(lrri);
mpfr_mul(lrri, left_real, right_imag, GMP_RNDN);
mpfr_t lirr;
mpfr_init(lirr);
mpfr_mul(lirr, left_imag, right_real, GMP_RNDN);
mpfr_t liri;
mpfr_init(liri);
mpfr_mul(liri, left_imag, right_imag, GMP_RNDN);
mpfr_sub(real, lrrr, liri, GMP_RNDN);
mpfr_add(imag, lrri, lirr, GMP_RNDN);
// If we get NaN on both sides, check whether it should really
// be infinity. The rule is that if either side of the
// complex number is infinity, then the whole value is
// infinity, even if the other side is NaN. So the only case
// we have to fix is the one in which both sides are NaN.
if (mpfr_nan_p(real) && mpfr_nan_p(imag)
&& (!mpfr_nan_p(left_real) || !mpfr_nan_p(left_imag))
&& (!mpfr_nan_p(right_real) || !mpfr_nan_p(right_imag)))
{
bool is_infinity = false;
mpfr_t lr;
mpfr_t li;
mpfr_init_set(lr, left_real, GMP_RNDN);
mpfr_init_set(li, left_imag, GMP_RNDN);
mpfr_t rr;
mpfr_t ri;
mpfr_init_set(rr, right_real, GMP_RNDN);
mpfr_init_set(ri, right_imag, GMP_RNDN);
// If the left side is infinity, then the result is
// infinity.
if (mpfr_inf_p(lr) || mpfr_inf_p(li))
{
mpfr_set_ui(lr, mpfr_inf_p(lr) ? 1 : 0, GMP_RNDN);
mpfr_copysign(lr, lr, left_real, GMP_RNDN);
mpfr_set_ui(li, mpfr_inf_p(li) ? 1 : 0, GMP_RNDN);
mpfr_copysign(li, li, left_imag, GMP_RNDN);
if (mpfr_nan_p(rr))
{
mpfr_set_ui(rr, 0, GMP_RNDN);
mpfr_copysign(rr, rr, right_real, GMP_RNDN);
}
if (mpfr_nan_p(ri))
{
mpfr_set_ui(ri, 0, GMP_RNDN);
mpfr_copysign(ri, ri, right_imag, GMP_RNDN);
}
is_infinity = true;
}
// If the right side is infinity, then the result is
// infinity.
if (mpfr_inf_p(rr) || mpfr_inf_p(ri))
{
mpfr_set_ui(rr, mpfr_inf_p(rr) ? 1 : 0, GMP_RNDN);
mpfr_copysign(rr, rr, right_real, GMP_RNDN);
mpfr_set_ui(ri, mpfr_inf_p(ri) ? 1 : 0, GMP_RNDN);
mpfr_copysign(ri, ri, right_imag, GMP_RNDN);
if (mpfr_nan_p(lr))
{
mpfr_set_ui(lr, 0, GMP_RNDN);
mpfr_copysign(lr, lr, left_real, GMP_RNDN);
}
if (mpfr_nan_p(li))
{
mpfr_set_ui(li, 0, GMP_RNDN);
mpfr_copysign(li, li, left_imag, GMP_RNDN);
}
is_infinity = true;
}
// If we got an overflow in the intermediate computations,
// then the result is infinity.
if (!is_infinity
&& (mpfr_inf_p(lrrr) || mpfr_inf_p(lrri)
|| mpfr_inf_p(lirr) || mpfr_inf_p(liri)))
{
if (mpfr_nan_p(lr))
{
mpfr_set_ui(lr, 0, GMP_RNDN);
mpfr_copysign(lr, lr, left_real, GMP_RNDN);
}
if (mpfr_nan_p(li))
{
mpfr_set_ui(li, 0, GMP_RNDN);
mpfr_copysign(li, li, left_imag, GMP_RNDN);
}
if (mpfr_nan_p(rr))
{
mpfr_set_ui(rr, 0, GMP_RNDN);
mpfr_copysign(rr, rr, right_real, GMP_RNDN);
}
if (mpfr_nan_p(ri))
{
mpfr_set_ui(ri, 0, GMP_RNDN);
mpfr_copysign(ri, ri, right_imag, GMP_RNDN);
}
is_infinity = true;
}
if (is_infinity)
{
mpfr_mul(lrrr, lr, rr, GMP_RNDN);
mpfr_mul(lrri, lr, ri, GMP_RNDN);
mpfr_mul(lirr, li, rr, GMP_RNDN);
mpfr_mul(liri, li, ri, GMP_RNDN);
mpfr_sub(real, lrrr, liri, GMP_RNDN);
mpfr_add(imag, lrri, lirr, GMP_RNDN);
mpfr_set_inf(real, mpfr_sgn(real));
mpfr_set_inf(imag, mpfr_sgn(imag));
}
mpfr_clear(lr);
mpfr_clear(li);
mpfr_clear(rr);
mpfr_clear(ri);
}
mpfr_clear(lrrr);
mpfr_clear(lrri);
mpfr_clear(lirr);
mpfr_clear(liri);
}
break; break;
case OPERATOR_DIV: case OPERATOR_DIV:
{ if (mpc_cmp_si(right_val, 0) == 0)
// For complex division we want to avoid having an
// intermediate overflow turn the whole result in a NaN. We
// scale the values to try to avoid this.
if (mpfr_zero_p(right_real) && mpfr_zero_p(right_imag))
{ {
error_at(location, "division by zero"); error_at(location, "division by zero");
mpfr_set_ui(real, 0, GMP_RNDN); mpc_set_ui(val, 0, MPC_RNDNN);
mpfr_set_ui(imag, 0, GMP_RNDN);
break; break;
} }
mpc_div(val, left_val, right_val, MPC_RNDNN);
mpfr_t rra;
mpfr_t ria;
mpfr_init(rra);
mpfr_init(ria);
mpfr_abs(rra, right_real, GMP_RNDN);
mpfr_abs(ria, right_imag, GMP_RNDN);
mpfr_t t;
mpfr_init(t);
mpfr_max(t, rra, ria, GMP_RNDN);
mpfr_t rr;
mpfr_t ri;
mpfr_init_set(rr, right_real, GMP_RNDN);
mpfr_init_set(ri, right_imag, GMP_RNDN);
long ilogbw = 0;
if (!mpfr_inf_p(t) && !mpfr_nan_p(t) && !mpfr_zero_p(t))
{
ilogbw = mpfr_get_exp(t);
mpfr_mul_2si(rr, rr, - ilogbw, GMP_RNDN);
mpfr_mul_2si(ri, ri, - ilogbw, GMP_RNDN);
}
mpfr_t denom;
mpfr_init(denom);
mpfr_mul(denom, rr, rr, GMP_RNDN);
mpfr_mul(t, ri, ri, GMP_RNDN);
mpfr_add(denom, denom, t, GMP_RNDN);
mpfr_mul(real, left_real, rr, GMP_RNDN);
mpfr_mul(t, left_imag, ri, GMP_RNDN);
mpfr_add(real, real, t, GMP_RNDN);
mpfr_div(real, real, denom, GMP_RNDN);
mpfr_mul_2si(real, real, - ilogbw, GMP_RNDN);
mpfr_mul(imag, left_imag, rr, GMP_RNDN);
mpfr_mul(t, left_real, ri, GMP_RNDN);
mpfr_sub(imag, imag, t, GMP_RNDN);
mpfr_div(imag, imag, denom, GMP_RNDN);
mpfr_mul_2si(imag, imag, - ilogbw, GMP_RNDN);
// If we wind up with NaN on both sides, check whether we
// should really have infinity. The rule is that if either
// side of the complex number is infinity, then the whole
// value is infinity, even if the other side is NaN. So the
// only case we have to fix is the one in which both sides are
// NaN.
if (mpfr_nan_p(real) && mpfr_nan_p(imag)
&& (!mpfr_nan_p(left_real) || !mpfr_nan_p(left_imag))
&& (!mpfr_nan_p(right_real) || !mpfr_nan_p(right_imag)))
{
if (mpfr_zero_p(denom))
{
mpfr_set_inf(real, mpfr_sgn(rr));
mpfr_mul(real, real, left_real, GMP_RNDN);
mpfr_set_inf(imag, mpfr_sgn(rr));
mpfr_mul(imag, imag, left_imag, GMP_RNDN);
}
else if ((mpfr_inf_p(left_real) || mpfr_inf_p(left_imag))
&& mpfr_number_p(rr) && mpfr_number_p(ri))
{
mpfr_set_ui(t, mpfr_inf_p(left_real) ? 1 : 0, GMP_RNDN);
mpfr_copysign(t, t, left_real, GMP_RNDN);
mpfr_t t2;
mpfr_init_set_ui(t2, mpfr_inf_p(left_imag) ? 1 : 0, GMP_RNDN);
mpfr_copysign(t2, t2, left_imag, GMP_RNDN);
mpfr_t t3;
mpfr_init(t3);
mpfr_mul(t3, t, rr, GMP_RNDN);
mpfr_t t4;
mpfr_init(t4);
mpfr_mul(t4, t2, ri, GMP_RNDN);
mpfr_add(t3, t3, t4, GMP_RNDN);
mpfr_set_inf(real, mpfr_sgn(t3));
mpfr_mul(t3, t2, rr, GMP_RNDN);
mpfr_mul(t4, t, ri, GMP_RNDN);
mpfr_sub(t3, t3, t4, GMP_RNDN);
mpfr_set_inf(imag, mpfr_sgn(t3));
mpfr_clear(t2);
mpfr_clear(t3);
mpfr_clear(t4);
}
else if ((mpfr_inf_p(right_real) || mpfr_inf_p(right_imag))
&& mpfr_number_p(left_real) && mpfr_number_p(left_imag))
{
mpfr_set_ui(t, mpfr_inf_p(rr) ? 1 : 0, GMP_RNDN);
mpfr_copysign(t, t, rr, GMP_RNDN);
mpfr_t t2;
mpfr_init_set_ui(t2, mpfr_inf_p(ri) ? 1 : 0, GMP_RNDN);
mpfr_copysign(t2, t2, ri, GMP_RNDN);
mpfr_t t3;
mpfr_init(t3);
mpfr_mul(t3, left_real, t, GMP_RNDN);
mpfr_t t4;
mpfr_init(t4);
mpfr_mul(t4, left_imag, t2, GMP_RNDN);
mpfr_add(t3, t3, t4, GMP_RNDN);
mpfr_set_ui(real, 0, GMP_RNDN);
mpfr_mul(real, real, t3, GMP_RNDN);
mpfr_mul(t3, left_imag, t, GMP_RNDN);
mpfr_mul(t4, left_real, t2, GMP_RNDN);
mpfr_sub(t3, t3, t4, GMP_RNDN);
mpfr_set_ui(imag, 0, GMP_RNDN);
mpfr_mul(imag, imag, t3, GMP_RNDN);
mpfr_clear(t2);
mpfr_clear(t3);
mpfr_clear(t4);
}
}
mpfr_clear(denom);
mpfr_clear(rr);
mpfr_clear(ri);
mpfr_clear(t);
mpfr_clear(rra);
mpfr_clear(ria);
}
break; break;
default: default:
go_unreachable(); go_unreachable();
} }
mpfr_clear(left_real); mpc_clear(left_val);
mpfr_clear(left_imag); mpc_clear(right_val);
mpfr_clear(right_real);
mpfr_clear(right_imag);
nc->set_complex(NULL, real, imag); nc->set_complex(NULL, val);
mpfr_clear(real); mpc_clear(val);
mpfr_clear(imag);
return ret; return ret;
} }
...@@ -7397,9 +7098,9 @@ Builtin_call_expression::check_int_value(Expression* e, bool is_length) ...@@ -7397,9 +7098,9 @@ Builtin_call_expression::check_int_value(Expression* e, bool is_length)
} }
// Return the type of the real or imag functions, given the type of // Return the type of the real or imag functions, given the type of
// the argument. We need to map complex to float, complex64 to // the argument. We need to map complex64 to float32 and complex128
// float32, and complex128 to float64, so it has to be done by name. // to float64, so it has to be done by name. This returns NULL if it
// This returns NULL if it can't figure out the type. // can't figure out the type.
Type* Type*
Builtin_call_expression::real_imag_type(Type* arg_type) Builtin_call_expression::real_imag_type(Type* arg_type)
...@@ -7713,16 +7414,16 @@ Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const ...@@ -7713,16 +7414,16 @@ Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const
if (!arg->numeric_constant_value(&argnc)) if (!arg->numeric_constant_value(&argnc))
return false; return false;
mpfr_t real; mpc_t val;
mpfr_t imag; if (!argnc.to_complex(&val))
if (!argnc.to_complex(&real, &imag))
return false; return false;
Type* type = Builtin_call_expression::real_imag_type(argnc.type()); Type* type = Builtin_call_expression::real_imag_type(argnc.type());
if (this->code_ == BUILTIN_REAL) if (this->code_ == BUILTIN_REAL)
nc->set_float(type, real); nc->set_float(type, mpc_realref(val));
else else
nc->set_float(type, imag); nc->set_float(type, mpc_imagref(val));
mpc_clear(val);
return true; return true;
} }
else if (this->code_ == BUILTIN_COMPLEX) else if (this->code_ == BUILTIN_COMPLEX)
...@@ -7759,12 +7460,17 @@ Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const ...@@ -7759,12 +7460,17 @@ Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const
if (arg_type == NULL || arg_type->is_abstract()) if (arg_type == NULL || arg_type->is_abstract())
arg_type = inc.type(); arg_type = inc.type();
Type* type = Builtin_call_expression::complex_type(arg_type); mpc_t val;
nc->set_complex(type, r, i); mpc_init2(val, mpc_precision);
mpc_set_fr_fr(val, r, i, MPC_RNDNN);
mpfr_clear(r); mpfr_clear(r);
mpfr_clear(i); mpfr_clear(i);
Type* type = Builtin_call_expression::complex_type(arg_type);
nc->set_complex(type, val);
mpc_clear(val);
return true; return true;
} }
...@@ -8690,11 +8396,10 @@ Builtin_call_expression::do_export(Export* exp) const ...@@ -8690,11 +8396,10 @@ Builtin_call_expression::do_export(Export* exp) const
} }
else if (nc.is_complex()) else if (nc.is_complex())
{ {
mpfr_t real; mpc_t cval;
mpfr_t imag; nc.get_complex(&cval);
Complex_expression::export_complex(exp, real, imag); Complex_expression::export_complex(exp, cval);
mpfr_clear(real); mpc_clear(cval);
mpfr_clear(imag);
} }
else else
go_unreachable(); go_unreachable();
...@@ -15333,10 +15038,8 @@ Numeric_constant::Numeric_constant(const Numeric_constant& a) ...@@ -15333,10 +15038,8 @@ Numeric_constant::Numeric_constant(const Numeric_constant& a)
mpfr_init_set(this->u_.float_val, a.u_.float_val, GMP_RNDN); mpfr_init_set(this->u_.float_val, a.u_.float_val, GMP_RNDN);
break; break;
case NC_COMPLEX: case NC_COMPLEX:
mpfr_init_set(this->u_.complex_val.real, a.u_.complex_val.real, mpc_init2(this->u_.complex_val, mpc_precision);
GMP_RNDN); mpc_set(this->u_.complex_val, a.u_.complex_val, MPC_RNDNN);
mpfr_init_set(this->u_.complex_val.imag, a.u_.complex_val.imag,
GMP_RNDN);
break; break;
default: default:
go_unreachable(); go_unreachable();
...@@ -15363,10 +15066,8 @@ Numeric_constant::operator=(const Numeric_constant& a) ...@@ -15363,10 +15066,8 @@ Numeric_constant::operator=(const Numeric_constant& a)
mpfr_init_set(this->u_.float_val, a.u_.float_val, GMP_RNDN); mpfr_init_set(this->u_.float_val, a.u_.float_val, GMP_RNDN);
break; break;
case NC_COMPLEX: case NC_COMPLEX:
mpfr_init_set(this->u_.complex_val.real, a.u_.complex_val.real, mpc_init2(this->u_.complex_val, mpc_precision);
GMP_RNDN); mpc_set(this->u_.complex_val, a.u_.complex_val, MPC_RNDNN);
mpfr_init_set(this->u_.complex_val.imag, a.u_.complex_val.imag,
GMP_RNDN);
break; break;
default: default:
go_unreachable(); go_unreachable();
...@@ -15391,8 +15092,7 @@ Numeric_constant::clear() ...@@ -15391,8 +15092,7 @@ Numeric_constant::clear()
mpfr_clear(this->u_.float_val); mpfr_clear(this->u_.float_val);
break; break;
case NC_COMPLEX: case NC_COMPLEX:
mpfr_clear(this->u_.complex_val.real); mpc_clear(this->u_.complex_val);
mpfr_clear(this->u_.complex_val.imag);
break; break;
default: default:
go_unreachable(); go_unreachable();
...@@ -15453,13 +15153,13 @@ Numeric_constant::set_float(Type* type, const mpfr_t val) ...@@ -15453,13 +15153,13 @@ Numeric_constant::set_float(Type* type, const mpfr_t val)
// Set to a complex value. // Set to a complex value.
void void
Numeric_constant::set_complex(Type* type, const mpfr_t real, const mpfr_t imag) Numeric_constant::set_complex(Type* type, const mpc_t val)
{ {
this->clear(); this->clear();
this->classification_ = NC_COMPLEX; this->classification_ = NC_COMPLEX;
this->type_ = type; this->type_ = type;
mpfr_init_set(this->u_.complex_val.real, real, GMP_RNDN); mpc_init2(this->u_.complex_val, mpc_precision);
mpfr_init_set(this->u_.complex_val.imag, imag, GMP_RNDN); mpc_set(this->u_.complex_val, val, MPC_RNDNN);
} }
// Get an int value. // Get an int value.
...@@ -15492,11 +15192,11 @@ Numeric_constant::get_float(mpfr_t* val) const ...@@ -15492,11 +15192,11 @@ Numeric_constant::get_float(mpfr_t* val) const
// Get a complex value. // Get a complex value.
void void
Numeric_constant::get_complex(mpfr_t* real, mpfr_t* imag) const Numeric_constant::get_complex(mpc_t* val) const
{ {
go_assert(this->is_complex()); go_assert(this->is_complex());
mpfr_init_set(*real, this->u_.complex_val.real, GMP_RNDN); mpc_init2(*val, mpc_precision);
mpfr_init_set(*imag, this->u_.complex_val.imag, GMP_RNDN); mpc_set(*val, this->u_.complex_val, MPC_RNDNN);
} }
// Express value as unsigned long if possible. // Express value as unsigned long if possible.
...@@ -15512,9 +15212,10 @@ Numeric_constant::to_unsigned_long(unsigned long* val) const ...@@ -15512,9 +15212,10 @@ Numeric_constant::to_unsigned_long(unsigned long* val) const
case NC_FLOAT: case NC_FLOAT:
return this->mpfr_to_unsigned_long(this->u_.float_val, val); return this->mpfr_to_unsigned_long(this->u_.float_val, val);
case NC_COMPLEX: case NC_COMPLEX:
if (!mpfr_zero_p(this->u_.complex_val.imag)) if (!mpfr_zero_p(mpc_imagref(this->u_.complex_val)))
return NC_UL_NOTINT; return NC_UL_NOTINT;
return this->mpfr_to_unsigned_long(this->u_.complex_val.real, val); return this->mpfr_to_unsigned_long(mpc_realref(this->u_.complex_val),
val);
default: default:
go_unreachable(); go_unreachable();
} }
...@@ -15569,11 +15270,11 @@ Numeric_constant::to_int(mpz_t* val) const ...@@ -15569,11 +15270,11 @@ Numeric_constant::to_int(mpz_t* val) const
mpfr_get_z(*val, this->u_.float_val, GMP_RNDN); mpfr_get_z(*val, this->u_.float_val, GMP_RNDN);
return true; return true;
case NC_COMPLEX: case NC_COMPLEX:
if (!mpfr_zero_p(this->u_.complex_val.imag) if (!mpfr_zero_p(mpc_imagref(this->u_.complex_val))
|| !mpfr_integer_p(this->u_.complex_val.real)) || !mpfr_integer_p(mpc_realref(this->u_.complex_val)))
return false; return false;
mpz_init(*val); mpz_init(*val);
mpfr_get_z(*val, this->u_.complex_val.real, GMP_RNDN); mpfr_get_z(*val, mpc_realref(this->u_.complex_val), GMP_RNDN);
return true; return true;
default: default:
go_unreachable(); go_unreachable();
...@@ -15595,9 +15296,9 @@ Numeric_constant::to_float(mpfr_t* val) const ...@@ -15595,9 +15296,9 @@ Numeric_constant::to_float(mpfr_t* val) const
mpfr_init_set(*val, this->u_.float_val, GMP_RNDN); mpfr_init_set(*val, this->u_.float_val, GMP_RNDN);
return true; return true;
case NC_COMPLEX: case NC_COMPLEX:
if (!mpfr_zero_p(this->u_.complex_val.imag)) if (!mpfr_zero_p(mpc_imagref(this->u_.complex_val)))
return false; return false;
mpfr_init_set(*val, this->u_.complex_val.real, GMP_RNDN); mpfr_init_set(*val, mpc_realref(this->u_.complex_val), GMP_RNDN);
return true; return true;
default: default:
go_unreachable(); go_unreachable();
...@@ -15607,22 +15308,20 @@ Numeric_constant::to_float(mpfr_t* val) const ...@@ -15607,22 +15308,20 @@ Numeric_constant::to_float(mpfr_t* val) const
// Convert value to complex. // Convert value to complex.
bool bool
Numeric_constant::to_complex(mpfr_t* vr, mpfr_t* vi) const Numeric_constant::to_complex(mpc_t* val) const
{ {
mpc_init2(*val, mpc_precision);
switch (this->classification_) switch (this->classification_)
{ {
case NC_INT: case NC_INT:
case NC_RUNE: case NC_RUNE:
mpfr_init_set_z(*vr, this->u_.int_val, GMP_RNDN); mpc_set_z(*val, this->u_.int_val, MPC_RNDNN);
mpfr_init_set_ui(*vi, 0, GMP_RNDN);
return true; return true;
case NC_FLOAT: case NC_FLOAT:
mpfr_init_set(*vr, this->u_.float_val, GMP_RNDN); mpc_set_fr(*val, this->u_.float_val, MPC_RNDNN);
mpfr_init_set_ui(*vi, 0, GMP_RNDN);
return true; return true;
case NC_COMPLEX: case NC_COMPLEX:
mpfr_init_set(*vr, this->u_.complex_val.real, GMP_RNDN); mpc_set(*val, this->u_.complex_val, MPC_RNDNN);
mpfr_init_set(*vi, this->u_.complex_val.imag, GMP_RNDN);
return true; return true;
default: default:
go_unreachable(); go_unreachable();
...@@ -15700,15 +15399,15 @@ Numeric_constant::check_int_type(Integer_type* type, bool issue_error, ...@@ -15700,15 +15399,15 @@ Numeric_constant::check_int_type(Integer_type* type, bool issue_error,
break; break;
case NC_COMPLEX: case NC_COMPLEX:
if (!mpfr_integer_p(this->u_.complex_val.real) if (!mpfr_integer_p(mpc_realref(this->u_.complex_val))
|| !mpfr_zero_p(this->u_.complex_val.imag)) || !mpfr_zero_p(mpc_imagref(this->u_.complex_val)))
{ {
if (issue_error) if (issue_error)
error_at(location, "complex constant truncated to integer"); error_at(location, "complex constant truncated to integer");
return false; return false;
} }
mpz_init(val); mpz_init(val);
mpfr_get_z(val, this->u_.complex_val.real, GMP_RNDN); mpfr_get_z(val, mpc_realref(this->u_.complex_val), GMP_RNDN);
break; break;
default: default:
...@@ -15767,13 +15466,13 @@ Numeric_constant::check_float_type(Float_type* type, bool issue_error, ...@@ -15767,13 +15466,13 @@ Numeric_constant::check_float_type(Float_type* type, bool issue_error,
break; break;
case NC_COMPLEX: case NC_COMPLEX:
if (!mpfr_zero_p(this->u_.complex_val.imag)) if (!mpfr_zero_p(mpc_imagref(this->u_.complex_val)))
{ {
if (issue_error) if (issue_error)
error_at(location, "complex constant truncated to float"); error_at(location, "complex constant truncated to float");
return false; return false;
} }
mpfr_init_set(val, this->u_.complex_val.real, GMP_RNDN); mpfr_init_set(val, mpc_realref(this->u_.complex_val), GMP_RNDN);
break; break;
default: default:
...@@ -15860,24 +15559,21 @@ Numeric_constant::check_complex_type(Complex_type* type, bool issue_error, ...@@ -15860,24 +15559,21 @@ Numeric_constant::check_complex_type(Complex_type* type, bool issue_error,
go_unreachable(); go_unreachable();
} }
mpfr_t real; mpc_t val;
mpfr_t imag; mpc_init2(val, mpc_precision);
switch (this->classification_) switch (this->classification_)
{ {
case NC_INT: case NC_INT:
case NC_RUNE: case NC_RUNE:
mpfr_init_set_z(real, this->u_.int_val, GMP_RNDN); mpc_set_z(val, this->u_.int_val, MPC_RNDNN);
mpfr_init_set_ui(imag, 0, GMP_RNDN);
break; break;
case NC_FLOAT: case NC_FLOAT:
mpfr_init_set(real, this->u_.float_val, GMP_RNDN); mpc_set_fr(val, this->u_.float_val, MPC_RNDNN);
mpfr_init_set_ui(imag, 0, GMP_RNDN);
break; break;
case NC_COMPLEX: case NC_COMPLEX:
mpfr_init_set(real, this->u_.complex_val.real, GMP_RNDN); mpc_set(val, this->u_.complex_val, MPC_RNDNN);
mpfr_init_set(imag, this->u_.complex_val.imag, GMP_RNDN);
break; break;
default: default:
...@@ -15885,20 +15581,20 @@ Numeric_constant::check_complex_type(Complex_type* type, bool issue_error, ...@@ -15885,20 +15581,20 @@ Numeric_constant::check_complex_type(Complex_type* type, bool issue_error,
} }
bool ret = true; bool ret = true;
if (!mpfr_nan_p(real) if (!mpfr_nan_p(mpc_realref(val))
&& !mpfr_inf_p(real) && !mpfr_inf_p(mpc_realref(val))
&& !mpfr_zero_p(real) && !mpfr_zero_p(mpc_realref(val))
&& mpfr_get_exp(real) > max_exp) && mpfr_get_exp(mpc_realref(val)) > max_exp)
{ {
if (issue_error) if (issue_error)
error_at(location, "complex real part overflow"); error_at(location, "complex real part overflow");
ret = false; ret = false;
} }
if (!mpfr_nan_p(imag) if (!mpfr_nan_p(mpc_imagref(val))
&& !mpfr_inf_p(imag) && !mpfr_inf_p(mpc_imagref(val))
&& !mpfr_zero_p(imag) && !mpfr_zero_p(mpc_imagref(val))
&& mpfr_get_exp(imag) > max_exp) && mpfr_get_exp(mpc_imagref(val)) > max_exp)
{ {
if (issue_error) if (issue_error)
error_at(location, "complex imaginary part overflow"); error_at(location, "complex imaginary part overflow");
...@@ -15908,30 +15604,26 @@ Numeric_constant::check_complex_type(Complex_type* type, bool issue_error, ...@@ -15908,30 +15604,26 @@ Numeric_constant::check_complex_type(Complex_type* type, bool issue_error,
if (ret) if (ret)
{ {
// Round the constant to the desired type. // Round the constant to the desired type.
mpfr_t t; mpc_t t;
mpfr_init(t);
switch (type->bits()) switch (type->bits())
{ {
case 64: case 64:
mpfr_set_prec(t, 24); mpc_init2(t, 24);
break; break;
case 128: case 128:
mpfr_set_prec(t, 53); mpc_init2(t, 53);
break; break;
default: default:
go_unreachable(); go_unreachable();
} }
mpfr_set(t, real, GMP_RNDN); mpc_set(t, val, MPC_RNDNN);
mpfr_set(real, t, GMP_RNDN); mpc_set(val, t, MPC_RNDNN);
mpfr_set(t, imag, GMP_RNDN); mpc_clear(t);
mpfr_set(imag, t, GMP_RNDN);
mpfr_clear(t);
this->set_complex(type, real, imag); this->set_complex(type, val);
} }
mpfr_clear(real); mpc_clear(val);
mpfr_clear(imag);
return ret; return ret;
} }
...@@ -15950,9 +15642,7 @@ Numeric_constant::expression(Location loc) const ...@@ -15950,9 +15642,7 @@ Numeric_constant::expression(Location loc) const
case NC_FLOAT: case NC_FLOAT:
return Expression::make_float(&this->u_.float_val, this->type_, loc); return Expression::make_float(&this->u_.float_val, this->type_, loc);
case NC_COMPLEX: case NC_COMPLEX:
return Expression::make_complex(&this->u_.complex_val.real, return Expression::make_complex(&this->u_.complex_val, this->type_, loc);
&this->u_.complex_val.imag,
this->type_, loc);
default: default:
go_unreachable(); go_unreachable();
} }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#define GO_EXPRESSIONS_H #define GO_EXPRESSIONS_H
#include <mpfr.h> #include <mpfr.h>
#include <mpc.h>
#include "operator.h" #include "operator.h"
...@@ -52,6 +53,9 @@ class Label; ...@@ -52,6 +53,9 @@ class Label;
class Ast_dump_context; class Ast_dump_context;
class String_dump; class String_dump;
// The precision to use for complex values represented as an mpc_t.
const int mpc_precision = 256;
// The base class for all expressions. // The base class for all expressions.
class Expression class Expression
...@@ -237,7 +241,7 @@ class Expression ...@@ -237,7 +241,7 @@ class Expression
// Make a constant complex expression. TYPE should be NULL for an // Make a constant complex expression. TYPE should be NULL for an
// abstract type. // abstract type.
static Expression* static Expression*
make_complex(const mpfr_t* real, const mpfr_t* imag, Type*, Location); make_complex(const mpc_t*, Type*, Location);
// Make a nil expression. // Make a nil expression.
static Expression* static Expression*
...@@ -2585,7 +2589,7 @@ class Numeric_constant ...@@ -2585,7 +2589,7 @@ class Numeric_constant
// Set to a complex value. // Set to a complex value.
void void
set_complex(Type*, const mpfr_t, const mpfr_t); set_complex(Type*, const mpc_t);
// Classifiers. // Classifiers.
bool bool
...@@ -2617,7 +2621,7 @@ class Numeric_constant ...@@ -2617,7 +2621,7 @@ class Numeric_constant
get_float(mpfr_t*) const; get_float(mpfr_t*) const;
void void
get_complex(mpfr_t*, mpfr_t*) const; get_complex(mpc_t*) const;
// Codes returned by to_unsigned_long. // Codes returned by to_unsigned_long.
enum To_unsigned_long enum To_unsigned_long
...@@ -2653,7 +2657,7 @@ class Numeric_constant ...@@ -2653,7 +2657,7 @@ class Numeric_constant
// If the value can be expressed as a complex, return true and // If the value can be expressed as a complex, return true and
// initialize and set VR and VI. // initialize and set VR and VI.
bool bool
to_complex(mpfr_t* vr, mpfr_t* vi) const; to_complex(mpc_t* val) const;
// Get the type. // Get the type.
Type* Type*
...@@ -2709,11 +2713,7 @@ class Numeric_constant ...@@ -2709,11 +2713,7 @@ class Numeric_constant
// If NC_FLOAT. // If NC_FLOAT.
mpfr_t float_val; mpfr_t float_val;
// If NC_COMPLEX. // If NC_COMPLEX.
struct mpc_t complex_val;
{
mpfr_t real;
mpfr_t imag;
} complex_val;
} u_; } u_;
// The type if there is one. This will be NULL for an untyped // The type if there is one. This will be NULL for an untyped
// constant. // constant.
......
...@@ -2525,9 +2525,12 @@ Parse::operand(bool may_be_sink, bool* is_parenthesized) ...@@ -2525,9 +2525,12 @@ Parse::operand(bool may_be_sink, bool* is_parenthesized)
{ {
mpfr_t zero; mpfr_t zero;
mpfr_init_set_ui(zero, 0, GMP_RNDN); mpfr_init_set_ui(zero, 0, GMP_RNDN);
ret = Expression::make_complex(&zero, token->imaginary_value(), mpc_t val;
NULL, token->location()); mpc_init2(val, mpc_precision);
mpc_set_fr_fr(val, zero, *token->imaginary_value(), MPC_RNDNN);
mpfr_clear(zero); mpfr_clear(zero);
ret = Expression::make_complex(&val, NULL, token->location());
mpc_clear(val);
this->advance_token(); this->advance_token();
return ret; return ret;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment