/* gcalc-constant.c generated by valac 0.56.0, the Vala compiler
 * generated from gcalc-constant.vala, do not modify */

/* gcalc-constant.vala
 *
 * Copyright (C) 2018  Daniel Espinosa <esodan@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *      Daniel Espinosa <esodan@gmail.com>
 */

#include "gcalc/gcalc.h"
#include <mpc.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <mpfr.h>
#include <float.h>
#include <math.h>
#include "mpfrg.h"
#include "gcalc.h"

enum  {
	GCALC_CONSTANT_0_PROPERTY,
	GCALC_CONSTANT_NUM_PROPERTIES
};
static GParamSpec* gcalc_constant_properties[GCALC_CONSTANT_NUM_PROPERTIES];
#define _g_free0(var) (var = (g_free (var), NULL))
#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);

struct _GCalcConstantPrivate {
	__mpc_struct _complex;
};

static gint GCalcConstant_private_offset;
static gpointer gcalc_constant_parent_class = NULL;
static GCalcMathConstantIface * gcalc_constant_gcalc_math_constant_parent_iface = NULL;
static GCalcMathConstantNumberIface * gcalc_constant_gcalc_math_constant_number_parent_iface = NULL;
static GCalcMathConstantComplexIface * gcalc_constant_gcalc_math_constant_complex_parent_iface = NULL;

VALA_EXTERN gchar* gcalc_expression_to_string (GCalcExpression* self);
VALA_EXTERN GCalcMathResult* gcalc_expression_solve (GCalcExpression* self);
VALA_EXTERN void gcalc_constant_get_complex (GCalcConstant* self,
                                 __mpc_struct* result);
VALA_EXTERN GCalcConstant* gcalc_constant_new_internal_complex (__mpc_struct* complex);
VALA_EXTERN GCalcConstant* gcalc_constant_construct_internal_complex (GType object_type,
                                                          __mpc_struct* complex);
static gdouble gcalc_constant_real_real (GCalcMathConstantComplex* base);
static gdouble gcalc_constant_real_imag (GCalcMathConstantComplex* base);
static void gcalc_constant_real_zero (GCalcMathConstantComplex* base);
static gdouble gcalc_constant_real_value (GCalcMathConstantNumber* base);
static GCalcMathConstant* gcalc_constant_real_add (GCalcMathConstant* base,
                                            GCalcMathConstant* c);
static GCalcMathConstant* gcalc_constant_real_subtract (GCalcMathConstant* base,
                                                 GCalcMathConstant* c);
static GCalcMathConstant* gcalc_constant_real_multiply (GCalcMathConstant* base,
                                                 GCalcMathConstant* c);
static GCalcMathConstant* gcalc_constant_real_divide (GCalcMathConstant* base,
                                               GCalcMathConstant* c);
static GCalcMathConstant* gcalc_constant_real_neg (GCalcMathConstant* base);
static GCalcMathConstant* gcalc_constant_real_pow (GCalcMathConstant* base,
                                            GCalcMathConstant* c);
static gchar* gcalc_constant_real_to_string (GCalcExpression* base);
static GCalcMathResult* gcalc_constant_real_solve (GCalcExpression* base);
static GObject * gcalc_constant_constructor (GType type,
                                      guint n_construct_properties,
                                      GObjectConstructParam * construct_properties);
static void gcalc_constant_finalize (GObject * obj);
static GType gcalc_constant_get_type_once (void);

static inline gpointer
gcalc_constant_get_instance_private (GCalcConstant* self)
{
	return G_STRUCT_MEMBER_P (self, GCalcConstant_private_offset);
}

void
gcalc_constant_get_complex (GCalcConstant* self,
                            __mpc_struct* result)
{
	g_return_if_fail (self != NULL);
	*result = self->priv->_complex;
	return;
}

