Commit f613b71b authored by Morten Welinder's avatar Morten Welinder

Complex number cleanup.

parent 33b04792
1999-06-17 Morten Welinder <terra@diku.dk>
* src/complex.c: Fix includes.
* src/fn-eng.c (gnumeric_impower): Use new complex_pow.
(callback_function_imoper): Benefit from new and more intuitive
behavoiur of complex_mul and complex_add.
* src/complex.h (complex_mod): Use hypot for better precision.
(complex_*): Use complex_init when possible. (This means that the
output can be the same as one of the inputs without any trouble.)
(complex_pow): New function.
1999-06-17 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-stat.c (gnumeric_percentrank): Interpolation and rounding
fixes.
1999-06-17 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-eng.c (gnumeric_erf): ERF() changed back to the previous
form. Negative arguments are wrong.
1999-06-16 Morten Welinder <terra@diku.dk>
* src/complex.h, src/complex.c: New files.
......@@ -23,7 +36,7 @@
* samples/finfuns.xls: A new file for financial functions.
* samples/engfuns.xls: A new file for engineering functions.
* samples/mathfuns.xls: COMBIN and FACT fixed.
* samples/statfuns.xls: Accuracy dropped again.
......@@ -48,7 +61,7 @@
* src/fn-eng.c (gnumeric_improduct, gnumeric_imsum): Made IMSUM()
and IMPRODUCT() to take variable number of arguments.
1999-06-15 Morten Welinder <terra@diku.dk>
* src/style.c (style_font_new_simple): Plug leak.
......
1999-06-17 Morten Welinder <terra@diku.dk>
* src/complex.c: Fix includes.
* src/fn-eng.c (gnumeric_impower): Use new complex_pow.
(callback_function_imoper): Benefit from new and more intuitive
behavoiur of complex_mul and complex_add.
* src/complex.h (complex_mod): Use hypot for better precision.
(complex_*): Use complex_init when possible. (This means that the
output can be the same as one of the inputs without any trouble.)
(complex_pow): New function.
1999-06-17 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-stat.c (gnumeric_percentrank): Interpolation and rounding
fixes.
1999-06-17 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-eng.c (gnumeric_erf): ERF() changed back to the previous
form. Negative arguments are wrong.
1999-06-16 Morten Welinder <terra@diku.dk>
* src/complex.h, src/complex.c: New files.
......@@ -23,7 +36,7 @@
* samples/finfuns.xls: A new file for financial functions.
* samples/engfuns.xls: A new file for engineering functions.
* samples/mathfuns.xls: COMBIN and FACT fixed.
* samples/statfuns.xls: Accuracy dropped again.
......@@ -48,7 +61,7 @@
* src/fn-eng.c (gnumeric_improduct, gnumeric_imsum): Made IMSUM()
and IMPRODUCT() to take variable number of arguments.
1999-06-15 Morten Welinder <terra@diku.dk>
* src/style.c (style_font_new_simple): Plug leak.
......
1999-06-17 Morten Welinder <terra@diku.dk>
* src/complex.c: Fix includes.
* src/fn-eng.c (gnumeric_impower): Use new complex_pow.
(callback_function_imoper): Benefit from new and more intuitive
behavoiur of complex_mul and complex_add.
* src/complex.h (complex_mod): Use hypot for better precision.
(complex_*): Use complex_init when possible. (This means that the
output can be the same as one of the inputs without any trouble.)
(complex_pow): New function.
1999-06-17 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-stat.c (gnumeric_percentrank): Interpolation and rounding
fixes.
1999-06-17 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-eng.c (gnumeric_erf): ERF() changed back to the previous
form. Negative arguments are wrong.
1999-06-16 Morten Welinder <terra@diku.dk>
* src/complex.h, src/complex.c: New files.
......@@ -23,7 +36,7 @@
* samples/finfuns.xls: A new file for financial functions.
* samples/engfuns.xls: A new file for engineering functions.
* samples/mathfuns.xls: COMBIN and FACT fixed.
* samples/statfuns.xls: Accuracy dropped again.
......@@ -48,7 +61,7 @@
* src/fn-eng.c (gnumeric_improduct, gnumeric_imsum): Made IMSUM()
and IMPRODUCT() to take variable number of arguments.
1999-06-15 Morten Welinder <terra@diku.dk>
* src/style.c (style_font_new_simple): Plug leak.
......
1999-06-17 Morten Welinder <terra@diku.dk>
* src/complex.c: Fix includes.
* src/fn-eng.c (gnumeric_impower): Use new complex_pow.
(callback_function_imoper): Benefit from new and more intuitive
behavoiur of complex_mul and complex_add.
* src/complex.h (complex_mod): Use hypot for better precision.
(complex_*): Use complex_init when possible. (This means that the
output can be the same as one of the inputs without any trouble.)
(complex_pow): New function.
1999-06-17 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-stat.c (gnumeric_percentrank): Interpolation and rounding
fixes.
1999-06-17 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-eng.c (gnumeric_erf): ERF() changed back to the previous
form. Negative arguments are wrong.
1999-06-16 Morten Welinder <terra@diku.dk>
* src/complex.h, src/complex.c: New files.
......@@ -23,7 +36,7 @@
* samples/finfuns.xls: A new file for financial functions.
* samples/engfuns.xls: A new file for engineering functions.
* samples/mathfuns.xls: COMBIN and FACT fixed.
* samples/statfuns.xls: Accuracy dropped again.
......@@ -48,7 +61,7 @@
* src/fn-eng.c (gnumeric_improduct, gnumeric_imsum): Made IMSUM()
and IMPRODUCT() to take variable number of arguments.
1999-06-15 Morten Welinder <terra@diku.dk>
* src/style.c (style_font_new_simple): Plug leak.
......
......@@ -845,7 +845,7 @@ static Value *
gnumeric_impower (struct FunctionDefinition *fd,
Value *argv [], char **error_string)
{
complex_t a, b, lna, b_lna, res;
complex_t a, b, res;
char imunit;
if (value_get_as_complex (argv[0], &a, &imunit)) {
......@@ -858,14 +858,12 @@ gnumeric_impower (struct FunctionDefinition *fd,
return NULL;
}
if (a.re == 0) {
if (complex_real_p (&a) && a.re <= 0 && !complex_real_p (&b)) {
*error_string = gnumeric_err_DIV0;
return NULL;
}
complex_ln (&lna, &a);
complex_mul (&b_lna, &b, &lna);
complex_exp (&res, &b_lna);
complex_pow (&res, &a, &b);
return value_new_complex (&res, imunit);
}
......@@ -1008,7 +1006,7 @@ callback_function_imoper (Sheet *sheet, Value *value,
char **error_string, void *closure)
{
eng_imoper_t *result = closure;
complex_t c, newres;
complex_t c;
char *imptr, dummy;
imptr = VALUE_IS_NUMBER (value) ? &dummy : &result->imunit;
......@@ -1019,17 +1017,15 @@ callback_function_imoper (Sheet *sheet, Value *value,
switch (result->type) {
case Improduct:
complex_mul (&newres, &result->res, &c);
complex_mul (&result->res, &result->res, &c);
break;
case Imsum:
complex_add (&newres, &result->res, &c);
complex_add (&result->res, &result->res, &c);
break;
default:
abort ();
}
/* Complex routines assume pointers are different. */
result->res = newres;
return TRUE;
}
......
......@@ -7,6 +7,7 @@
*/
#include <glib.h>
#include <stdlib.h>
#define GNUMERIC_COMPLEX_IMPLEMENTATION
#include "complex.h"
......@@ -131,30 +132,3 @@ complex_from_string (complex_t *dst, const char *src, char *imunit)
}
/* ------------------------------------------------------------------------- */
void
complex_to_polar (float_t *mod, float_t *angle, const complex_t *src)
{
*mod = complex_mod (src);
*angle = complex_angle (src);
}
/* ------------------------------------------------------------------------- */
void
complex_from_polar (complex_t *dst, float_t mod, float_t angle)
{
complex_init (dst, mod * cos (angle), mod * sin (angle));
}
/* ------------------------------------------------------------------------- */
void
complex_sqrt (complex_t *dst, const complex_t *src)
{
complex_from_polar (dst,
sqrt (complex_mod (src)),
complex_angle (src) / 2);
}
/* ------------------------------------------------------------------------- */
......@@ -38,10 +38,6 @@ char *complex_to_string (const complex_t *src, const char *reformat,
int complex_from_string (complex_t *dst, const char *src, char *imunit);
void complex_sqrt (complex_t *dst, const complex_t *src);
void complex_to_polar (float_t *mod, float_t *angle, const complex_t *src);
void complex_from_polar (complex_t *dst, float_t mod, float_t angle);
/* ------------------------------------------------------------------------- */
GNUMERIC_COMPLEX_PROTO (void complex_init (complex_t *dst, float_t re, float_t im))
......@@ -85,7 +81,7 @@ GNUMERIC_COMPLEX_PROTO (int complex_zero_p (const complex_t *src))
GNUMERIC_COMPLEX_PROTO (float_t complex_mod (const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
return sqrt (src->re * src->re + src->im * src->im);
return hypot (src->re, src->im);
}
#endif
......@@ -100,11 +96,29 @@ GNUMERIC_COMPLEX_PROTO (float_t complex_angle (const complex_t *src))
/* ------------------------------------------------------------------------- */
GNUMERIC_COMPLEX_PROTO (void complex_to_polar (float_t *mod, float_t *angle, const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
*mod = complex_mod (src);
*angle = complex_angle (src);
}
#endif
/* ------------------------------------------------------------------------- */
GNUMERIC_COMPLEX_PROTO (void complex_from_polar (complex_t *dst, float_t mod, float_t angle))
#ifdef GNUMERIC_COMPLEX_BODY
{
complex_init (dst, mod * cos (angle), mod * sin (angle));
}
#endif
/* ------------------------------------------------------------------------- */
GNUMERIC_COMPLEX_PROTO (void complex_conj (complex_t *dst, const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
dst->re = src->re;
dst->im = -src->im;
complex_init (dst, src->re, -src->im);
}
#endif
......@@ -113,8 +127,7 @@ GNUMERIC_COMPLEX_PROTO (void complex_conj (complex_t *dst, const complex_t *src)
GNUMERIC_COMPLEX_PROTO (void complex_add (complex_t *dst, const complex_t *a, const complex_t *b))
#ifdef GNUMERIC_COMPLEX_BODY
{
dst->re = a->re + b->re;
dst->im = a->im + b->im;
complex_init (dst, a->re + b->re, a->im + b->im);
}
#endif
......@@ -123,8 +136,7 @@ GNUMERIC_COMPLEX_PROTO (void complex_add (complex_t *dst, const complex_t *a, co
GNUMERIC_COMPLEX_PROTO (void complex_sub (complex_t *dst, const complex_t *a, const complex_t *b))
#ifdef GNUMERIC_COMPLEX_BODY
{
dst->re = a->re - b->re;
dst->im = a->im - b->im;
complex_init (dst, a->re - b->re, a->im - b->im);
}
#endif
......@@ -133,8 +145,9 @@ GNUMERIC_COMPLEX_PROTO (void complex_sub (complex_t *dst, const complex_t *a, co
GNUMERIC_COMPLEX_PROTO (void complex_mul (complex_t *dst, const complex_t *a, const complex_t *b))
#ifdef GNUMERIC_COMPLEX_BODY
{
dst->re = a->re * b->re - a->im * b->im;
dst->im = a->re * b->im + a->im * b->re;
complex_init (dst,
a->re * b->re - a->im * b->im,
a->re * b->im + a->im * b->re);
}
#endif
......@@ -146,8 +159,9 @@ GNUMERIC_COMPLEX_PROTO (void complex_div (complex_t *dst, const complex_t *a, co
float_t modsqr;
modsqr = b->re * b->re + b->im * b->im;
dst->re = (a->re * b->re + a->im * b->im) / modsqr;
dst->im = (a->im * b->re - a->re * b->im) / modsqr;
complex_init (dst,
(a->re * b->re + a->im * b->im) / modsqr,
(a->im * b->re - a->re * b->im) / modsqr);
}
#endif
......@@ -156,8 +170,9 @@ GNUMERIC_COMPLEX_PROTO (void complex_div (complex_t *dst, const complex_t *a, co
GNUMERIC_COMPLEX_PROTO (void complex_exp (complex_t *dst, const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
dst->re = exp (src->re) * cos (src->im);
dst->im = exp (src->re) * sin (src->im);
complex_init (dst,
exp (src->re) * cos (src->im),
exp (src->re) * sin (src->im));
}
#endif
......@@ -166,8 +181,27 @@ GNUMERIC_COMPLEX_PROTO (void complex_exp (complex_t *dst, const complex_t *src))
GNUMERIC_COMPLEX_PROTO (void complex_ln (complex_t *dst, const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
dst->re = log (complex_mod (src));
dst->im = complex_angle (src);
complex_init (dst,
log (complex_mod (src)),
complex_angle (src));
}
#endif
/* ------------------------------------------------------------------------- */
GNUMERIC_COMPLEX_PROTO (void complex_pow (complex_t *dst, const complex_t *a, const complex_t *b))
#ifdef GNUMERIC_COMPLEX_BODY
{
complex_t lna, b_lna;
/* ln is not defined for reals less than or equal to zero. */
if (complex_real_p (a) && complex_real_p (b))
complex_init (dst, pow (a->re, b->re), 0);
else {
complex_ln (&lna, a);
complex_mul (&b_lna, b, &lna);
complex_exp (dst, &b_lna);
}
}
#endif
......@@ -176,8 +210,9 @@ GNUMERIC_COMPLEX_PROTO (void complex_ln (complex_t *dst, const complex_t *src))
GNUMERIC_COMPLEX_PROTO (void complex_sin (complex_t *dst, const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
dst->re = sin (src->re) * cosh (src->im);
dst->im = cos (src->re) * sinh (src->im);
complex_init (dst,
sin (src->re) * cosh (src->im),
cos (src->re) * sinh (src->im));
}
#endif
......@@ -186,8 +221,9 @@ GNUMERIC_COMPLEX_PROTO (void complex_sin (complex_t *dst, const complex_t *src))
GNUMERIC_COMPLEX_PROTO (void complex_cos (complex_t *dst, const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
dst->re = cos (src->re) * cosh (src->im);
dst->im = -sin (src->re) * sinh (src->im);
complex_init (dst,
cos (src->re) * cosh (src->im),
-sin (src->re) * sinh (src->im));
}
#endif
......@@ -206,6 +242,17 @@ GNUMERIC_COMPLEX_PROTO (void complex_tan (complex_t *dst, const complex_t *src))
/* ------------------------------------------------------------------------- */
GNUMERIC_COMPLEX_PROTO (void complex_sqrt (complex_t *dst, const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
complex_from_polar (dst,
sqrt (complex_mod (src)),
complex_angle (src) / 2);
}
#endif
/* ------------------------------------------------------------------------- */
#undef GNUMERIC_COMPLEX_PROTO
#undef GNUMERIC_COMPLEX_BODY
......
......@@ -845,7 +845,7 @@ static Value *
gnumeric_impower (struct FunctionDefinition *fd,
Value *argv [], char **error_string)
{
complex_t a, b, lna, b_lna, res;
complex_t a, b, res;
char imunit;
if (value_get_as_complex (argv[0], &a, &imunit)) {
......@@ -858,14 +858,12 @@ gnumeric_impower (struct FunctionDefinition *fd,
return NULL;
}
if (a.re == 0) {
if (complex_real_p (&a) && a.re <= 0 && !complex_real_p (&b)) {
*error_string = gnumeric_err_DIV0;
return NULL;
}
complex_ln (&lna, &a);
complex_mul (&b_lna, &b, &lna);
complex_exp (&res, &b_lna);
complex_pow (&res, &a, &b);
return value_new_complex (&res, imunit);
}
......@@ -1008,7 +1006,7 @@ callback_function_imoper (Sheet *sheet, Value *value,
char **error_string, void *closure)
{
eng_imoper_t *result = closure;
complex_t c, newres;
complex_t c;
char *imptr, dummy;
imptr = VALUE_IS_NUMBER (value) ? &dummy : &result->imunit;
......@@ -1019,17 +1017,15 @@ callback_function_imoper (Sheet *sheet, Value *value,
switch (result->type) {
case Improduct:
complex_mul (&newres, &result->res, &c);
complex_mul (&result->res, &result->res, &c);
break;
case Imsum:
complex_add (&newres, &result->res, &c);
complex_add (&result->res, &result->res, &c);
break;
default:
abort ();
}
/* Complex routines assume pointers are different. */
result->res = newres;
return TRUE;
}
......
......@@ -845,7 +845,7 @@ static Value *
gnumeric_impower (struct FunctionDefinition *fd,
Value *argv [], char **error_string)
{
complex_t a, b, lna, b_lna, res;
complex_t a, b, res;
char imunit;
if (value_get_as_complex (argv[0], &a, &imunit)) {
......@@ -858,14 +858,12 @@ gnumeric_impower (struct FunctionDefinition *fd,
return NULL;
}
if (a.re == 0) {
if (complex_real_p (&a) && a.re <= 0 && !complex_real_p (&b)) {
*error_string = gnumeric_err_DIV0;
return NULL;
}
complex_ln (&lna, &a);
complex_mul (&b_lna, &b, &lna);
complex_exp (&res, &b_lna);
complex_pow (&res, &a, &b);
return value_new_complex (&res, imunit);
}
......@@ -1008,7 +1006,7 @@ callback_function_imoper (Sheet *sheet, Value *value,
char **error_string, void *closure)
{
eng_imoper_t *result = closure;
complex_t c, newres;
complex_t c;
char *imptr, dummy;
imptr = VALUE_IS_NUMBER (value) ? &dummy : &result->imunit;
......@@ -1019,17 +1017,15 @@ callback_function_imoper (Sheet *sheet, Value *value,
switch (result->type) {
case Improduct:
complex_mul (&newres, &result->res, &c);
complex_mul (&result->res, &result->res, &c);
break;
case Imsum:
complex_add (&newres, &result->res, &c);
complex_add (&result->res, &result->res, &c);
break;
default:
abort ();
}
/* Complex routines assume pointers are different. */
result->res = newres;
return TRUE;
}
......
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