/****************************************************************************
* *
* W mpc . c GAP source Laurent Bartholdi
* *
* Y Copyright ( C ) 2008 - 2012 Laurent Bartholdi
* *
* * This file contains the functions for the float package .
* * complex floats are implemented using the MPC package .
*/
#include "floatconfig.h"
#undef PACKAGE
#undef PACKAGE_BUGREPORT
#undef PACKAGE_NAME
#undef PACKAGE_STRING
#undef PACKAGE_TARNAME
#undef PACKAGE_URL
#undef PACKAGE_VERSION
#include <stdio.h>
#include "floattypes.h"
#include <mpc.h>
#include <mp_poly.h>
/****************************************************************
* mpc ' s are stored as follows :
* + - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - +
* | TYPE_MPC | _ _ mpc_struct | _ _ mp_limb_t [ ] |
* | | _ _ mpfr_struct real imag | limbr . . . limbi . . . |
* | | prec exp sign mant prec exp sign mant | |
* + - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - +
* \ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \ _ _ _ _ ^ ^
* \ _ _ _ _ _ _ _ _ _ _ _ _ /
* it is assumed that the real and imaginary mpfr ' s are allocated with the
* same precision
****************************************************************/
#define MPC_OBJ(obj) ((mpc_ptr) (ADDR_OBJ(obj)+1 ))
#define REMANTISSA_MPC(p) ((mp_limb_t *) (p+1 ))
#define IMMANTISSA_MPC(p) (REMANTISSA_MPC(p)+(mpc_get_prec(p)+GMP_NUMB_BITS-1 )/GMP_NUMB_BITS)
static inline mpc_ptr GET_MPC(Obj obj) {
mpc_ptr p = MPC_OBJ(obj);
mpfr_custom_move (p->re, REMANTISSA_MPC(p));
mpfr_custom_move (p->im, IMMANTISSA_MPC(p));
return p;
}
/****************************************************************************
* *
* F allocate new object , initialize to NaN
* *
*/
Obj TYPE_MPC;
static inline Obj NEW_MPC( mp_prec_t prec )
{
Obj f = NEW_DATOBJ(sizeof (__mpc_struct)+2 *mpfr_custom_get_size(prec), TYPE_MPC);
mpc_ptr p = MPC_OBJ(f);
mpfr_custom_init_set(p->re, MPFR_NAN_KIND, 0 , prec, REMANTISSA_MPC(p));
mpfr_custom_init_set(p->im, MPFR_NAN_KIND, 0 , prec, IMMANTISSA_MPC(p));
return f;
}
/****************************************************************************
* *
* F Func1_MPC ( < float > ) . . . . . . . . . . . . . . . . 1 - argument functions
* *
*/
#define Func1_MPC(name,mpc_name) \
static Obj name(Obj self, Obj f) \
{ \
mp_prec_t prec = mpc_get_prec(GET_MPC(f)); \
Obj g = NEW_MPC(prec); \
mpc_name (MPC_OBJ(g), GET_MPC(f), MPC_RNDNN); \
return g; \
}
#define Func1_MPFRMPC(name,mpc_name) \
static Obj name(Obj self, Obj f) \
{ \
mp_prec_t prec = mpc_get_prec(GET_MPC(f)); \
Obj g = NEW_MPFR(prec); \
mpc_name (MPFR_OBJ(g), GET_MPC(f), MPC_RNDNN); \
return g; \
}
#define Inc1_MPC_arg(name,arg) \
{ #name , 1 , arg, (ObjFunc)(void *)(name), "src/mpc.c:" #name }
#define Inc1_MPC(name) Inc1_MPC_arg(name,"complex" )
Func1_MPC(PROJ_MPC,mpc_proj);
Func1_MPC(EXP_MPC,mpc_exp);
Func1_MPC(LOG_MPC,mpc_log);
Func1_MPC(CONJ_MPC,mpc_conj);
Func1_MPC(AINV_MPC,mpc_neg);
Func1_MPC(SQRT_MPC,mpc_sqrt);
Func1_MPC(SQR_MPC,mpc_sqr);
Func1_MPC(SIN_MPC,mpc_sin);
Func1_MPC(COS_MPC,mpc_cos);
Func1_MPC(TAN_MPC,mpc_tan);
Func1_MPC(SINH_MPC,mpc_sinh);
Func1_MPC(COSH_MPC,mpc_cosh);
Func1_MPC(TANH_MPC,mpc_tanh);
Func1_MPC(ASIN_MPC,mpc_asin);
Func1_MPC(ACOS_MPC,mpc_acos);
Func1_MPC(ATAN_MPC,mpc_atan);
Func1_MPC(ASINH_MPC,mpc_asinh);
Func1_MPC(ACOSH_MPC,mpc_acosh);
Func1_MPC(ATANH_MPC,mpc_atanh);
Func1_MPFRMPC(ABS_MPC,mpc_abs);
Func1_MPFRMPC(NORM_MPC,mpc_norm);
Func1_MPFRMPC(REAL_MPC,mpc_real);
Func1_MPFRMPC(IMAG_MPC,mpc_imag);
Func1_MPFRMPC(ARG_MPC,mpc_arg);
int mpc_nan_p(mpc_ptr c) { return mpfr_nan_p(c->re) || mpfr_nan_p(c->im); }
int mpc_inf_p(mpc_ptr c) { return mpfr_inf_p(c->re) || mpfr_inf_p(c->im); }
int mpc_zero_p(mpc_ptr c) { return mpfr_zero_p(c->re) && mpfr_zero_p(c->im); }
int mpc_number_p(mpc_ptr c) { return mpfr_number_p(c->re) && mpfr_number_p(c->im); }
static Obj ISNAN_MPC(Obj self, Obj f)
{
return mpc_nan_p(GET_MPC(f)) ? True : False ;
}
static Obj ISINF_MPC(Obj self, Obj f)
{
return mpc_inf_p(GET_MPC(f)) ? True : False ;
}
static Obj ISZERO_MPC(Obj self, Obj f)
{
return mpc_zero_p(GET_MPC(f)) ? True : False ;
}
static Obj ISNUMBER_MPC(Obj self, Obj f)
{
return mpc_number_p(GET_MPC(f)) ? True : False ;
}
static Obj FREXP_MPC(Obj self, Obj f)
{
mp_prec_t prec = mpc_get_prec(GET_MPC(f));
Obj g = NEW_MPC(prec);
mpc_set (MPC_OBJ(g), GET_MPC(f), MPC_RNDNN);
mp_exp_t ere = mpfr_get_exp(MPC_OBJ(f)->re),
eim = mpfr_get_exp(MPC_OBJ(f)->im);
mp_exp_t e = ere > eim ? ere : eim;
mpfr_set_exp(MPC_OBJ(g)->re, ere-e);
mpfr_set_exp(MPC_OBJ(g)->im, eim-e);
Obj l = NEW_PLIST(T_PLIST,2 );
SET_ELM_PLIST(l,1 ,g);
SET_ELM_PLIST(l,2 , ObjInt_Int(e));
SET_LEN_PLIST(l,2 );
return l;
}
static Obj LDEXP_MPC(Obj self, Obj f, Obj exp)
{
mp_exp_t e = Int_ObjInt(exp);
mp_prec_t prec = mpc_get_prec(GET_MPC(f));
Obj g = NEW_MPC(prec);
mpfr_mul_2si (MPC_OBJ(g)->re, GET_MPC(f)->re, e, GMP_RNDN);
mpfr_mul_2si (MPC_OBJ(g)->im, MPC_OBJ(f)->im, e, GMP_RNDN);
return g;
}
static Obj EXTREPOFOBJ_MPC(Obj self, Obj f)
{
mp_prec_t prec = mpc_get_prec(GET_MPC(f));
int i;
Obj l = NEW_PLIST(T_PLIST,4 );
SET_LEN_PLIST(l,4 );
Obj g = NEW_MPFR(prec);
if (mpc_zero_p(GET_MPC(f))) {
SET_ELM_PLIST(l,1 , INTOBJ_INT(0 ));
SET_ELM_PLIST(l,2 , INTOBJ_INT(0 ));
return l;
}
if (!mpc_number_p(GET_MPC(f))) {
SET_ELM_PLIST(l,1 , INTOBJ_INT(0 ));
if (mpc_nan_p(MPC_OBJ(f)))
SET_ELM_PLIST(l,2 , INTOBJ_INT(4 ));
else if (mpc_inf_p(MPC_OBJ(f)))
SET_ELM_PLIST(l,2 , INTOBJ_INT(2 ));
return l;
}
mpz_t z;
mpz_init2 (z, prec);
for (i = 0 ; i < 2 ; i++) {
if (i == 0 )
mpfr_set (MPFR_OBJ(g), GET_MPC(f)->re, GMP_RNDN);
else
mpfr_set (MPFR_OBJ(g), GET_MPC(f)->im, GMP_RNDN);
mp_exp_t e = mpfr_get_exp(MPFR_OBJ(g));
mpfr_set_exp(MPFR_OBJ(g), prec);
mpfr_get_z (z, MPFR_OBJ(g), GMP_RNDZ);
Obj ig = INT_mpz(z);
SET_ELM_PLIST(l,2 *i+1 , ig);
SET_ELM_PLIST(l,2 *i+2 , ObjInt_Int(e));
}
mpz_clear(z);
return l;
}
#pragma GCC diagnostic ignored "-Wuninitialized"
static Obj OBJBYEXTREP_MPC(Obj self, Obj list)
{
int i;
mp_prec_t prec = 0 ;
if (LEN_LIST(list) != 4 ) {
ErrorMayQuit("OBJBYEXTREP_MPC: object must be a list of length 4, not a %s" ,
(Int )TNAM_OBJ(list),0 );
}
for (i = 0 ; i < 4 ; i += 2 ) {
Obj m = ELM_PLIST(list,i+1 );
mp_prec_t newprec;
if (IS_INTOBJ(m))
newprec = 8 *sizeof (long );
else if (TNUM_OBJ(m) == T_INTPOS || TNUM_OBJ(m) == T_INTNEG)
newprec = 8 *sizeof (mp_limb_t)*SIZE_INT(m);
else
ErrorQuit("OBJBYEXTREP_MPC: invalid argument %d" , i+1 ,0 );
if (newprec > prec)
prec = newprec;
}
Obj f = NEW_MPC(prec);
for (i = 0 ; i < 4 ; i++) {
Obj m = ELM_PLIST(list,i+1 );
Int iarg;
mpz_ptr zarg;
int argtype;
if (IS_INTOBJ(m))
iarg = INT_INTOBJ(m), argtype = 0 ;
else
zarg = mpz_MPZ(MPZ_LONGINT(m)), argtype = 1 ;
if (i & 1 && argtype) /* exponent, must be small int */
iarg = mpz_get_si(zarg), argtype = 0 ;
mpfr_ptr reim;
if (i < 2 )
reim = GET_MPC(f)->re;
else
reim = GET_MPC(f)->im;
if (i & 1 )
mpfr_set_exp(reim, iarg);
else if (argtype)
mpfr_set_z(reim, zarg, GMP_RNDN);
else {
if (iarg == 0 ) { /* special case */
switch (INT_INTOBJ(ELM_PLIST(list,i+2 ))) {
case 0 : /* 0 */
case 1 : /* -0 */
mpfr_set_si(reim, 0 , GMP_RNDN); break ;
case 2 : /* inf */
case 3 : /* -inf */
mpfr_set_inf (reim, 1 ); break ;
case 4 : /* nan */
case 5 : /* -nan */
mpfr_set_nan (reim); break ;
default :
ErrorQuit("OBJBYEXTREP_MPC: invalid argument [%d,%d]" ,
iarg, INT_INTOBJ(ELM_PLIST(list,i+2 )));
}
i++; /* skip "exponent" */
continue ;
}
mpfr_set_si(reim, iarg, GMP_RNDN);
}
}
return f;
}
static Obj ZERO_MPC(Obj self, Obj f)
{
mp_prec_t prec = mpc_get_prec(GET_MPC(f));
Obj g = NEW_MPC(prec);
mpc_set_ui(MPC_OBJ(g), 0 , MPC_RNDNN);
return g;
}
static Obj ONE_MPC(Obj self, Obj f)
{
mp_prec_t prec = mpc_get_prec(GET_MPC(f));
Obj g = NEW_MPC(prec);
mpc_set_ui (MPC_OBJ(g), 1 , MPC_RNDNN);
return g;
}
static Obj MPC_MAKENAN(Obj self, Obj prec)
{
TEST_IS_INTOBJ("MPC_MAKENAN" ,prec);
Obj g = NEW_MPC(INT_INTOBJ(prec));
mpfr_set_nan (MPC_OBJ(g)->re);
mpfr_set_nan (MPC_OBJ(g)->im);
return g;
}
static Obj MPC_MAKEINFINITY(Obj self, Obj prec)
{
TEST_IS_INTOBJ("MPC_MAKEINFINITY" ,prec);
int p = INT_INTOBJ(prec);
Obj g = NEW_MPC(p < 0 ? -p : p);
mpfr_set_inf (MPC_OBJ(g)->re, p);
mpfr_set_inf (MPC_OBJ(g)->im, p);
return g;
}
static Obj INV_MPC(Obj self, Obj f)
{
Obj g = NEW_MPC(mpc_get_prec(GET_MPC(f)));
mpc_ui_div (MPC_OBJ(g), 1 , GET_MPC(f), MPC_RNDNN);
return g;
}
static Obj MPC_INT(Obj self, Obj i)
{
Obj g;
if (IS_INTOBJ(i)) {
g = NEW_MPC(8 *sizeof (long ));
mpc_set_si(MPC_OBJ(g), INT_INTOBJ(i), MPC_RNDNN);
} else {
Obj f = MPZ_LONGINT(i);
g = NEW_MPC(8 *sizeof (mp_limb_t)*SIZE_INT(i));
mpfr_set_z(MPC_OBJ(g)->re, mpz_MPZ(f), GMP_RNDN);
mpfr_set_ui(MPC_OBJ(g)->im, 0 , GMP_RNDN);
}
return g;
}
static Obj MPC_INTPREC(Obj self, Obj i, Obj prec)
{
Obj g;
TEST_IS_INTOBJ("MPC_INTPREC" ,prec);
if (IS_INTOBJ(i)) {
g = NEW_MPC(INT_INTOBJ(prec));
mpc_set_si(MPC_OBJ(g), INT_INTOBJ(i), MPC_RNDNN);
} else {
Obj f = MPZ_LONGINT(i);
g = NEW_MPC(INT_INTOBJ(prec));
mpfr_set_z(MPC_OBJ(g)->re, mpz_MPZ(f), GMP_RNDN);
mpfr_set_ui(MPC_OBJ(g)->im, 0 , GMP_RNDN);
}
return g;
}
static Obj PREC_MPC(Obj self, Obj f)
{
return INTOBJ_INT(mpc_get_prec(GET_MPC(f)));
}
static Obj MPC_MPCPREC(Obj self, Obj f, Obj prec)
{
TEST_IS_INTOBJ("MPC_MPCPREC" ,prec);
Obj g = NEW_MPC(INT_INTOBJ(prec));
mpc_set (MPC_OBJ(g), GET_MPC(f), MPC_RNDNN);
return g;
}
static Obj STRING_MPC(Obj self, Obj f, Obj digits)
{
mp_prec_t prec = mpc_get_prec(GET_MPC(f));
Obj str = NEW_STRING(2 *(prec*302 /1000 +10 )+3 );
int slen = 0 , smid, n;
TEST_IS_INTOBJ("STRING_MPC" ,digits);
n = INT_INTOBJ(digits);
if (n == 1 ) n = 2 ;
char *c = CSTR_STRING(str);
slen += PRINT_MPFR(c+slen, 0 , n, GET_MPC(f)->re, GMP_RNDN);
c[slen++] = '+' ;
smid = slen;
slen += PRINT_MPFR(c+slen, 0 , n, GET_MPC(f)->im, GMP_RNDN);
if (c[smid] == '-' ) {
while (smid <= slen) { c[smid-1 ] = c[smid]; smid++; }
slen--;
}
c[slen++] = 'i' ;
c[slen] = 0 ;
SET_LEN_STRING(str, slen);
SHRINK_STRING(str);
return str;
}
static Obj VIEWSTRING_MPC(Obj self, Obj f, Obj digits)
{
mp_prec_t prec = mpc_get_prec(GET_MPC(f));
Obj str = NEW_STRING(2 *(prec*302 /1000 +10 )+3 );
int slen = 0 , n;
TEST_IS_INTOBJ("VIEWSTRING_MPC" ,digits);
n = INT_INTOBJ(digits);
if (n == 1 ) n = 2 ;
char *c = CSTR_STRING(str);
if (mpc_inf_p(GET_MPC(f))) {
strcat(c+slen, CSTR_STRING(FLOAT_INFINITY_STRING));
slen += GET_LEN_STRING(FLOAT_INFINITY_STRING);
} else if (mpc_nan_p(GET_MPC(f))) {
c[slen++] = 'n' ;
c[slen++] = 'a' ;
c[slen++] = 'n' ;
} else {
slen += PRINT_MPFR(c+slen, 0 , n, GET_MPC(f)->re, GMP_RNDN);
Obj im = NEW_MPFR(prec);
// Reassign in case GC occurred
c = CSTR_STRING(str);
mpfr_add(MPFR_OBJ(im), GET_MPC(f)->re, GET_MPC(f)->im, GMP_RNDN);
mpfr_sub(MPFR_OBJ(im), MPFR_OBJ(im), GET_MPC(f)->re, GMP_RNDN); /* round off small im */
if (!mpfr_zero_p(MPFR_OBJ(im))) {
if (mpfr_sgn(MPFR_OBJ(im)) < 0 )
c[slen++] = '-' ;
else
c[slen++] = '+' ;
mpfr_abs (MPFR_OBJ(im), GET_MPC(f)->im, GMP_RNDN);
slen += PRINT_MPFR(c+slen, 0 , n, MPFR_OBJ(im), GMP_RNDN);
strcat(c+slen, CSTR_STRING(FLOAT_I_STRING));
slen += GET_LEN_STRING(FLOAT_I_STRING);
}
}
CSTR_STRING(str)[slen] = 0 ;
SET_LEN_STRING(str, slen);
SHRINK_STRING(str);
return str;
}
static Obj MPC_STRING(Obj self, Obj s, Obj prec)
{
TEST_IS_STRING(MPC_STRING, s);
TEST_IS_INTOBJ("MPC_STRING" ,prec);
int n = INT_INTOBJ(prec);
if (n == 0 )
n = GET_LEN_STRING(s)*1000 / 301 ;
Obj newg = NEW_MPFR(INT_INTOBJ(prec));
Obj g = NEW_MPC(INT_INTOBJ(prec));
// Force newg internal pointers to be updated
GET_MPFR(newg);
int sign = 1 ;
mpc_set_ui(MPC_OBJ(g), 0 , MPC_RNDNN);
mpfr_ptr f = MPC_OBJ(g)->re;
char *p = CSTR_STRING(s), *newp;
for (;;) {
switch (*p) {
case '-' :
case '+' :
case 0 :
if (!mpfr_nan_p(MPFR_OBJ(newg))) { /* drop the last read float */
mpfr_add (f, f, MPFR_OBJ(newg), GMP_RNDN);
mpfr_set_nan (MPFR_OBJ(newg));
f = GET_MPC(g)->re;
sign = 1 ;
}
if (!*p)
return g;
if (*p == '-' )
sign = -sign;
case '*' : p++; break ;
case 'i' :
case 'I' : if (f == GET_MPC(g)->re) {
f = GET_MPC(g)->im;
if (mpfr_nan_p(MPFR_OBJ(newg)))
mpfr_set_si (MPFR_OBJ(newg), sign, GMP_RNDN); /* accept 'i' as '1*i' */
} else return Fail;
p++; break ;
default :
mpfr_strtofr(MPFR_OBJ(newg), p, &newp, 10 , GMP_RNDN);
if (newp == p && f != GET_MPC(g)->im)
return Fail; /* no valid characters read */
if (sign == -1 )
mpfr_neg(MPFR_OBJ(newg), MPFR_OBJ(newg), GMP_RNDN);
p = newp;
}
}
return g;
}
static Obj MPC_MPFR(Obj self, Obj f)
{
Obj g = NEW_MPC (mpfr_get_prec(GET_MPFR(f)));
mpfr_set (MPC_OBJ(g)->re, GET_MPFR(f), GMP_RNDN);
mpfr_set_ui (MPC_OBJ(g)->im, 0 , GMP_RNDN);
return g;
}
/****************************************************************************
* *
* F Func2_MPC ( < float > , < float > ) . . . . . . . . . . . 2 - argument functions
* *
*/
#define Func2_MPC(name,mpc_name) \
static Obj name## _MPC(Obj self, Obj fl, Obj fr) \
{ \
mp_prec_t precl = mpc_get_prec(GET_MPC(fl)), \
precr = mpc_get_prec(GET_MPC(fr)); \
\
Obj g = NEW_MPC(precl > precr ? precl : precr); \
mpc_name (MPC_OBJ(g), GET_MPC(fl), GET_MPC(fr), MPC_RNDNN); \
return g; \
}
#define Func2_MPC_MPFR(name,mpc_name) \
static Obj name## _MPC_MPFR(Obj self, Obj fl, Obj fr) \
{ \
mp_prec_t precl = mpc_get_prec(GET_MPC(fl)), \
precr = mpfr_get_prec(GET_MPFR(fr)); \
\
Obj g = NEW_MPC(precl > precr ? precl : precr); \
mpc_name (MPC_OBJ(g), GET_MPC(fl), GET_MPFR(fr), MPC_RNDNN); \
return g; \
}
#define Func2_MPFR_MPC(name,mpc_name) \
static Obj name## _MPFR_MPC(Obj self, Obj fl, Obj fr) \
{ \
mp_prec_t precl = mpfr_get_prec(GET_MPFR(fl)), \
precr = mpc_get_prec(GET_MPC(fr)); \
\
Obj g = NEW_MPC(precl > precr ? precl : precr); \
mpc_name (MPC_OBJ(g), GET_MPFR(fl), GET_MPC(fr), MPC_RNDNN); \
return g; \
}
#define Inc2_MPC_arg(name,arg) \
{ #name , 2 , arg, (ObjFunc)(void *)(name), "src/mpc.c:" #name }
#define Inc2_MPC(name) Inc2_MPC_arg(name## _MPC,"complex, complex" ), \
Inc2_MPC_arg(name## _MPC_MPFR,"complex, real" ), \
Inc2_MPC_arg(name## _MPFR_MPC,"real, complex" ) \
Func2_MPC(SUM,mpc_add);
Func2_MPC(DIFF,mpc_sub);
Func2_MPC(PROD,mpc_mul);
Func2_MPC(QUO,mpc_div);
Func2_MPC(POW,mpc_pow);
Func2_MPC_MPFR(SUM,mpc_add_fr);
Func2_MPC_MPFR(DIFF,mpc_sub_fr);
Func2_MPC_MPFR(PROD,mpc_mul_fr);
Func2_MPC_MPFR(QUO,mpc_div_fr);
Func2_MPC_MPFR(POW,mpc_pow_fr);
#define mpc_fr_add(a,b,c,d) mpc_add_fr(a,c,b,d)
Func2_MPFR_MPC(SUM,mpc_fr_add);
Func2_MPFR_MPC(DIFF,mpc_fr_sub);
#define mpc_fr_mul(a,b,c,d) mpc_mul_fr(a,c,b,d)
Func2_MPFR_MPC(PROD,mpc_fr_mul);
Func2_MPFR_MPC(QUO,mpc_fr_div);
static Obj POW_MPFR_MPC(Obj self, Obj fl, Obj fr)
{
mp_prec_t precl = mpfr_get_prec(GET_MPFR(fl)),
precr = mpc_get_prec(GET_MPC(fr));
Obj h = NEW_MPC (precl);
mpfr_set (MPC_OBJ(h)->re, GET_MPFR(fl), GMP_RNDN);
mpfr_set_ui (MPC_OBJ(h)->im, 0 , GMP_RNDN);
Obj g = NEW_MPC(precl > precr ? precl : precr);
mpc_pow (MPC_OBJ(g), GET_MPC(h), GET_MPC(fr), MPC_RNDNN);
return g;
}
static Obj LQUO_MPC(Obj self, Obj fl, Obj fr)
{
return QUO_MPC(self, fr, fl);
}
static Obj LQUO_MPC_MPFR(Obj self, Obj fl, Obj fr)
{
return QUO_MPFR_MPC(self, fr, fl);
}
static Obj LQUO_MPFR_MPC(Obj self, Obj fl, Obj fr)
{
return QUO_MPC_MPFR(self, fr, fl);
}
static Obj EQ_MPC (Obj self, Obj fl, Obj fr)
{
return mpc_cmp(GET_MPC(fl),GET_MPC(fr)) == 0 ? True : False ;
}
static Obj EQ_MPC_MPFR (Obj self, Obj fl, Obj fr)
{
return mpfr_cmp(GET_MPC(fl)->re,GET_MPFR(fr)) == 0 && mpfr_zero_p(MPC_OBJ(fl)->im) ? True : False ;
}
static Obj EQ_MPFR_MPC (Obj self, Obj fl, Obj fr)
{
return mpfr_cmp(GET_MPFR(fl),GET_MPC(fr)->re) == 0 && mpfr_zero_p(MPC_OBJ(fr)->im) ? True : False ;
}
static Obj LT_MPC (Obj self, Obj fl, Obj fr)
{
int c = mpc_cmp(GET_MPC(fl),GET_MPC(fr)), cre = MPC_INEX_RE(c);
return (cre < 0 || (cre == 0 && MPC_INEX_IM(c) < 0 )) ? True : False ;
}
static Obj LT_MPC_MPFR (Obj self, Obj fl, Obj fr)
{
int c = mpfr_cmp(GET_MPC(fl)->re, GET_MPFR(fr));
if (!c) c = mpfr_cmp_si(GET_MPC(fl)->im, 0 );
return c < 0 ? True : False ;
}
static Obj LT_MPFR_MPC (Obj self, Obj fl, Obj fr)
{
int c = mpfr_cmp(GET_MPFR(fl), GET_MPC(fr)->re);
if (!c) c = -mpfr_cmp_si(GET_MPC(fr)->im, 0 );
return c < 0 ? True : False ;
}
static Obj MPC_2MPFR (Obj self, Obj fl, Obj fr)
{
mp_prec_t precl = mpfr_get_prec(GET_MPFR(fl)),
precr = mpfr_get_prec(GET_MPFR(fr));
Obj g = NEW_MPC(precl > precr ? precl : precr);
mpfr_set (MPC_OBJ(g)->re, GET_MPFR(fl), GMP_RNDN);
mpfr_set (MPC_OBJ(g)->im, GET_MPFR(fr), GMP_RNDN);
return g;
}
static Obj ROOTPOLY_MPC (Obj self, Obj coeffs, Obj precision)
{
Obj result;
Int i, numroots, degree = LEN_PLIST(coeffs)-1 ;
mpc_t op[degree+1 ], zero[degree];
mp_prec_t prec = INT_INTOBJ(precision);
if (degree < 1 ) {
result = NEW_PLIST(T_PLIST,0 );
SET_LEN_PLIST(result,0 );
return result;
}
for (i = 0 ; i <= degree; i++) {
mpc_init2(op[degree-i],mpc_get_prec(GET_MPC(ELM_PLIST(coeffs,i+1 ))));
mpc_set(op[degree-i],GET_MPC(ELM_PLIST(coeffs,i+1 )),MPC_RNDNN);
if (!mpc_number_p(op[degree-i]))
return Fail;
}
for (i = 0 ; i < degree; i++)
mpc_init2(zero[i],prec);
/* !!! first call routine on low-precision IEEE numbers; if got n roots, refine them using accelerated Newton's method (x - ff'/(f'f' - ff")), or (x-jf/f' with j such that f(new pt) in minimal. if fails, call the high-precision method */
numroots = cpoly_MPC (degree, op, zero, (int )prec);
for (i = 0 ; i <= degree; i++)
mpc_clear(op[degree-i]);
if (numroots == -1 )
result = Fail;
else {
result = NEW_PLIST(T_PLIST,numroots);
SET_LEN_PLIST(result,numroots);
for (i = 1 ; i <= numroots; i++) {
Obj t = NEW_MPC(mpc_get_prec(zero[i-1 ]));
mpc_set (MPC_OBJ(t), zero[i-1 ], MPC_RNDNN);
SET_ELM_PLIST(result,i, t);
}
}
for (i = 0 ; i < degree; i++)
mpc_clear(zero[i]);
return result;
}
/****************************************************************
* export functions
****************************************************************/
static StructGVarFunc GVarFuncs [] = {
Inc1_MPC(AINV_MPC),
Inc1_MPC(ABS_MPC),
Inc1_MPC(INV_MPC),
Inc1_MPC(EXP_MPC),
Inc1_MPC(LOG_MPC),
Inc1_MPC(SQRT_MPC),
Inc1_MPC(SQR_MPC),
Inc1_MPC(CONJ_MPC),
Inc1_MPC(PROJ_MPC),
Inc1_MPC(SIN_MPC),
Inc1_MPC(COS_MPC),
Inc1_MPC(TAN_MPC),
Inc1_MPC(ASIN_MPC),
Inc1_MPC(ACOS_MPC),
Inc1_MPC(ATAN_MPC),
Inc1_MPC(SINH_MPC),
Inc1_MPC(COSH_MPC),
Inc1_MPC(TANH_MPC),
Inc1_MPC(ASINH_MPC),
Inc1_MPC(ACOSH_MPC),
Inc1_MPC(ATANH_MPC),
Inc1_MPC(ZERO_MPC),
Inc1_MPC(ONE_MPC),
Inc1_MPC(ISZERO_MPC),
Inc1_MPC(ISNUMBER_MPC),
Inc1_MPC(ISNAN_MPC),
Inc1_MPC(ISINF_MPC),
Inc1_MPC_arg(MPC_MAKENAN,"int" ),
Inc1_MPC_arg(MPC_MAKEINFINITY,"int" ),
Inc1_MPC_arg(MPC_INT,"int" ),
Inc1_MPC(PREC_MPC),
Inc1_MPC(REAL_MPC),
Inc1_MPC(IMAG_MPC),
Inc1_MPC(NORM_MPC),
Inc1_MPC(ARG_MPC),
Inc1_MPC(MPC_MPFR),
Inc1_MPC(FREXP_MPC),
Inc2_MPC_arg(LDEXP_MPC,"complex, int" ),
Inc1_MPC(EXTREPOFOBJ_MPC),
Inc1_MPC_arg(OBJBYEXTREP_MPC,"list" ),
Inc2_MPC(SUM),
Inc2_MPC(DIFF),
Inc2_MPC(PROD),
Inc2_MPC(QUO),
Inc2_MPC(LQUO),
Inc2_MPC(POW),
Inc2_MPC(EQ),
Inc2_MPC(LT),
Inc2_MPC_arg(MPC_STRING,"string, int" ),
Inc2_MPC_arg(STRING_MPC,"complex, int" ),
Inc2_MPC_arg(VIEWSTRING_MPC,"complex, int" ),
Inc2_MPC_arg(MPC_INTPREC,"int, int" ),
Inc2_MPC_arg(MPC_MPCPREC,"complex, int" ),
Inc2_MPC_arg(MPC_2MPFR,"complex, complex" ),
Inc2_MPC_arg(ROOTPOLY_MPC,"coeffs, prec" ),
{0 }
};
int InitMPCKernel (void )
{
InitHdlrFuncsFromTable (GVarFuncs);
ImportGVarFromLibrary ("TYPE_MPC" , &TYPE_MPC);
return 0 ;
}
int InitMPCLibrary (void )
{
InitGVarFuncsFromTable (GVarFuncs);
return 0 ;
}
/****************************************************************************
* *
* E mpc . c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here
*/
Messung V0.5 in Prozent C=98 H=92 G=94
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet am 2026-06-17)
¤
*© Formatika GbR, Deutschland