Commit f6f3582b authored by Morten Welinder's avatar Morten Welinder

Major cleanup for complex number calculations.

parent 8314ae0b
1999-06-16 Morten Welinder <terra@diku.dk>
* src/complex.h, src/complex.c: New files.
* src/fn-eng.c: Use complex.c; improve precision, fix a few bugs,
plug a few leaks, add a few functions, and generally be merry.
* src/Makefile.am (GNUMERIC_BASE_SOURCES): Add complex.c and
complex.h.
1999-06-16 Jukka-Pekka Iivonen <iivonen@iki.fi>
* samples/finfuns.xls: A new file for financial functions.
......
1999-06-16 Morten Welinder <terra@diku.dk>
* src/complex.h, src/complex.c: New files.
* src/fn-eng.c: Use complex.c; improve precision, fix a few bugs,
plug a few leaks, add a few functions, and generally be merry.
* src/Makefile.am (GNUMERIC_BASE_SOURCES): Add complex.c and
complex.h.
1999-06-16 Jukka-Pekka Iivonen <iivonen@iki.fi>
* samples/finfuns.xls: A new file for financial functions.
......
1999-06-16 Morten Welinder <terra@diku.dk>
* src/complex.h, src/complex.c: New files.
* src/fn-eng.c: Use complex.c; improve precision, fix a few bugs,
plug a few leaks, add a few functions, and generally be merry.
* src/Makefile.am (GNUMERIC_BASE_SOURCES): Add complex.c and
complex.h.
1999-06-16 Jukka-Pekka Iivonen <iivonen@iki.fi>
* samples/finfuns.xls: A new file for financial functions.
......
1999-06-16 Morten Welinder <terra@diku.dk>
* src/complex.h, src/complex.c: New files.
* src/fn-eng.c: Use complex.c; improve precision, fix a few bugs,
plug a few leaks, add a few functions, and generally be merry.
* src/Makefile.am (GNUMERIC_BASE_SOURCES): Add complex.c and
complex.h.
1999-06-16 Jukka-Pekka Iivonen <iivonen@iki.fi>
* samples/finfuns.xls: A new file for financial functions.
......
This diff is collapsed.
......@@ -42,6 +42,8 @@ GNUMERIC_BASE_SOURCES = \
clipboard.h \
color.c \
color.h \
complex.h \
complex.c \
corba.h \
cursors.c \
cursors.h \
......
/*
* complex.c: A quick library for complex math.
*
* Author:
* Morten Welinder <terra@diku.dk>
* Jukka-Pekka Iivonen <iivonen@iki.fi>
*/
#include <glib.h>
#define GNUMERIC_COMPLEX_IMPLEMENTATION
#include "complex.h"
/* ------------------------------------------------------------------------- */
char *
complex_to_string (const complex_t *src, const char *reformat,
const char *imformat, char imunit)
{
char *re_buffer = NULL;
char *im_buffer = NULL;
char *sign = "";
char *suffix = "";
char *res;
char suffix_buffer[2];
if (src->re != 0 || src->im == 0) {
/* We have a real part. */
re_buffer = g_strdup_printf (reformat, src->re);
}
if (src->im != 0) {
/* We have an imaginary part. */
suffix = suffix_buffer;
suffix_buffer[0] = imunit;
suffix_buffer[1] = 0;
if (src->im == 1) {
if (re_buffer)
sign = "+";
} else if (src->im == -1) {
sign = "-";
} else {
im_buffer = g_strdup_printf (reformat, src->im);
if (re_buffer && *im_buffer != '-' && *im_buffer != '+')
sign = (src->im >= 0) ? "+" : "-";
}
}
res = g_strconcat (re_buffer ? re_buffer : "",
sign,
im_buffer ? im_buffer : "",
suffix,
NULL);
if (re_buffer) g_free (re_buffer);
if (im_buffer) g_free (im_buffer);
return res;
}
/* ------------------------------------------------------------------------- */
static int
is_unit_imaginary (const char *src, float_t *im, char *imunit)
{
if (*src == '-') {
*im = -1.0;
src++;
} else {
*im = +1.0;
if (*src == '+') src++;
}
if ((*src == 'i' || *src == 'j') && src[1] == 0) {
*imunit = *src;
return 1;
} else
return 0;
}
int
complex_from_string (complex_t *dst, const char *src, char *imunit)
{
float_t x, y;
char *end;
/* Case: "i", "+i", "-i", ... */
if (is_unit_imaginary (src, &dst->im, imunit)) {
dst->re = 0;
return 0;
}
x = strtod (src, &end);
if (src == end)
return -1;
src = end;
/* Case: "42", "+42", "-42", ... */
if (*src == 0) {
complex_real (dst, x);
*imunit = 'i';
return 0;
}
/* Case: "42i", "+42i", "-42i", ... */
if ((*src == 'i' || *src == 'j') && src[1] == 0) {
complex_init (dst, 0, x);
*imunit = *src;
return 0;
}
/* Case: "42+i", "+42-i", "-42-i", ... */
if (is_unit_imaginary (src, &dst->im, imunit)) {
dst->re = x;
return 0;
}
y = strtod (src, &end);
if (src == end)
return -1;
src = end;
/* Case: "42+12i", "+42-12i", "-42-12i", ... */
if ((*src == 'i' || *src == 'j') && src[1] == 0) {
complex_init (dst, x, y);
*imunit = *src;
return 0;
}
return -1;
}
/* ------------------------------------------------------------------------- */
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);
}
/* ------------------------------------------------------------------------- */
#ifndef GNUMERIC_COMPLEX_H
#define GNUMERIC_COMPLEX_H
#include "numbers.h"
#include <math.h>
typedef struct {
float_t re, im;
} complex_t;
#ifdef GNUMERIC_COMPLEX_IMPLEMENTATION
/* The actual definitions. */
#define GNUMERIC_COMPLEX_PROTO(p) p; p
#define GNUMERIC_COMPLEX_BODY
#else
#ifdef __GNUC__
/* Have gcc -- inline functions. */
#define GNUMERIC_COMPLEX_PROTO(p) p; extern inline p
#define GNUMERIC_COMPLEX_BODY
#else
/* No gcc -- no inline functions. */
#define GNUMERIC_COMPLEX_INLINE(p) extern p;
#undef GNUMERIC_COMPLEX_BODY
#endif
#endif
/* ------------------------------------------------------------------------- */
char *complex_to_string (const complex_t *src, const char *reformat,
const char *imformat, char imunit);
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))
#ifdef GNUMERIC_COMPLEX_BODY
{
dst->re = re;
dst->im = im;
}
#endif
/* ------------------------------------------------------------------------- */
GNUMERIC_COMPLEX_PROTO (void complex_real (complex_t *dst, float_t re))
#ifdef GNUMERIC_COMPLEX_BODY
{
dst->re = re;
dst->im = 0;
}
#endif
/* ------------------------------------------------------------------------- */
GNUMERIC_COMPLEX_PROTO (int complex_real_p (const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
return src->im == 0;
}
#endif
/* ------------------------------------------------------------------------- */
GNUMERIC_COMPLEX_PROTO (int complex_zero_p (const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
return src->re == 0 && src->im == 0;
}
#endif
/* ------------------------------------------------------------------------- */
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);
}
#endif
/* ------------------------------------------------------------------------- */
GNUMERIC_COMPLEX_PROTO (float_t complex_angle (const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
return atan2 (src->im, src->re);
}
#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;
}
#endif
/* ------------------------------------------------------------------------- */
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;
}
#endif
/* ------------------------------------------------------------------------- */
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;
}
#endif
/* ------------------------------------------------------------------------- */
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;
}
#endif
/* ------------------------------------------------------------------------- */
GNUMERIC_COMPLEX_PROTO (void complex_div (complex_t *dst, const complex_t *a, const complex_t *b))
#ifdef GNUMERIC_COMPLEX_BODY
{
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;
}
#endif
/* ------------------------------------------------------------------------- */
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);
}
#endif
/* ------------------------------------------------------------------------- */
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);
}
#endif
/* ------------------------------------------------------------------------- */
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);
}
#endif
/* ------------------------------------------------------------------------- */
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);
}
#endif
/* ------------------------------------------------------------------------- */
GNUMERIC_COMPLEX_PROTO (void complex_tan (complex_t *dst, const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
complex_t s, c;
complex_sin (&s, src);
complex_cos (&c, src);
complex_div (dst, &s, &c);
}
#endif
/* ------------------------------------------------------------------------- */
#undef GNUMERIC_COMPLEX_PROTO
#undef GNUMERIC_COMPLEX_BODY
#endif
This diff is collapsed.
This diff is collapsed.
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