GCalcConstant*
gcalc_constant_construct_internal_complex (GType object_type,
                                           __mpc_struct* complex)
{
	GCalcConstant * self = NULL;
	__mpc_struct _tmp0_;
	g_return_val_if_fail (complex != NULL, NULL);
	self = (GCalcConstant*) gcalc_expression_construct (object_type);
	_tmp0_ = *complex;
	mpc_set (&self->priv->_complex, &_tmp0_, MPC_RNDNN);
	return self;
}

GCalcConstant*
gcalc_constant_new_internal_complex (__mpc_struct* complex)
{
	return gcalc_constant_construct_internal_complex (GCALC_TYPE_CONSTANT, complex);
}

GCalcConstant*
gcalc_constant_construct_integer (GType object_type,
                                  gint val)
{
	GCalcConstant * self = NULL;
	self = (GCalcConstant*) gcalc_expression_construct (object_type);
	mpc_set_d_d (&self->priv->_complex, (gdouble) val, (gdouble) 0, MPC_RNDNN);
	return self;
}

GCalcConstant*
gcalc_constant_new_integer (gint val)
{
	return gcalc_constant_construct_integer (GCALC_TYPE_CONSTANT, val);
}

GCalcConstant*
gcalc_constant_construct_unsigned_integer (GType object_type,
                                           guint val)
{
	GCalcConstant * self = NULL;
	self = (GCalcConstant*) gcalc_expression_construct (object_type);
	mpc_set_d_d (&self->priv->_complex, (gdouble) val, (gdouble) 0, MPC_RNDNN);
	return self;
}

GCalcConstant*
gcalc_constant_new_unsigned_integer (guint val)
{
	return gcalc_constant_construct_unsigned_integer (GCALC_TYPE_CONSTANT, val);
}

GCalcConstant*
gcalc_constant_construct_double (GType object_type,
                                 gdouble val)
{
	GCalcConstant * self = NULL;
	self = (GCalcConstant*) gcalc_expression_construct (object_type);
	mpc_set_d_d (&self->priv->_complex, val, (gdouble) 0, MPC_RNDNN);
	return self;
}

GCalcConstant*
gcalc_constant_new_double (gdouble val)
{
	return gcalc_constant_construct_double (GCALC_TYPE_CONSTANT, val);
}

GCalcConstant*
gcalc_constant_construct_complex (GType object_type,
                                  gdouble real,
                                  gdouble imag)
{
	GCalcConstant * self = NULL;
	self = (GCalcConstant*) gcalc_expression_construct (object_type);
	mpc_set_d_d (&self->priv->_complex, real, imag, MPC_RNDNN);
	return self;
}

GCalcConstant*
gcalc_constant_new_complex (gdouble real,
                            gdouble imag)
{
	return gcalc_constant_construct_complex (GCALC_TYPE_CONSTANT, real, imag);
}

static gdouble
mpc_get_real_double (__mpc_struct *self)
{
	__mpfr_struct r = {0};
	MPFRGRealRef* _tmp0_;
	gdouble result;
	mpfr_init2 (&r, (mpfr_prec_t) 1000);
	_tmp0_ = mpc_realref (&(*self));
	mpfr_set (&r, &_tmp0_->val, MPFR_RNDN);
	result = mpfr_get_d (&r, MPFR_RNDN);
	mpfr_clear (&r);
	return result;
}

static gdouble
gcalc_constant_real_real (GCalcMathConstantComplex* base)
{
	GCalcConstant * self;
	gdouble result;
	self = (GCalcConstant*) base;
	result = mpc_get_real_double (&self->priv->_complex);
	return result;
}

static gdouble
mpc_get_imag_double (__mpc_struct *self)
{
	__mpfr_struct i = {0};
	MPFRGRealRef* _tmp0_;
	gdouble result;
	mpfr_init2 (&i, (mpfr_prec_t) 1000);
	_tmp0_ = mpc_imagref (&(*self));
	mpfr_set (&i, &_tmp0_->val, MPFR_RNDN);
	result = mpfr_get_d (&i, MPFR_RNDN);
	mpfr_clear (&i);
	return result;
}

