2 * complex.c: A quick library for complex math.
5 * Morten Welinder <terra@gnome.org>
6 * Jukka-Pekka Iivonen <iivonen@iki.fi>
9 #include <gnumeric-config.h>
19 /* ------------------------------------------------------------------------- */
22 gnm_complex_to_string (gnm_complex
const *src
, char imunit
)
24 char *re_buffer
= NULL
;
25 char *im_buffer
= NULL
;
26 char const *sign
= "";
27 char const *suffix
= "";
29 char suffix_buffer
[2];
30 const char *fmt
= "%.*" GNM_FORMAT_g
;
31 static int digits
= -1;
34 gnm_float l10
= gnm_log10 (FLT_RADIX
);
35 digits
= (int)gnm_ceil (GNM_MANT_DIG
* l10
) +
36 (l10
== (int)l10
? 0 : 1);
39 if (src
->re
!= 0 || src
->im
== 0) {
40 /* We have a real part. */
41 re_buffer
= g_strdup_printf (fmt
, digits
, src
->re
);
45 /* We have an imaginary part. */
46 suffix
= suffix_buffer
;
47 suffix_buffer
[0] = imunit
;
52 } else if (src
->im
== -1) {
55 im_buffer
= g_strdup_printf (fmt
, digits
, src
->im
);
56 if (re_buffer
&& *im_buffer
!= '-' && *im_buffer
!= '+')
57 sign
= (src
->im
>= 0) ? "+" : "-";
61 res
= g_strconcat (re_buffer
? re_buffer
: "",
63 im_buffer
? im_buffer
: "",
73 /* ------------------------------------------------------------------------- */
75 #define EAT_SPACES(src_) do { \
76 while (g_unichar_isspace (g_utf8_get_char (src_))) \
77 src_ = g_utf8_next_char (src_); \
80 #define HANDLE_SIGN(src_,sign_) do { \
82 case '+': sign_ = +1; src_++; EAT_SPACES (src_); break; \
83 case '-': sign_ = -1; src_++; EAT_SPACES (src_); break; \
84 default: sign_ = 0; break; \
89 * gnm_complex_from_string:
90 * @dst: return location
91 * @src: string to parse
92 * @imunit: (out): return location of imaginary unit.
94 * Returns: zero on success, -1 otherwise.
96 * This function differs from Excel's parsing in at least the following
98 * (1) We allow spaces before the imaginary unit used with an impled "1".
99 * Therefore we allow "+ i".
100 * (2) We do not allow a thousands separator as in "1,000i".
103 gnm_complex_from_string (gnm_complex
*dst
, char const *src
, char *imunit
)
110 HANDLE_SIGN (src
, sign
);
112 /* Case: "i", "+i", "-i", ... */
113 if (*src
== 'i' || *src
== 'j') {
116 x
= gnm_strto (src
, &end
);
117 if (src
== end
|| errno
== ERANGE
)
125 /* Case: "42", "+42", "-42", ... */
127 *dst
= GNM_CREAL (x
);
132 /* Case: "42i", "+42i", "-42i", "-i", "i", ... */
133 if (*src
== 'i' || *src
== 'j') {
137 *dst
= GNM_CMAKE (0, x
);
143 HANDLE_SIGN (src
, sign
);
147 if (*src
== 'i' || *src
== 'j') {
150 y
= gnm_strto (src
, &end
);
151 if (src
== end
|| errno
== ERANGE
)
159 /* Case: "42+12i", "+42-12i", "-42-12i", "-42+i", "+42-i", ... */
160 if (*src
== 'i' || *src
== 'j') {
164 *dst
= GNM_CMAKE (x
, y
);
172 /* ------------------------------------------------------------------------- */
175 gnm_complex_invalid_p (gnm_complex
const *src
)
177 return !(gnm_finite (src
->re
) && gnm_finite (src
->im
));
180 /* ------------------------------------------------------------------------- */