|
Packit Service |
2e9770 |
/* mpc_get_dc, mpc_get_ldc -- Transform mpc number into C complex number
|
|
Packit Service |
2e9770 |
mpc_get_str -- Convert a complex number into a string.
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
Copyright (C) 2009, 2010, 2011 INRIA
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
This file is part of GNU MPC.
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
GNU MPC is free software; you can redistribute it and/or modify it under
|
|
Packit Service |
2e9770 |
the terms of the GNU Lesser General Public License as published by the
|
|
Packit Service |
2e9770 |
Free Software Foundation; either version 3 of the License, or (at your
|
|
Packit Service |
2e9770 |
option) any later version.
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
Packit Service |
2e9770 |
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
Packit Service |
2e9770 |
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
|
Packit Service |
2e9770 |
more details.
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
2e9770 |
along with this program. If not, see http://www.gnu.org/licenses/ .
|
|
Packit Service |
2e9770 |
*/
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
#include "config.h"
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
#ifdef HAVE_COMPLEX_H
|
|
Packit Service |
2e9770 |
#include <complex.h>
|
|
Packit Service |
2e9770 |
#endif
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
#ifdef HAVE_LOCALE_H
|
|
Packit Service |
2e9770 |
#include <locale.h>
|
|
Packit Service |
2e9770 |
#endif
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
#include <stdio.h> /* for sprintf, fprintf */
|
|
Packit Service |
2e9770 |
#include <ctype.h>
|
|
Packit Service |
2e9770 |
#include <string.h>
|
|
Packit Service |
2e9770 |
#include "mpc-impl.h"
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
#ifdef HAVE_COMPLEX_H
|
|
Packit Service |
2e9770 |
double _Complex
|
|
Packit Service |
2e9770 |
mpc_get_dc (mpc_srcptr op, mpc_rnd_t rnd) {
|
|
Packit Service |
2e9770 |
return I * mpfr_get_d (mpc_imagref (op), MPC_RND_IM (rnd))
|
|
Packit Service |
2e9770 |
+ mpfr_get_d (mpc_realref (op), MPC_RND_RE (rnd));
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
long double _Complex
|
|
Packit Service |
2e9770 |
mpc_get_ldc (mpc_srcptr op, mpc_rnd_t rnd) {
|
|
Packit Service |
2e9770 |
return I * mpfr_get_ld (mpc_imagref (op), MPC_RND_IM (rnd))
|
|
Packit Service |
2e9770 |
+ mpfr_get_ld (mpc_realref (op), MPC_RND_RE (rnd));
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
#endif
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
/* Code for mpc_get_str. The output format is "(real imag)", the decimal point
|
|
Packit Service |
2e9770 |
of the locale is used. */
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
/* mpfr_prec_t can be either int or long int */
|
|
Packit Service |
2e9770 |
#if (__GMP_MP_SIZE_T_INT == 1)
|
|
Packit Service |
2e9770 |
#define MPC_EXP_FORMAT_SPEC "i"
|
|
Packit Service |
2e9770 |
#elif (__GMP_MP_SIZE_T_INT == 0)
|
|
Packit Service |
2e9770 |
#define MPC_EXP_FORMAT_SPEC "li"
|
|
Packit Service |
2e9770 |
#else
|
|
Packit Service |
2e9770 |
#error "mpfr_exp_t size not supported"
|
|
Packit Service |
2e9770 |
#endif
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
static char *
|
|
Packit Service |
2e9770 |
pretty_zero (mpfr_srcptr zero)
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
char *pretty;
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
pretty = mpc_alloc_str (3);
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
pretty[0] = mpfr_signbit (zero) ? '-' : '+';
|
|
Packit Service |
2e9770 |
pretty[1] = '0';
|
|
Packit Service |
2e9770 |
pretty[2] = '\0';
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
return pretty;
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
static char *
|
|
Packit Service |
2e9770 |
prettify (const char *str, const mp_exp_t expo, int base, int special)
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
size_t sz;
|
|
Packit Service |
2e9770 |
char *pretty;
|
|
Packit Service |
2e9770 |
char *p;
|
|
Packit Service |
2e9770 |
const char *s;
|
|
Packit Service |
2e9770 |
mp_exp_t x;
|
|
Packit Service |
2e9770 |
int sign;
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
sz = strlen (str) + 1; /* + terminal '\0' */
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
if (special)
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
/* special number: nan or inf */
|
|
Packit Service |
2e9770 |
pretty = mpc_alloc_str (sz);
|
|
Packit Service |
2e9770 |
strcpy (pretty, str);
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
return pretty;
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
/* regular number */
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
sign = (str[0] == '-' || str[0] == '+');
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
x = expo - 1; /* expo is the exponent value with decimal point BEFORE
|
|
Packit Service |
2e9770 |
the first digit, we wants decimal point AFTER the first
|
|
Packit Service |
2e9770 |
digit */
|
|
Packit Service |
2e9770 |
if (base == 16)
|
|
Packit Service |
2e9770 |
x <<= 2; /* the output exponent is a binary exponent */
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
++sz; /* + decimal point */
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
if (x != 0)
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
/* augment sz with the size needed for an exponent written in base
|
|
Packit Service |
2e9770 |
ten */
|
|
Packit Service |
2e9770 |
mp_exp_t xx;
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
sz += 3; /* + exponent char + sign + 1 digit */
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
if (x < 0)
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
/* avoid overflow when changing sign (assuming that, for the
|
|
Packit Service |
2e9770 |
mp_exp_t type, (max value) is greater than (- min value / 10)) */
|
|
Packit Service |
2e9770 |
if (x < -10)
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
xx = - (x / 10);
|
|
Packit Service |
2e9770 |
sz++;
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else
|
|
Packit Service |
2e9770 |
xx = -x;
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else
|
|
Packit Service |
2e9770 |
xx = x;
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
/* compute sz += floor(log(expo)/log(10)) without using libm
|
|
Packit Service |
2e9770 |
functions */
|
|
Packit Service |
2e9770 |
while (xx > 9)
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
sz++;
|
|
Packit Service |
2e9770 |
xx /= 10;
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
pretty = mpc_alloc_str (sz);
|
|
Packit Service |
2e9770 |
p = pretty;
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
/* 1. optional sign plus first digit */
|
|
Packit Service |
2e9770 |
s = str;
|
|
Packit Service |
2e9770 |
*p++ = *s++;
|
|
Packit Service |
2e9770 |
if (sign)
|
|
Packit Service |
2e9770 |
*p++ = *s++;
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
/* 2. decimal point */
|
|
Packit Service |
2e9770 |
#ifdef HAVE_LOCALECONV
|
|
Packit Service |
2e9770 |
*p++ = *localeconv ()->decimal_point;
|
|
Packit Service |
2e9770 |
#else
|
|
Packit Service |
2e9770 |
*p++ = '.';
|
|
Packit Service |
2e9770 |
#endif
|
|
Packit Service |
2e9770 |
*p = '\0';
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
/* 3. other significant digits */
|
|
Packit Service |
2e9770 |
strcat (pretty, s);
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
/* 4. exponent (in base ten) */
|
|
Packit Service |
2e9770 |
if (x == 0)
|
|
Packit Service |
2e9770 |
return pretty;
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
p = pretty + strlen (str) + 1;
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
switch (base)
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
case 10:
|
|
Packit Service |
2e9770 |
*p++ = 'e';
|
|
Packit Service |
2e9770 |
break;
|
|
Packit Service |
2e9770 |
case 2:
|
|
Packit Service |
2e9770 |
case 16:
|
|
Packit Service |
2e9770 |
*p++ = 'p';
|
|
Packit Service |
2e9770 |
break;
|
|
Packit Service |
2e9770 |
default:
|
|
Packit Service |
2e9770 |
*p++ = '@';
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
*p = '\0';
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
sprintf (p, "%+"MPC_EXP_FORMAT_SPEC, x);
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
return pretty;
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
static char *
|
|
Packit Service |
2e9770 |
get_pretty_str (const int base, const size_t n, mpfr_srcptr x, mpfr_rnd_t rnd)
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
mp_exp_t expo;
|
|
Packit Service |
2e9770 |
char *ugly;
|
|
Packit Service |
2e9770 |
char *pretty;
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
if (mpfr_zero_p (x))
|
|
Packit Service |
2e9770 |
return pretty_zero (x);
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
ugly = mpfr_get_str (NULL, &expo, base, n, x, rnd);
|
|
Packit Service |
2e9770 |
MPC_ASSERT (ugly != NULL);
|
|
Packit Service |
2e9770 |
pretty = prettify (ugly, expo, base, !mpfr_number_p (x));
|
|
Packit Service |
2e9770 |
mpfr_free_str (ugly);
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
return pretty;
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
char *
|
|
Packit Service |
2e9770 |
mpc_get_str (int base, size_t n, mpc_srcptr op, mpc_rnd_t rnd)
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
size_t needed_size;
|
|
Packit Service |
2e9770 |
char *real_str;
|
|
Packit Service |
2e9770 |
char *imag_str;
|
|
Packit Service |
2e9770 |
char *complex_str = NULL;
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
if (base < 2 || base > 36)
|
|
Packit Service |
2e9770 |
return NULL;
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
real_str = get_pretty_str (base, n, mpc_realref (op), MPC_RND_RE (rnd));
|
|
Packit Service |
2e9770 |
imag_str = get_pretty_str (base, n, mpc_imagref (op), MPC_RND_IM (rnd));
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
needed_size = strlen (real_str) + strlen (imag_str) + 4;
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
complex_str = mpc_alloc_str (needed_size);
|
|
Packit Service |
2e9770 |
MPC_ASSERT (complex_str != NULL);
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
strcpy (complex_str, "(");
|
|
Packit Service |
2e9770 |
strcat (complex_str, real_str);
|
|
Packit Service |
2e9770 |
strcat (complex_str, " ");
|
|
Packit Service |
2e9770 |
strcat (complex_str, imag_str);
|
|
Packit Service |
2e9770 |
strcat (complex_str, ")");
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
mpc_free_str (real_str);
|
|
Packit Service |
2e9770 |
mpc_free_str (imag_str);
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
return complex_str;
|
|
Packit Service |
2e9770 |
}
|