static gdouble
gcalc_constant_real_imag (GCalcMathConstantComplex* base)
{
	GCalcConstant * self;
	gdouble result;
	self = (GCalcConstant*) base;
	result = mpc_get_imag_double (&self->priv->_complex);
	return result;
}

static gint
mpc_set_mpreal (__mpc_struct *self,
                __mpfr_struct* re,
                __mpfr_struct* im,
                mpc_rnd_t rnd)
{
	__mpfr_struct _tmp1_;
	__mpfr_struct _tmp2_;
	gint result;
	g_return_val_if_fail (re != NULL, 0);
	if (im == NULL) {
		__mpfr_struct _tmp0_;
		_tmp0_ = *re;
		result = mpc_set_fr (&(*self), &_tmp0_, rnd);
		return result;
	}
	_tmp1_ = *re;
	_tmp2_ = *im;
	result = mpc_set_fr_fr (&(*self), &_tmp1_, &_tmp2_, rnd);
	return result;
}

static void
gcalc_constant_real_zero (GCalcMathConstantComplex* base)
{
	GCalcConstant * self;
	__mpfr_struct r = {0};
	self = (GCalcConstant*) base;
	mpfr_init2 (&r, (mpfr_prec_t) 1000);
	mpfr_set_zero (&r, MPFR_RNDN);
	mpc_set_mpreal (&self->priv->_complex, &r, NULL, MPC_RNDNN);
	mpfr_clear (&r);
}

static gdouble
gcalc_constant_real_value (GCalcMathConstantNumber* base)
{
	GCalcConstant * self;
	gdouble result;
	self = (GCalcConstant*) base;
	result = gcalc_math_constant_complex_real ((GCalcMathConstantComplex*) self);
	return result;
}

static GCalcMathConstant*
gcalc_constant_real_add (GCalcMathConstant* base,
                         GCalcMathConstant* c)
{
	GCalcConstant * self;
	__mpc_struct res = {0};
	__mpc_struct p1 = {0};
	__mpc_struct _tmp0_ = {0};
	GCalcConstant* _tmp1_;
	GCalcMathConstant* result;
	self = (GCalcConstant*) base;
	g_return_val_if_fail (c != NULL, NULL);
	_vala_return_val_if_fail (GCALC_IS_CONSTANT (c), "c is Constant", NULL);
	mpc_init2 (&res, (mpfr_prec_t) 1000);
	mpc_init2 (&p1, (mpfr_prec_t) 1000);
	gcalc_constant_get_complex (G_TYPE_CHECK_INSTANCE_CAST (c, GCALC_TYPE_CONSTANT, GCalcConstant), &_tmp0_);
	mpc_set (&p1, &_tmp0_, MPC_RNDNN);
	mpc_add (&res, &self->priv->_complex, &p1, MPC_RNDNN);
	_tmp1_ = gcalc_constant_new_internal_complex (&res);
	result = (GCalcMathConstant*) _tmp1_;
	mpc_clear (&p1);
	mpc_clear (&res);
	return result;
}

static GCalcMathConstant*
gcalc_constant_real_subtract (GCalcMathConstant* base,
                              GCalcMathConstant* c)
{
	GCalcConstant * self;
	__mpc_struct res = {0};
	__mpc_struct p1 = {0};
	__mpc_struct _tmp0_ = {0};
	GCalcConstant* _tmp1_;
	GCalcMathConstant* result;
	self = (GCalcConstant*) base;
	g_return_val_if_fail (c != NULL, NULL);
	_vala_return_val_if_fail (GCALC_IS_CONSTANT (c), "c is Constant", NULL);
	mpc_init2 (&res, (mpfr_prec_t) 1000);
	mpc_init2 (&p1, (mpfr_prec_t) 1000);
	gcalc_constant_get_complex (G_TYPE_CHECK_INSTANCE_CAST (c, GCALC_TYPE_CONSTANT, GCalcConstant), &_tmp0_);
	mpc_set (&p1, &_tmp0_, MPC_RNDNN);
	mpc_sub (&res, &self->priv->_complex, &p1, MPC_RNDNN);
	_tmp1_ = gcalc_constant_new_internal_complex (&res);
	result = (GCalcMathConstant*) _tmp1_;
	mpc_clear (&p1);
	mpc_clear (&res);
	return result;
}

