complex.h 6.84 KB
Newer Older
1 2 3 4 5 6 7
#ifndef GNUMERIC_COMPLEX_H
#define GNUMERIC_COMPLEX_H

#include "numbers.h"
#include <math.h>

typedef struct {
8
	gnm_float re, im;
9 10 11 12 13 14 15 16 17 18 19 20 21
} 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.  */
22
#define GNUMERIC_COMPLEX_PROTO(p) p; extern __inline__ p
23 24 25 26 27
#define GNUMERIC_COMPLEX_BODY

#else

/* No gcc -- no inline functions.  */
28
#define GNUMERIC_COMPLEX_PROTO(p) extern p;
29 30 31 32 33 34 35 36 37 38 39 40 41 42
#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);

/* ------------------------------------------------------------------------- */

43
GNUMERIC_COMPLEX_PROTO (void complex_init (complex_t *dst, gnm_float re, gnm_float im))
44 45 46 47 48 49 50 51 52
#ifdef GNUMERIC_COMPLEX_BODY
{
	dst->re = re;
	dst->im = im;
}
#endif

/* ------------------------------------------------------------------------- */

53
GNUMERIC_COMPLEX_PROTO (void complex_real (complex_t *dst, gnm_float re))
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
#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

/* ------------------------------------------------------------------------- */

81
GNUMERIC_COMPLEX_PROTO (gnm_float complex_mod (const complex_t *src))
82 83
#ifdef GNUMERIC_COMPLEX_BODY
{
84
	return hypotgnum (src->re, src->im);
85 86 87 88 89
}
#endif

/* ------------------------------------------------------------------------- */

90
GNUMERIC_COMPLEX_PROTO (gnm_float complex_angle (const complex_t *src))
91 92
#ifdef GNUMERIC_COMPLEX_BODY
{
93
	return atan2gnum (src->im, src->re);
94 95 96 97 98
}
#endif

/* ------------------------------------------------------------------------- */

99
GNUMERIC_COMPLEX_PROTO (void complex_to_polar (gnm_float *mod, gnm_float *angle, const complex_t *src))
100 101 102 103 104 105 106 107 108
#ifdef GNUMERIC_COMPLEX_BODY
{
	*mod = complex_mod (src);
	*angle = complex_angle (src);
}
#endif

/* ------------------------------------------------------------------------- */

109
GNUMERIC_COMPLEX_PROTO (void complex_from_polar (complex_t *dst, gnm_float mod, gnm_float angle))
110 111
#ifdef GNUMERIC_COMPLEX_BODY
{
112
	complex_init (dst, mod * cosgnum (angle), mod * singnum (angle));
113 114 115 116 117
}
#endif

/* ------------------------------------------------------------------------- */

118 119 120
GNUMERIC_COMPLEX_PROTO (void complex_conj (complex_t *dst, const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
121
	complex_init (dst, src->re, -src->im);
122 123 124 125 126
}
#endif

/* ------------------------------------------------------------------------- */

127
GNUMERIC_COMPLEX_PROTO (void complex_scale_real (complex_t *dst, gnm_float f))
Morten Welinder's avatar
Morten Welinder committed
128 129 130 131 132 133 134 135 136
#ifdef GNUMERIC_COMPLEX_BODY
{
	dst->re *= f;
	dst->im *= f;
}
#endif

/* ------------------------------------------------------------------------- */

137 138 139
GNUMERIC_COMPLEX_PROTO (void complex_add (complex_t *dst, const complex_t *a, const complex_t *b))
#ifdef GNUMERIC_COMPLEX_BODY
{
140
	complex_init (dst, a->re + b->re, a->im + b->im);
141 142 143 144 145 146 147 148
}
#endif

/* ------------------------------------------------------------------------- */

GNUMERIC_COMPLEX_PROTO (void complex_sub (complex_t *dst, const complex_t *a, const complex_t *b))
#ifdef GNUMERIC_COMPLEX_BODY
{
149
	complex_init (dst, a->re - b->re, a->im - b->im);
150 151 152 153 154 155 156 157
}
#endif

/* ------------------------------------------------------------------------- */

GNUMERIC_COMPLEX_PROTO (void complex_mul (complex_t *dst, const complex_t *a, const complex_t *b))
#ifdef GNUMERIC_COMPLEX_BODY
{
158 159 160
	complex_init (dst,
		      a->re * b->re - a->im * b->im,
		      a->re * b->im + a->im * b->re);
161 162 163 164 165 166 167 168
}
#endif

/* ------------------------------------------------------------------------- */

GNUMERIC_COMPLEX_PROTO (void complex_div (complex_t *dst, const complex_t *a, const complex_t *b))
#ifdef GNUMERIC_COMPLEX_BODY
{
169
	gnm_float modsqr;
170 171

	modsqr = b->re * b->re + b->im * b->im;
172 173 174
	complex_init (dst,
		      (a->re * b->re + a->im * b->im) / modsqr,
		      (a->im * b->re - a->re * b->im) / modsqr);
175 176 177 178 179 180 181 182
}
#endif

/* ------------------------------------------------------------------------- */

GNUMERIC_COMPLEX_PROTO (void complex_exp (complex_t *dst, const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
183
	complex_init (dst,
184 185
		      expgnum (src->re) * cosgnum (src->im),
		      expgnum (src->re) * singnum (src->im));
186 187 188 189 190 191 192 193
}
#endif

/* ------------------------------------------------------------------------- */

GNUMERIC_COMPLEX_PROTO (void complex_ln (complex_t *dst, const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
194
	complex_init (dst,
195
		      loggnum (complex_mod (src)),
196 197 198 199 200 201 202 203 204 205 206 207 208
		      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))
209
		complex_init (dst, powgnum (a->re, b->re), 0);
210 211 212 213 214
	else {
		complex_ln (&lna, a);
		complex_mul (&b_lna, b, &lna);
		complex_exp (dst, &b_lna);
	}
215 216 217 218 219 220 221 222
}
#endif

/* ------------------------------------------------------------------------- */

GNUMERIC_COMPLEX_PROTO (void complex_sin (complex_t *dst, const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
223
	complex_init (dst,
224 225
		      singnum (src->re) * coshgnum (src->im),
		      cosgnum (src->re) * sinhgnum (src->im));
226 227 228 229 230 231 232 233
}
#endif

/* ------------------------------------------------------------------------- */

GNUMERIC_COMPLEX_PROTO (void complex_cos (complex_t *dst, const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
234
	complex_init (dst,
235 236
		      cosgnum (src->re) * coshgnum (src->im),
		      -singnum (src->re) * sinhgnum (src->im));
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
}
#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

/* ------------------------------------------------------------------------- */

255 256 257 258
GNUMERIC_COMPLEX_PROTO (void complex_sqrt (complex_t *dst, const complex_t *src))
#ifdef GNUMERIC_COMPLEX_BODY
{
	complex_from_polar (dst,
259
			    sqrtgnum (complex_mod (src)),
260 261 262 263 264 265
			    complex_angle (src) / 2);
}
#endif

/* ------------------------------------------------------------------------- */

266 267 268 269
#undef GNUMERIC_COMPLEX_PROTO
#undef GNUMERIC_COMPLEX_BODY

#endif