1 // Warning: this file is included twice in
2 // aten/src/ATen/test/cuda_complex_math_test.cu
3
4 #include <c10/util/complex.h>
5 #include <gtest/gtest.h>
6
7 #ifndef PI
8 #define PI 3.141592653589793238463
9 #endif
10
11 #ifndef tol
12 #define tol 1e-6
13 #endif
14
15 // Exponential functions
16
C10_DEFINE_TEST(TestExponential,IPi)17 C10_DEFINE_TEST(TestExponential, IPi) {
18 // exp(i*pi) = -1
19 {
20 c10::complex<float> e_i_pi = std::exp(c10::complex<float>(0, float(PI)));
21 C10_ASSERT_NEAR(e_i_pi.real(), -1, tol);
22 C10_ASSERT_NEAR(e_i_pi.imag(), 0, tol);
23 }
24 {
25 c10::complex<float> e_i_pi = ::exp(c10::complex<float>(0, float(PI)));
26 C10_ASSERT_NEAR(e_i_pi.real(), -1, tol);
27 C10_ASSERT_NEAR(e_i_pi.imag(), 0, tol);
28 }
29 {
30 c10::complex<double> e_i_pi = std::exp(c10::complex<double>(0, PI));
31 C10_ASSERT_NEAR(e_i_pi.real(), -1, tol);
32 C10_ASSERT_NEAR(e_i_pi.imag(), 0, tol);
33 }
34 {
35 c10::complex<double> e_i_pi = ::exp(c10::complex<double>(0, PI));
36 C10_ASSERT_NEAR(e_i_pi.real(), -1, tol);
37 C10_ASSERT_NEAR(e_i_pi.imag(), 0, tol);
38 }
39 }
40
C10_DEFINE_TEST(TestExponential,EulerFormula)41 C10_DEFINE_TEST(TestExponential, EulerFormula) {
42 // exp(ix) = cos(x) + i * sin(x)
43 {
44 c10::complex<float> x(0.1, 1.2);
45 c10::complex<float> e = std::exp(x);
46 float expected_real = std::exp(x.real()) * std::cos(x.imag());
47 float expected_imag = std::exp(x.real()) * std::sin(x.imag());
48 C10_ASSERT_NEAR(e.real(), expected_real, tol);
49 C10_ASSERT_NEAR(e.imag(), expected_imag, tol);
50 }
51 {
52 c10::complex<float> x(0.1, 1.2);
53 c10::complex<float> e = ::exp(x);
54 float expected_real = ::exp(x.real()) * ::cos(x.imag());
55 float expected_imag = ::exp(x.real()) * ::sin(x.imag());
56 C10_ASSERT_NEAR(e.real(), expected_real, tol);
57 C10_ASSERT_NEAR(e.imag(), expected_imag, tol);
58 }
59 {
60 c10::complex<double> x(0.1, 1.2);
61 c10::complex<double> e = std::exp(x);
62 float expected_real = std::exp(x.real()) * std::cos(x.imag());
63 float expected_imag = std::exp(x.real()) * std::sin(x.imag());
64 C10_ASSERT_NEAR(e.real(), expected_real, tol);
65 C10_ASSERT_NEAR(e.imag(), expected_imag, tol);
66 }
67 {
68 c10::complex<double> x(0.1, 1.2);
69 c10::complex<double> e = ::exp(x);
70 float expected_real = ::exp(x.real()) * ::cos(x.imag());
71 float expected_imag = ::exp(x.real()) * ::sin(x.imag());
72 C10_ASSERT_NEAR(e.real(), expected_real, tol);
73 C10_ASSERT_NEAR(e.imag(), expected_imag, tol);
74 }
75 }
76
C10_DEFINE_TEST(TestExpm1,Normal)77 C10_DEFINE_TEST(TestExpm1, Normal) {
78 // expm1(x) = exp(x) - 1
79 {
80 c10::complex<float> x(0.1, 1.2);
81 c10::complex<float> l1 = std::expm1(x);
82 c10::complex<float> l2 = std::exp(x) - 1.0f;
83 C10_ASSERT_NEAR(l1.real(), l2.real(), tol);
84 C10_ASSERT_NEAR(l1.imag(), l2.imag(), tol);
85 }
86 {
87 c10::complex<double> x(0.1, 1.2);
88 c10::complex<double> l1 = std::expm1(x);
89 c10::complex<double> l2 = std::exp(x) - 1.0;
90 C10_ASSERT_NEAR(l1.real(), l2.real(), tol);
91 C10_ASSERT_NEAR(l1.imag(), l2.imag(), tol);
92 }
93 }
94
C10_DEFINE_TEST(TestExpm1,Small)95 C10_DEFINE_TEST(TestExpm1, Small) {
96 // expm1(x) = exp(x) - 1
97 // expm1(x) provides greater precision than exp(x) - 1 for small values of x
98 {
99 c10::complex<float> x(1e-30, 1e-30);
100 c10::complex<float> l1 = std::expm1(x);
101 C10_ASSERT_NEAR(l1.real(), 1e-30, tol);
102 C10_ASSERT_NEAR(l1.imag(), 1e-30, tol);
103 }
104 {
105 c10::complex<double> x(1e-100, 1e-100);
106 c10::complex<double> l1 = std::expm1(x);
107 C10_ASSERT_NEAR(l1.real(), 1e-30, tol);
108 C10_ASSERT_NEAR(l1.imag(), 1e-30, tol);
109 }
110 }
111
C10_DEFINE_TEST(TestLog,Definition)112 C10_DEFINE_TEST(TestLog, Definition) {
113 // log(x) = log(r) + i*theta
114 {
115 c10::complex<float> x(1.2, 3.4);
116 c10::complex<float> l = std::log(x);
117 float expected_real = std::log(std::abs(x));
118 float expected_imag = std::arg(x);
119 C10_ASSERT_NEAR(l.real(), expected_real, tol);
120 C10_ASSERT_NEAR(l.imag(), expected_imag, tol);
121 }
122 {
123 c10::complex<float> x(1.2, 3.4);
124 c10::complex<float> l = ::log(x);
125 float expected_real = ::log(std::abs(x));
126 float expected_imag = std::arg(x);
127 C10_ASSERT_NEAR(l.real(), expected_real, tol);
128 C10_ASSERT_NEAR(l.imag(), expected_imag, tol);
129 }
130 {
131 c10::complex<double> x(1.2, 3.4);
132 c10::complex<double> l = std::log(x);
133 float expected_real = std::log(std::abs(x));
134 float expected_imag = std::arg(x);
135 C10_ASSERT_NEAR(l.real(), expected_real, tol);
136 C10_ASSERT_NEAR(l.imag(), expected_imag, tol);
137 }
138 {
139 c10::complex<double> x(1.2, 3.4);
140 c10::complex<double> l = ::log(x);
141 float expected_real = ::log(std::abs(x));
142 float expected_imag = std::arg(x);
143 C10_ASSERT_NEAR(l.real(), expected_real, tol);
144 C10_ASSERT_NEAR(l.imag(), expected_imag, tol);
145 }
146 }
147
C10_DEFINE_TEST(TestLog10,Rev)148 C10_DEFINE_TEST(TestLog10, Rev) {
149 // log10(10^x) = x
150 {
151 c10::complex<float> x(0.1, 1.2);
152 c10::complex<float> l = std::log10(std::pow(float(10), x));
153 C10_ASSERT_NEAR(l.real(), float(0.1), tol);
154 C10_ASSERT_NEAR(l.imag(), float(1.2), tol);
155 }
156 {
157 c10::complex<float> x(0.1, 1.2);
158 c10::complex<float> l = ::log10(::pow(float(10), x));
159 C10_ASSERT_NEAR(l.real(), float(0.1), tol);
160 C10_ASSERT_NEAR(l.imag(), float(1.2), tol);
161 }
162 {
163 c10::complex<double> x(0.1, 1.2);
164 c10::complex<double> l = std::log10(std::pow(double(10), x));
165 C10_ASSERT_NEAR(l.real(), double(0.1), tol);
166 C10_ASSERT_NEAR(l.imag(), double(1.2), tol);
167 }
168 {
169 c10::complex<double> x(0.1, 1.2);
170 c10::complex<double> l = ::log10(::pow(double(10), x));
171 C10_ASSERT_NEAR(l.real(), double(0.1), tol);
172 C10_ASSERT_NEAR(l.imag(), double(1.2), tol);
173 }
174 }
175
C10_DEFINE_TEST(TestLog2,Rev)176 C10_DEFINE_TEST(TestLog2, Rev) {
177 // log2(2^x) = x
178 {
179 c10::complex<float> x(0.1, 1.2);
180 c10::complex<float> l = std::log2(std::pow(float(2), x));
181 C10_ASSERT_NEAR(l.real(), float(0.1), tol);
182 C10_ASSERT_NEAR(l.imag(), float(1.2), tol);
183 }
184 {
185 c10::complex<float> x(0.1, 1.2);
186 c10::complex<float> l = ::log2(std::pow(float(2), x));
187 C10_ASSERT_NEAR(l.real(), float(0.1), tol);
188 C10_ASSERT_NEAR(l.imag(), float(1.2), tol);
189 }
190 {
191 c10::complex<double> x(0.1, 1.2);
192 c10::complex<double> l = std::log2(std::pow(double(2), x));
193 C10_ASSERT_NEAR(l.real(), double(0.1), tol);
194 C10_ASSERT_NEAR(l.imag(), double(1.2), tol);
195 }
196 {
197 c10::complex<double> x(0.1, 1.2);
198 c10::complex<double> l = ::log2(std::pow(double(2), x));
199 C10_ASSERT_NEAR(l.real(), double(0.1), tol);
200 C10_ASSERT_NEAR(l.imag(), double(1.2), tol);
201 }
202 }
203
C10_DEFINE_TEST(TestLog1p,Normal)204 C10_DEFINE_TEST(TestLog1p, Normal) {
205 // log1p(x) = log(1 + x)
206 {
207 c10::complex<float> x(0.1, 1.2);
208 c10::complex<float> l1 = std::log1p(x);
209 c10::complex<float> l2 = std::log(1.0f + x);
210 C10_ASSERT_NEAR(l1.real(), l2.real(), tol);
211 C10_ASSERT_NEAR(l1.imag(), l2.imag(), tol);
212 }
213 {
214 c10::complex<double> x(0.1, 1.2);
215 c10::complex<double> l1 = std::log1p(x);
216 c10::complex<double> l2 = std::log(1.0 + x);
217 C10_ASSERT_NEAR(l1.real(), l2.real(), tol);
218 C10_ASSERT_NEAR(l1.imag(), l2.imag(), tol);
219 }
220 }
221
C10_DEFINE_TEST(TestLog1p,Small)222 C10_DEFINE_TEST(TestLog1p, Small) {
223 // log(1 + x) ~ x for |x| << 1
224 {
225 c10::complex<float> x(1e-9, 2e-9);
226 c10::complex<float> l = std::log1p(x);
227 C10_ASSERT_NEAR(l.real() / x.real(), 1, tol);
228 C10_ASSERT_NEAR(l.imag() / x.imag(), 1, tol);
229 }
230 {
231 c10::complex<double> x(1e-100, 2e-100);
232 c10::complex<double> l = std::log1p(x);
233 C10_ASSERT_NEAR(l.real() / x.real(), 1, tol);
234 C10_ASSERT_NEAR(l.imag() / x.imag(), 1, tol);
235 }
236 }
237
C10_DEFINE_TEST(TestLog1p,Extreme)238 C10_DEFINE_TEST(TestLog1p, Extreme) {
239 // log(1 + x) ~ x for |x| << 1 and in the brink of overflow / underflow
240 {
241 c10::complex<float> x(-1, 1e-30);
242 c10::complex<float> l = std::log1p(x);
243 C10_ASSERT_NEAR(l.real(), -69.07755278982137, tol);
244 C10_ASSERT_NEAR(l.imag(), 1.5707963267948966, tol);
245 }
246 {
247 c10::complex<float> x(-1, 1e30);
248 c10::complex<float> l = std::log1p(x);
249 C10_ASSERT_NEAR(l.real(), 69.07755278982137, tol);
250 C10_ASSERT_NEAR(l.imag(), 1.5707963267948966, tol);
251 }
252 {
253 c10::complex<float> x(1e30, 1);
254 c10::complex<float> l = std::log1p(x);
255 C10_ASSERT_NEAR(l.real(), 69.07755278982137, tol);
256 C10_ASSERT_NEAR(l.imag(), 1e-30, tol);
257 }
258 {
259 c10::complex<float> x(1e-30, 1);
260 c10::complex<float> l = std::log1p(x);
261 C10_ASSERT_NEAR(l.real(), 0.34657359027997264, tol);
262 C10_ASSERT_NEAR(l.imag(), 0.7853981633974483, tol);
263 }
264 {
265 c10::complex<float> x(1e30, 1e30);
266 c10::complex<float> l = std::log1p(x);
267 C10_ASSERT_NEAR(l.real(), 69.42412638010134, tol);
268 C10_ASSERT_NEAR(l.imag(), 0.7853981633974483, tol);
269 }
270 {
271 c10::complex<float> x(1e-38, 1e-38);
272 c10::complex<float> l = std::log1p(x);
273 C10_ASSERT_NEAR(l.real(), 1e-38, tol);
274 C10_ASSERT_NEAR(l.imag(), 1e-38, tol);
275 }
276 {
277 c10::complex<float> x(1e-38, 2e-30);
278 c10::complex<float> l = std::log1p(x);
279 C10_ASSERT_NEAR(l.real(), 1e-30, tol);
280 C10_ASSERT_NEAR(l.imag(), 2e-30, tol);
281 }
282 {
283 c10::complex<double> x(-1, 1e-250);
284 c10::complex<double> l = std::log1p(x);
285 C10_ASSERT_NEAR(l.real(), -575.6462732485114, tol);
286 C10_ASSERT_NEAR(l.imag(), 1.5707963267948966, tol);
287 }
288 {
289 c10::complex<double> x(-1, 1e250);
290 c10::complex<double> l = std::log1p(x);
291 C10_ASSERT_NEAR(l.real(), 575.6462732485114, tol);
292 C10_ASSERT_NEAR(l.imag(), 1.5707963267948966, tol);
293 }
294 {
295 c10::complex<double> x(1e250, 1);
296 c10::complex<double> l = std::log1p(x);
297 C10_ASSERT_NEAR(l.real(), 575.6462732485114, tol);
298 C10_ASSERT_NEAR(l.imag(), 1e-250, tol);
299 }
300 {
301 c10::complex<double> x(1e-250, 1);
302 c10::complex<double> l = std::log1p(x);
303 C10_ASSERT_NEAR(l.real(), 0.34657359027997264, tol);
304 C10_ASSERT_NEAR(l.imag(), 0.7853981633974483, tol);
305 }
306 {
307 c10::complex<double> x(1e250, 1e250);
308 c10::complex<double> l = std::log1p(x);
309 C10_ASSERT_NEAR(l.real(), 575.9928468387914, tol);
310 C10_ASSERT_NEAR(l.imag(), 0.7853981633974483, tol);
311 }
312 {
313 c10::complex<double> x(1e-250, 1e-250);
314 c10::complex<double> l = std::log1p(x);
315 C10_ASSERT_NEAR(l.real(), 1e-250, tol);
316 C10_ASSERT_NEAR(l.imag(), 1e-250, tol);
317 }
318 {
319 c10::complex<double> x(1e-250, 2e-250);
320 c10::complex<double> l = std::log1p(x);
321 C10_ASSERT_NEAR(l.real(), 1e-250, tol);
322 C10_ASSERT_NEAR(l.imag(), 2e-250, tol);
323 }
324 {
325 c10::complex<double> x(2e-308, 1.5e-250);
326 c10::complex<double> l = std::log1p(x);
327 C10_ASSERT_NEAR(l.real(), 2e-308, tol);
328 C10_ASSERT_NEAR(l.imag(), 1.5e-308, tol);
329 }
330 }
331
332 // Power functions
333
C10_DEFINE_TEST(TestPowSqrt,Equal)334 C10_DEFINE_TEST(TestPowSqrt, Equal) {
335 // x^0.5 = sqrt(x)
336 {
337 c10::complex<float> x(0.1, 1.2);
338 c10::complex<float> y = std::pow(x, float(0.5));
339 c10::complex<float> z = std::sqrt(x);
340 C10_ASSERT_NEAR(y.real(), z.real(), tol);
341 C10_ASSERT_NEAR(y.imag(), z.imag(), tol);
342 }
343 {
344 c10::complex<float> x(0.1, 1.2);
345 c10::complex<float> y = ::pow(x, float(0.5));
346 c10::complex<float> z = ::sqrt(x);
347 C10_ASSERT_NEAR(y.real(), z.real(), tol);
348 C10_ASSERT_NEAR(y.imag(), z.imag(), tol);
349 }
350 {
351 c10::complex<double> x(0.1, 1.2);
352 c10::complex<double> y = std::pow(x, double(0.5));
353 c10::complex<double> z = std::sqrt(x);
354 C10_ASSERT_NEAR(y.real(), z.real(), tol);
355 C10_ASSERT_NEAR(y.imag(), z.imag(), tol);
356 }
357 {
358 c10::complex<double> x(0.1, 1.2);
359 c10::complex<double> y = ::pow(x, double(0.5));
360 c10::complex<double> z = ::sqrt(x);
361 C10_ASSERT_NEAR(y.real(), z.real(), tol);
362 C10_ASSERT_NEAR(y.imag(), z.imag(), tol);
363 }
364 }
365
C10_DEFINE_TEST(TestPow,Square)366 C10_DEFINE_TEST(TestPow, Square) {
367 // x^2 = x * x
368 {
369 c10::complex<float> x(0.1, 1.2);
370 c10::complex<float> y = std::pow(x, float(2));
371 c10::complex<float> z = x * x;
372 C10_ASSERT_NEAR(y.real(), z.real(), tol);
373 C10_ASSERT_NEAR(y.imag(), z.imag(), tol);
374 }
375 {
376 c10::complex<float> x(0.1, 1.2);
377 c10::complex<float> y = ::pow(x, float(2));
378 c10::complex<float> z = x * x;
379 C10_ASSERT_NEAR(y.real(), z.real(), tol);
380 C10_ASSERT_NEAR(y.imag(), z.imag(), tol);
381 }
382 {
383 c10::complex<double> x(0.1, 1.2);
384 c10::complex<double> y = std::pow(x, double(2));
385 c10::complex<double> z = x * x;
386 C10_ASSERT_NEAR(y.real(), z.real(), tol);
387 C10_ASSERT_NEAR(y.imag(), z.imag(), tol);
388 }
389 {
390 c10::complex<double> x(0.1, 1.2);
391 c10::complex<double> y = ::pow(x, double(2));
392 c10::complex<double> z = x * x;
393 C10_ASSERT_NEAR(y.real(), z.real(), tol);
394 C10_ASSERT_NEAR(y.imag(), z.imag(), tol);
395 }
396 }
397
398 // Trigonometric functions and hyperbolic functions
399
C10_DEFINE_TEST(TestSinCosSinhCosh,Identity)400 C10_DEFINE_TEST(TestSinCosSinhCosh, Identity) {
401 // sin(x + i * y) = sin(x) * cosh(y) + i * cos(x) * sinh(y)
402 // cos(x + i * y) = cos(x) * cosh(y) - i * sin(x) * sinh(y)
403 {
404 c10::complex<float> x(0.1, 1.2);
405 c10::complex<float> y = std::sin(x);
406 float expected_real = std::sin(x.real()) * std::cosh(x.imag());
407 float expected_imag = std::cos(x.real()) * std::sinh(x.imag());
408 C10_ASSERT_NEAR(y.real(), expected_real, tol);
409 C10_ASSERT_NEAR(y.imag(), expected_imag, tol);
410 }
411 {
412 c10::complex<float> x(0.1, 1.2);
413 c10::complex<float> y = ::sin(x);
414 float expected_real = ::sin(x.real()) * ::cosh(x.imag());
415 float expected_imag = ::cos(x.real()) * ::sinh(x.imag());
416 C10_ASSERT_NEAR(y.real(), expected_real, tol);
417 C10_ASSERT_NEAR(y.imag(), expected_imag, tol);
418 }
419 {
420 c10::complex<float> x(0.1, 1.2);
421 c10::complex<float> y = std::cos(x);
422 float expected_real = std::cos(x.real()) * std::cosh(x.imag());
423 float expected_imag = -std::sin(x.real()) * std::sinh(x.imag());
424 C10_ASSERT_NEAR(y.real(), expected_real, tol);
425 C10_ASSERT_NEAR(y.imag(), expected_imag, tol);
426 }
427 {
428 c10::complex<float> x(0.1, 1.2);
429 c10::complex<float> y = ::cos(x);
430 float expected_real = ::cos(x.real()) * ::cosh(x.imag());
431 float expected_imag = -::sin(x.real()) * ::sinh(x.imag());
432 C10_ASSERT_NEAR(y.real(), expected_real, tol);
433 C10_ASSERT_NEAR(y.imag(), expected_imag, tol);
434 }
435 {
436 c10::complex<double> x(0.1, 1.2);
437 c10::complex<double> y = std::sin(x);
438 float expected_real = std::sin(x.real()) * std::cosh(x.imag());
439 float expected_imag = std::cos(x.real()) * std::sinh(x.imag());
440 C10_ASSERT_NEAR(y.real(), expected_real, tol);
441 C10_ASSERT_NEAR(y.imag(), expected_imag, tol);
442 }
443 {
444 c10::complex<double> x(0.1, 1.2);
445 c10::complex<double> y = ::sin(x);
446 float expected_real = ::sin(x.real()) * ::cosh(x.imag());
447 float expected_imag = ::cos(x.real()) * ::sinh(x.imag());
448 C10_ASSERT_NEAR(y.real(), expected_real, tol);
449 C10_ASSERT_NEAR(y.imag(), expected_imag, tol);
450 }
451 {
452 c10::complex<double> x(0.1, 1.2);
453 c10::complex<double> y = std::cos(x);
454 float expected_real = std::cos(x.real()) * std::cosh(x.imag());
455 float expected_imag = -std::sin(x.real()) * std::sinh(x.imag());
456 C10_ASSERT_NEAR(y.real(), expected_real, tol);
457 C10_ASSERT_NEAR(y.imag(), expected_imag, tol);
458 }
459 {
460 c10::complex<double> x(0.1, 1.2);
461 c10::complex<double> y = ::cos(x);
462 float expected_real = ::cos(x.real()) * ::cosh(x.imag());
463 float expected_imag = -::sin(x.real()) * ::sinh(x.imag());
464 C10_ASSERT_NEAR(y.real(), expected_real, tol);
465 C10_ASSERT_NEAR(y.imag(), expected_imag, tol);
466 }
467 }
468
C10_DEFINE_TEST(TestTan,Identity)469 C10_DEFINE_TEST(TestTan, Identity) {
470 // tan(x) = sin(x) / cos(x)
471 {
472 c10::complex<float> x(0.1, 1.2);
473 c10::complex<float> y = std::tan(x);
474 c10::complex<float> z = std::sin(x) / std::cos(x);
475 C10_ASSERT_NEAR(y.real(), z.real(), tol);
476 C10_ASSERT_NEAR(y.imag(), z.imag(), tol);
477 }
478 {
479 c10::complex<float> x(0.1, 1.2);
480 c10::complex<float> y = ::tan(x);
481 c10::complex<float> z = ::sin(x) / ::cos(x);
482 C10_ASSERT_NEAR(y.real(), z.real(), tol);
483 C10_ASSERT_NEAR(y.imag(), z.imag(), tol);
484 }
485 {
486 c10::complex<double> x(0.1, 1.2);
487 c10::complex<double> y = std::tan(x);
488 c10::complex<double> z = std::sin(x) / std::cos(x);
489 C10_ASSERT_NEAR(y.real(), z.real(), tol);
490 C10_ASSERT_NEAR(y.imag(), z.imag(), tol);
491 }
492 {
493 c10::complex<double> x(0.1, 1.2);
494 c10::complex<double> y = ::tan(x);
495 c10::complex<double> z = ::sin(x) / ::cos(x);
496 C10_ASSERT_NEAR(y.real(), z.real(), tol);
497 C10_ASSERT_NEAR(y.imag(), z.imag(), tol);
498 }
499 }
500
C10_DEFINE_TEST(TestTanh,Identity)501 C10_DEFINE_TEST(TestTanh, Identity) {
502 // tanh(x) = sinh(x) / cosh(x)
503 {
504 c10::complex<float> x(0.1, 1.2);
505 c10::complex<float> y = std::tanh(x);
506 c10::complex<float> z = std::sinh(x) / std::cosh(x);
507 C10_ASSERT_NEAR(y.real(), z.real(), tol);
508 C10_ASSERT_NEAR(y.imag(), z.imag(), tol);
509 }
510 {
511 c10::complex<float> x(0.1, 1.2);
512 c10::complex<float> y = ::tanh(x);
513 c10::complex<float> z = ::sinh(x) / ::cosh(x);
514 C10_ASSERT_NEAR(y.real(), z.real(), tol);
515 C10_ASSERT_NEAR(y.imag(), z.imag(), tol);
516 }
517 {
518 c10::complex<double> x(0.1, 1.2);
519 c10::complex<double> y = std::tanh(x);
520 c10::complex<double> z = std::sinh(x) / std::cosh(x);
521 C10_ASSERT_NEAR(y.real(), z.real(), tol);
522 C10_ASSERT_NEAR(y.imag(), z.imag(), tol);
523 }
524 {
525 c10::complex<double> x(0.1, 1.2);
526 c10::complex<double> y = ::tanh(x);
527 c10::complex<double> z = ::sinh(x) / ::cosh(x);
528 C10_ASSERT_NEAR(y.real(), z.real(), tol);
529 C10_ASSERT_NEAR(y.imag(), z.imag(), tol);
530 }
531 }
532
533 // Rev trigonometric functions
534
C10_DEFINE_TEST(TestRevTrigonometric,Rev)535 C10_DEFINE_TEST(TestRevTrigonometric, Rev) {
536 // asin(sin(x)) = x
537 // acos(cos(x)) = x
538 // atan(tan(x)) = x
539 {
540 c10::complex<float> x(0.5, 0.6);
541 c10::complex<float> s = std::sin(x);
542 c10::complex<float> ss = std::asin(s);
543 c10::complex<float> c = std::cos(x);
544 c10::complex<float> cc = std::acos(c);
545 c10::complex<float> t = std::tan(x);
546 c10::complex<float> tt = std::atan(t);
547 C10_ASSERT_NEAR(x.real(), ss.real(), tol);
548 C10_ASSERT_NEAR(x.imag(), ss.imag(), tol);
549 C10_ASSERT_NEAR(x.real(), cc.real(), tol);
550 C10_ASSERT_NEAR(x.imag(), cc.imag(), tol);
551 C10_ASSERT_NEAR(x.real(), tt.real(), tol);
552 C10_ASSERT_NEAR(x.imag(), tt.imag(), tol);
553 }
554 {
555 c10::complex<float> x(0.5, 0.6);
556 c10::complex<float> s = ::sin(x);
557 c10::complex<float> ss = ::asin(s);
558 c10::complex<float> c = ::cos(x);
559 c10::complex<float> cc = ::acos(c);
560 c10::complex<float> t = ::tan(x);
561 c10::complex<float> tt = ::atan(t);
562 C10_ASSERT_NEAR(x.real(), ss.real(), tol);
563 C10_ASSERT_NEAR(x.imag(), ss.imag(), tol);
564 C10_ASSERT_NEAR(x.real(), cc.real(), tol);
565 C10_ASSERT_NEAR(x.imag(), cc.imag(), tol);
566 C10_ASSERT_NEAR(x.real(), tt.real(), tol);
567 C10_ASSERT_NEAR(x.imag(), tt.imag(), tol);
568 }
569 {
570 c10::complex<double> x(0.5, 0.6);
571 c10::complex<double> s = std::sin(x);
572 c10::complex<double> ss = std::asin(s);
573 c10::complex<double> c = std::cos(x);
574 c10::complex<double> cc = std::acos(c);
575 c10::complex<double> t = std::tan(x);
576 c10::complex<double> tt = std::atan(t);
577 C10_ASSERT_NEAR(x.real(), ss.real(), tol);
578 C10_ASSERT_NEAR(x.imag(), ss.imag(), tol);
579 C10_ASSERT_NEAR(x.real(), cc.real(), tol);
580 C10_ASSERT_NEAR(x.imag(), cc.imag(), tol);
581 C10_ASSERT_NEAR(x.real(), tt.real(), tol);
582 C10_ASSERT_NEAR(x.imag(), tt.imag(), tol);
583 }
584 {
585 c10::complex<double> x(0.5, 0.6);
586 c10::complex<double> s = ::sin(x);
587 c10::complex<double> ss = ::asin(s);
588 c10::complex<double> c = ::cos(x);
589 c10::complex<double> cc = ::acos(c);
590 c10::complex<double> t = ::tan(x);
591 c10::complex<double> tt = ::atan(t);
592 C10_ASSERT_NEAR(x.real(), ss.real(), tol);
593 C10_ASSERT_NEAR(x.imag(), ss.imag(), tol);
594 C10_ASSERT_NEAR(x.real(), cc.real(), tol);
595 C10_ASSERT_NEAR(x.imag(), cc.imag(), tol);
596 C10_ASSERT_NEAR(x.real(), tt.real(), tol);
597 C10_ASSERT_NEAR(x.imag(), tt.imag(), tol);
598 }
599 }
600
601 // Rev hyperbolic functions
602
C10_DEFINE_TEST(TestRevHyperbolic,Rev)603 C10_DEFINE_TEST(TestRevHyperbolic, Rev) {
604 // asinh(sinh(x)) = x
605 // acosh(cosh(x)) = x
606 // atanh(tanh(x)) = x
607 {
608 c10::complex<float> x(0.5, 0.6);
609 c10::complex<float> s = std::sinh(x);
610 c10::complex<float> ss = std::asinh(s);
611 c10::complex<float> c = std::cosh(x);
612 c10::complex<float> cc = std::acosh(c);
613 c10::complex<float> t = std::tanh(x);
614 c10::complex<float> tt = std::atanh(t);
615 C10_ASSERT_NEAR(x.real(), ss.real(), tol);
616 C10_ASSERT_NEAR(x.imag(), ss.imag(), tol);
617 C10_ASSERT_NEAR(x.real(), cc.real(), tol);
618 C10_ASSERT_NEAR(x.imag(), cc.imag(), tol);
619 C10_ASSERT_NEAR(x.real(), tt.real(), tol);
620 C10_ASSERT_NEAR(x.imag(), tt.imag(), tol);
621 }
622 {
623 c10::complex<float> x(0.5, 0.6);
624 c10::complex<float> s = ::sinh(x);
625 c10::complex<float> ss = ::asinh(s);
626 c10::complex<float> c = ::cosh(x);
627 c10::complex<float> cc = ::acosh(c);
628 c10::complex<float> t = ::tanh(x);
629 c10::complex<float> tt = ::atanh(t);
630 C10_ASSERT_NEAR(x.real(), ss.real(), tol);
631 C10_ASSERT_NEAR(x.imag(), ss.imag(), tol);
632 C10_ASSERT_NEAR(x.real(), cc.real(), tol);
633 C10_ASSERT_NEAR(x.imag(), cc.imag(), tol);
634 C10_ASSERT_NEAR(x.real(), tt.real(), tol);
635 C10_ASSERT_NEAR(x.imag(), tt.imag(), tol);
636 }
637 {
638 c10::complex<double> x(0.5, 0.6);
639 c10::complex<double> s = std::sinh(x);
640 c10::complex<double> ss = std::asinh(s);
641 c10::complex<double> c = std::cosh(x);
642 c10::complex<double> cc = std::acosh(c);
643 c10::complex<double> t = std::tanh(x);
644 c10::complex<double> tt = std::atanh(t);
645 C10_ASSERT_NEAR(x.real(), ss.real(), tol);
646 C10_ASSERT_NEAR(x.imag(), ss.imag(), tol);
647 C10_ASSERT_NEAR(x.real(), cc.real(), tol);
648 C10_ASSERT_NEAR(x.imag(), cc.imag(), tol);
649 C10_ASSERT_NEAR(x.real(), tt.real(), tol);
650 C10_ASSERT_NEAR(x.imag(), tt.imag(), tol);
651 }
652 {
653 c10::complex<double> x(0.5, 0.6);
654 c10::complex<double> s = ::sinh(x);
655 c10::complex<double> ss = ::asinh(s);
656 c10::complex<double> c = ::cosh(x);
657 c10::complex<double> cc = ::acosh(c);
658 c10::complex<double> t = ::tanh(x);
659 c10::complex<double> tt = ::atanh(t);
660 C10_ASSERT_NEAR(x.real(), ss.real(), tol);
661 C10_ASSERT_NEAR(x.imag(), ss.imag(), tol);
662 C10_ASSERT_NEAR(x.real(), cc.real(), tol);
663 C10_ASSERT_NEAR(x.imag(), cc.imag(), tol);
664 C10_ASSERT_NEAR(x.real(), tt.real(), tol);
665 C10_ASSERT_NEAR(x.imag(), tt.imag(), tol);
666 }
667 }
668