static GCalcMathConstant*
gcalc_constant_real_multiply (GCalcMathConstant* base,
                              GCalcMathConstant* c)
{
	GCalcConstant * self;
	__mpc_struct res = {0};
	__mpc_struct p1 = {0};
	__mpc_struct _tmp0_ = {0};
	GCalcConstant* _tmp1_;
	GCalcMathConstant* result;
	self = (GCalcConstant*) base;
	g_return_val_if_fail (c != NULL, NULL);
	_vala_return_val_if_fail (GCALC_IS_CONSTANT (c), "c is Constant", NULL);
	mpc_init2 (&res, (mpfr_prec_t) 1000);
	mpc_init2 (&p1, (mpfr_prec_t) 1000);
	gcalc_constant_get_complex (G_TYPE_CHECK_INSTANCE_CAST (c, GCALC_TYPE_CONSTANT, GCalcConstant), &_tmp0_);
	mpc_set (&p1, &_tmp0_, MPC_RNDNN);
	mpc_mul (&res, &self->priv->_complex, &p1, MPC_RNDNN);
	_tmp1_ = gcalc_constant_new_internal_complex (&res);
	result = (GCalcMathConstant*) _tmp1_;
	mpc_clear (&p1);
	mpc_clear (&res);
	return result;
}

static GCalcMathConstant*
gcalc_constant_real_divide (GCalcMathConstant* base,
                            GCalcMathConstant* c)
{
	GCalcConstant * self;
	__mpc_struct res = {0};
	__mpc_struct p1 = {0};
	__mpc_struct _tmp0_ = {0};
	GCalcConstant* _tmp1_;
	GCalcMathConstant* result;
	self = (GCalcConstant*) base;
	g_return_val_if_fail (c != NULL, NULL);
	_vala_return_val_if_fail (GCALC_IS_CONSTANT (c), "c is Constant", NULL);
	mpc_init2 (&res, (mpfr_prec_t) 1000);
	mpc_init2 (&p1, (mpfr_prec_t) 1000);
	gcalc_constant_get_complex (G_TYPE_CHECK_INSTANCE_CAST (c, GCALC_TYPE_CONSTANT, GCalcConstant), &_tmp0_);
	mpc_set (&p1, &_tmp0_, MPC_RNDNN);
	mpc_div (&res, &self->priv->_complex, &p1, MPC_RNDNN);
	_tmp1_ = gcalc_constant_new_internal_complex (&res);
	result = (GCalcMathConstant*) _tmp1_;
	mpc_clear (&p1);
	mpc_clear (&res);
	return result;
}

static GCalcMathConstant*
gcalc_constant_real_neg (GCalcMathConstant* base)
{
	GCalcConstant * self;
	__mpc_struct res = {0};
	GCalcConstant* _tmp0_;
	GCalcMathConstant* result;
	self = (GCalcConstant*) base;
	mpc_init2 (&res, (mpfr_prec_t) 1000);
	mpc_neg (&res, &self->priv->_complex, MPC_RNDNN);
	_tmp0_ = gcalc_constant_new_internal_complex (&res);
	result = (GCalcMathConstant*) _tmp0_;
	mpc_clear (&res);
	return result;
}

