1 /*-
2 * Copyright (c) 2014-2018 Carsten Sonne Larsen <cs@innolan.net>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * Project homepage:
26 * https://amath.innolan.net
27 *
28 */
29
30 #include "prim.h"
31
32 #define REAL_PART(z) ((z).parts[0])
33 #define IMAG_PART(z) ((z).parts[1])
34
35 /**
36 * @brief Real part of complex number
37 */
creal(complex z)38 double creal(complex z)
39 {
40 return (REAL_PART(z));
41 }
42
43 /**
44 * @brief Imaginary part of complex number
45 */
cimag(complex z)46 double cimag(complex z)
47 {
48 return (IMAG_PART(z));
49 }
50
51 /**
52 * @brief Absolute value of complex number
53 */
cabs(complex z)54 double cabs(complex z)
55 {
56 return hypot(creal(z), cimag(z));
57 }
58
conj(complex z)59 complex conj(complex z)
60 {
61 IMAG_PART(z) = -IMAG_PART(z);
62 return cpack(REAL_PART(z), IMAG_PART(z));
63 }
64
65 /**
66 * @brief Pack two real numbers into a complex number
67 */
cpack(double x,double y)68 complex cpack(double x, double y)
69 {
70 complex z;
71
72 REAL_PART(z) = x;
73 IMAG_PART(z) = y;
74 return (z);
75 }
76
77 /**
78 * @brief Truncated value of complex number
79 */
ctrunc(complex z)80 complex ctrunc(complex z)
81 {
82 complex w;
83 w = cpack(trunc(creal(z)), trunc(cimag(z)));
84 return w;
85 }
86
87 /**
88 * @brief Floor value of complex number
89 */
cfloor(complex z)90 complex cfloor(complex z)
91 {
92 complex w;
93 w = cpack(floor(creal(z)), floor(cimag(z)));
94 return w;
95 }
96
97 /**
98 * @brief Ceiling value of complex number
99 */
cceil(complex z)100 complex cceil(complex z)
101 {
102 complex w;
103 w = cpack(ceil(creal(z)), ceil(cimag(z)));
104 return w;
105 }
106
107 /**
108 * @brief Division of two complex numbers
109 */
cround(complex z)110 complex cround(complex z)
111 {
112 complex w;
113 w = cpack(round(creal(z)), round(cimag(z)));
114 return w;
115 }
116
117 /**
118 * @brief Addition of two complex numbers
119 */
cadd(complex y,complex z)120 complex cadd(complex y, complex z)
121 {
122 complex w;
123 w = cpack(creal(y) + creal(z), cimag(y) + cimag(z));
124 return w;
125 }
126
127 /**
128 * @brief Subtraction of two complex numbers
129 */
csub(complex y,complex z)130 complex csub(complex y, complex z)
131 {
132 complex w;
133 w = cpack(creal(y) - creal(z), cimag(y) - cimag(z));
134 return w;
135 }
136
137 /**
138 * @brief Multiplication of two complex numbers
139 */
cmul(complex y,complex z)140 complex cmul(complex y, complex z)
141 {
142 complex w;
143 double a, b, c, d;
144
145 // (a+bi)(c+di)
146 a = creal(y);
147 b = cimag(y);
148 c = creal(z);
149 d = cimag(z);
150
151 // (ac -bd) + (ad + bc)i
152 w = cpack(a * c - b * d, a * d + b * c);
153 return w;
154 }
155
156 /**
157 * @brief Division of two complex numbers
158 */
cdiv(complex y,complex z)159 complex cdiv(complex y, complex z)
160 {
161 complex w;
162 double a, b, c, d;
163 double q, v, x;
164
165 a = creal(y);
166 b = cimag(y);
167 c = creal(z);
168 d = cimag(z);
169
170 q = c * c + d * d;
171 v = a * c + b * d;
172 x = b * c - a * d;
173
174 w = cpack(v / q, x / q);
175 return w;
176 }
177
178 /**
179 * @brief Reciprocal value of complex number
180 */
creci(complex z)181 complex creci(complex z)
182 {
183 complex w;
184 double q, a, b;
185
186 a = creal(z);
187 b = cimag(conj(z));
188 q = a * a + b * b;
189 w = cpack(a / q, b / q);
190
191 return w;
192 }
193
194 /**
195 * @brief Calculate cosh and sinh
196 */
cchsh(double x,double * c,double * s)197 void cchsh(double x, double* c, double* s)
198 {
199 double e, ei;
200
201 if (fabs(x) <= 0.5)
202 {
203 *c = cosh(x);
204 *s = sinh(x);
205 }
206 else
207 {
208 e = exp(x);
209 ei = 0.5 / e;
210 e = 0.5 * e;
211 *s = e - ei;
212 *c = e + ei;
213 }
214 }
215
216 /**
217 * @brief Calculate cosh and cos
218 */
cchc(double x,double * ch,double * c)219 void cchc(double x, double* ch, double* c)
220 {
221 *ch = cosh(2.0 * x);
222 *c = cos(2.0 * x);
223 }
224