xref: /aosp_15_r20/external/pytorch/c10/test/util/complex_math_test_common.h (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
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