static GCalcMathConstant*
gcalc_constant_real_pow (GCalcMathConstant* base,
                         GCalcMathConstant* c)
{
	GCalcConstant * self;
	__mpc_struct res = {0};
	__mpc_struct p1 = {0};
	__mpc_struct _tmp0_ = {0};
	GCalcConstant* _tmp1_;
	GCalcMathConstant* result;
	self = (GCalcConstant*) base;
	g_return_val_if_fail (c != NULL, NULL);
	_vala_return_val_if_fail (GCALC_IS_CONSTANT (c), "c is Constant", NULL);
	mpc_init2 (&res, (mpfr_prec_t) 1000);
	mpc_init2 (&p1, (mpfr_prec_t) 1000);
	gcalc_constant_get_complex (G_TYPE_CHECK_INSTANCE_CAST (c, GCALC_TYPE_CONSTANT, GCalcConstant), &_tmp0_);
	mpc_set (&p1, &_tmp0_, MPC_RNDNN);
	mpc_pow (&res, &self->priv->_complex, &p1, MPC_RNDNN);
	_tmp1_ = gcalc_constant_new_internal_complex (&res);
	result = (GCalcMathConstant*) _tmp1_;
	mpc_clear (&p1);
	mpc_clear (&res);
	return result;
}

static gchar*
gcalc_constant_real_to_string (GCalcExpression* base)
{
	GCalcConstant * self;
	gchar* s = NULL;
	gchar* _tmp0_;
	gchar* result;
	self = (GCalcConstant*) base;
	_tmp0_ = g_strdup ("");
	s = _tmp0_;
	if (gcalc_math_constant_complex_imag ((GCalcMathConstantComplex*) self) != 0.0) {
		gboolean par = FALSE;
		gdouble im = 0.0;
		const gchar* _tmp13_;
		gchar* _tmp14_;
		par = FALSE;
		if (gcalc_math_constant_complex_real ((GCalcMathConstantComplex*) self) != 0.0) {
			GCalcMathExpression* _tmp1_;
			GCalcMathExpression* _tmp2_;
			const gchar* _tmp5_;
			gchar* _tmp6_;
			gchar* _tmp7_;
			gchar* _tmp8_;
			_tmp1_ = gcalc_math_expression_get_parent ((GCalcMathExpression*) self);
			_tmp2_ = _tmp1_;
			if (_tmp2_ != NULL) {
				const gchar* _tmp3_;
				gchar* _tmp4_;
				_tmp3_ = s;
				_tmp4_ = g_strconcat (_tmp3_, "(", NULL);
				_g_free0 (s);
				s = _tmp4_;
				par = TRUE;
			}
			_tmp5_ = s;
			_tmp6_ = g_strdup_printf ("%g", gcalc_math_constant_complex_real ((GCalcMathConstantComplex*) self));
			_tmp7_ = _tmp6_;
			_tmp8_ = g_strconcat (_tmp5_, _tmp7_, NULL);
			_g_free0 (s);
			s = _tmp8_;
			_g_free0 (_tmp7_);
		}
		im = gcalc_math_constant_complex_imag ((GCalcMathConstantComplex*) self);
		if (im < 0.0) {
			const gchar* _tmp9_;
			gchar* _tmp10_;
			_tmp9_ = s;
			_tmp10_ = g_strconcat (_tmp9_, "-", NULL);
			_g_free0 (s);
			s = _tmp10_;
			im = im * (-1.0);
		} else {
			if (gcalc_math_constant_complex_real ((GCalcMathConstantComplex*) self) != 0.0) {
				const gchar* _tmp11_;
				gchar* _tmp12_;
				_tmp11_ = s;
				_tmp12_ = g_strconcat (_tmp11_, "+", NULL);
				_g_free0 (s);
				s = _tmp12_;
			}
		}
		_tmp13_ = s;
		_tmp14_ = g_strconcat (_tmp13_, "i", NULL);
		_g_free0 (s);
		s = _tmp14_;
		if (im != 1.0) {
			const gchar* _tmp15_;
			gchar* _tmp16_;
			gchar* _tmp17_;
			gchar* _tmp18_;
			_tmp15_ = s;
			_tmp16_ = g_strdup_printf ("%g", im);
			_tmp17_ = _tmp16_;
			_tmp18_ = g_strconcat (_tmp15_, _tmp17_, NULL);
			_g_free0 (s);
			s = _tmp18_;
			_g_free0 (_tmp17_);
		}
		if (par) {
			const gchar* _tmp19_;
			gchar* _tmp20_;
			_tmp19_ = s;
			_tmp20_ = g_strconcat (_tmp19_, ")", NULL);
			_g_free0 (s);
			s = _tmp20_;
		}
	} else {
		gchar* _tmp21_;
		_tmp21_ = g_strdup_printf ("%g", gcalc_math_constant_complex_real ((GCalcMathConstantComplex*) self));
		_g_free0 (s);
		s = _tmp21_;
	}
	result = s;
	return result;
}

static GCalcMathResult*
gcalc_constant_real_solve (GCalcExpression* base)
{
	GCalcConstant * self;
	GCalcResult* _tmp0_;
	GCalcMathResult* result;
	self = (GCalcConstant*) base;
	_tmp0_ = gcalc_result_new ((GCalcMathExpression*) self);
	result = (GCalcMathResult*) _tmp0_;
	return result;
}

GCalcConstant*
gcalc_constant_construct (GType object_type)
{
	GCalcConstant * self = NULL;
	self = (GCalcConstant*) gcalc_expression_construct (object_type);
	return self;
}

GCalcConstant*
gcalc_constant_new (void)
{
	return gcalc_constant_construct (GCALC_TYPE_CONSTANT);
}

static GObject *
gcalc_constant_constructor (GType type,
                            guint n_construct_properties,
                            GObjectConstructParam * construct_properties)
{
	GObject * obj;
	GObjectClass * parent_class;
	GCalcConstant * self;
	parent_class = G_OBJECT_CLASS (gcalc_constant_parent_class);
	obj = parent_class->constructor (type, n_construct_properties, construct_properties);
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, GCALC_TYPE_CONSTANT, GCalcConstant);
	mpc_set_d_d (&self->priv->_complex, 0.0, (gdouble) 0, MPC_RNDNN);
	return obj;
}

static void
gcalc_constant_class_init (GCalcConstantClass * klass,
                           gpointer klass_data)
{
	gcalc_constant_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &GCalcConstant_private_offset);
	((GCalcExpressionClass *) klass)->to_string = (gchar* (*) (GCalcExpression*)) gcalc_constant_real_to_string;
	((GCalcExpressionClass *) klass)->solve = (GCalcMathResult* (*) (GCalcExpression*)) gcalc_constant_real_solve;
	G_OBJECT_CLASS (klass)->constructor = gcalc_constant_constructor;
	G_OBJECT_CLASS (klass)->finalize = gcalc_constant_finalize;
}

static void
gcalc_constant_gcalc_math_constant_interface_init (GCalcMathConstantIface * iface,
                                                   gpointer iface_data)
{
	gcalc_constant_gcalc_math_constant_parent_iface = g_type_interface_peek_parent (iface);
	iface->add = (GCalcMathConstant* (*) (GCalcMathConstant*, GCalcMathConstant*)) gcalc_constant_real_add;
	iface->subtract = (GCalcMathConstant* (*) (GCalcMathConstant*, GCalcMathConstant*)) gcalc_constant_real_subtract;
	iface->multiply = (GCalcMathConstant* (*) (GCalcMathConstant*, GCalcMathConstant*)) gcalc_constant_real_multiply;
	iface->divide = (GCalcMathConstant* (*) (GCalcMathConstant*, GCalcMathConstant*)) gcalc_constant_real_divide;
	iface->neg = (GCalcMathConstant* (*) (GCalcMathConstant*)) gcalc_constant_real_neg;
	iface->pow = (GCalcMathConstant* (*) (GCalcMathConstant*, GCalcMathConstant*)) gcalc_constant_real_pow;
}

static void
gcalc_constant_gcalc_math_constant_number_interface_init (GCalcMathConstantNumberIface * iface,
                                                          gpointer iface_data)
{
	gcalc_constant_gcalc_math_constant_number_parent_iface = g_type_interface_peek_parent (iface);
	iface->value = (gdouble (*) (GCalcMathConstantNumber*)) gcalc_constant_real_value;
}

static void
gcalc_constant_gcalc_math_constant_complex_interface_init (GCalcMathConstantComplexIface * iface,
                                                           gpointer iface_data)
{
	gcalc_constant_gcalc_math_constant_complex_parent_iface = g_type_interface_peek_parent (iface);
	iface->real = (gdouble (*) (GCalcMathConstantComplex*)) gcalc_constant_real_real;
	iface->imag = (gdouble (*) (GCalcMathConstantComplex*)) gcalc_constant_real_imag;
	iface->zero = (void (*) (GCalcMathConstantComplex*)) gcalc_constant_real_zero;
}

static void
gcalc_constant_instance_init (GCalcConstant * self,
                              gpointer klass)
{
	self->priv = gcalc_constant_get_instance_private (self);
	mpc_init2 (&self->priv->_complex, (mpfr_prec_t) 1000);
}

static void
gcalc_constant_finalize (GObject * obj)
{
	GCalcConstant * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, GCALC_TYPE_CONSTANT, GCalcConstant);
	mpc_clear (&self->priv->_complex);
	G_OBJECT_CLASS (gcalc_constant_parent_class)->finalize (obj);
}

/**
 * An implementation of {@link MathConstant}
 */
static GType
gcalc_constant_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (GCalcConstantClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gcalc_constant_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GCalcConstant), 0, (GInstanceInitFunc) gcalc_constant_instance_init, NULL };
	static const GInterfaceInfo gcalc_math_constant_info = { (GInterfaceInitFunc) gcalc_constant_gcalc_math_constant_interface_init, (GInterfaceFinalizeFunc) NULL, NULL};
	static const GInterfaceInfo gcalc_math_constant_number_info = { (GInterfaceInitFunc) gcalc_constant_gcalc_math_constant_number_interface_init, (GInterfaceFinalizeFunc) NULL, NULL};
	static const GInterfaceInfo gcalc_math_constant_complex_info = { (GInterfaceInitFunc) gcalc_constant_gcalc_math_constant_complex_interface_init, (GInterfaceFinalizeFunc) NULL, NULL};
	GType gcalc_constant_type_id;
	gcalc_constant_type_id = g_type_register_static (GCALC_TYPE_EXPRESSION, "GCalcConstant", &g_define_type_info, 0);
	g_type_add_interface_static (gcalc_constant_type_id, GCALC_TYPE_MATH_CONSTANT, &gcalc_math_constant_info);
	g_type_add_interface_static (gcalc_constant_type_id, GCALC_TYPE_MATH_CONSTANT_NUMBER, &gcalc_math_constant_number_info);
	g_type_add_interface_static (gcalc_constant_type_id, GCALC_TYPE_MATH_CONSTANT_COMPLEX, &gcalc_math_constant_complex_info);
	GCalcConstant_private_offset = g_type_add_instance_private (gcalc_constant_type_id, sizeof (GCalcConstantPrivate));
	return gcalc_constant_type_id;
}

GType
gcalc_constant_get_type (void)
{
	static volatile gsize gcalc_constant_type_id__once = 0;
	if (g_once_init_enter (&gcalc_constant_type_id__once)) {
		GType gcalc_constant_type_id;
		gcalc_constant_type_id = gcalc_constant_get_type_once ();
		g_once_init_leave (&gcalc_constant_type_id__once, gcalc_constant_type_id);
	}
	return gcalc_constant_type_id__once;
}

