test_core_math.odin 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123
  1. // Tests "math.odin" in "core:math".
  2. // Must be run with `-collection:tests=` flag, e.g.
  3. // ./odin run tests/core/math/test_core_math.odin -collection:tests=./tests
  4. package test_core_math
  5. import "core:fmt"
  6. import "core:math"
  7. import "core:testing"
  8. import tc "tests:common"
  9. main :: proc() {
  10. t := testing.T{}
  11. test_classify_f16(&t)
  12. test_classify_f32(&t)
  13. test_classify_f64(&t)
  14. test_trunc_f16(&t)
  15. test_trunc_f32(&t)
  16. test_trunc_f64(&t)
  17. test_nan(&t)
  18. test_acos(&t)
  19. test_acosh(&t)
  20. test_asin(&t)
  21. test_asinh(&t)
  22. test_atan(&t)
  23. test_atanh(&t)
  24. test_atan2(&t)
  25. test_cos(&t)
  26. test_cosh(&t)
  27. test_sin(&t)
  28. test_sinh(&t)
  29. test_sqrt(&t)
  30. test_tan(&t)
  31. test_tanh(&t)
  32. test_large_cos(&t)
  33. test_large_sin(&t)
  34. test_large_tan(&t)
  35. tc.report(&t)
  36. }
  37. @test
  38. test_classify_f16 :: proc(t: ^testing.T) {
  39. r: math.Float_Class
  40. Datum :: struct {
  41. i: int,
  42. v: f16,
  43. e: math.Float_Class,
  44. }
  45. @static data := []Datum{
  46. { 0, 1.2, .Normal },
  47. { 1, 0h0001, .Subnormal },
  48. { 2, 0.0, .Zero },
  49. { 3, -0.0, .Neg_Zero },
  50. { 4, math.SNAN_F16, .NaN },
  51. { 5, math.QNAN_F16, .NaN },
  52. { 6, math.INF_F16, .Inf },
  53. { 7, math.NEG_INF_F16, .Neg_Inf },
  54. }
  55. for d, i in data {
  56. assert(i == d.i)
  57. r = math.classify_f16(d.v)
  58. tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %v != %v", i, #procedure, d.v, r, d.e))
  59. }
  60. /* Check all subnormals (exponent 0, 10-bit significand non-zero) */
  61. for i in u16(1)..<0x400 {
  62. v := transmute(f16)i
  63. r = math.classify_f16(v)
  64. e :: math.Float_Class.Subnormal
  65. tc.expect(t, r == e, fmt.tprintf("i:%d %s(%h) -> %v != %v", i, #procedure, v, r, e))
  66. }
  67. }
  68. @test
  69. test_classify_f32 :: proc(t: ^testing.T) {
  70. r: math.Float_Class
  71. Datum :: struct {
  72. i: int,
  73. v: f32,
  74. e: math.Float_Class,
  75. }
  76. @static data := []Datum{
  77. { 0, 1.2, .Normal },
  78. { 1, 0h0000_0001, .Subnormal },
  79. { 2, 0.0, .Zero },
  80. { 3, -0.0, .Neg_Zero },
  81. { 4, math.SNAN_F32, .NaN },
  82. { 5, math.QNAN_F32, .NaN },
  83. { 6, math.INF_F32, .Inf },
  84. { 7, math.NEG_INF_F32, .Neg_Inf },
  85. }
  86. for d, i in data {
  87. assert(i == d.i)
  88. r = math.classify_f32(d.v)
  89. tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %v != %v", i, #procedure, d.v, r, d.e))
  90. }
  91. }
  92. @test
  93. test_classify_f64 :: proc(t: ^testing.T) {
  94. r: math.Float_Class
  95. Datum :: struct {
  96. i: int,
  97. v: f64,
  98. e: math.Float_Class,
  99. }
  100. @static data := []Datum{
  101. { 0, 1.2, .Normal },
  102. { 1, 0h0000_0000_0000_0001, .Subnormal },
  103. { 2, 0.0, .Zero },
  104. { 3, -0.0, .Neg_Zero },
  105. { 4, math.SNAN_F64, .NaN },
  106. { 5, math.QNAN_F64, .NaN },
  107. { 6, math.INF_F64, .Inf },
  108. { 7, math.NEG_INF_F64, .Neg_Inf },
  109. }
  110. for d, i in data {
  111. assert(i == d.i)
  112. r = math.classify_f64(d.v)
  113. tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %v != %v", i, #procedure, d.v, r, d.e))
  114. }
  115. }
  116. @test
  117. test_trunc_f16 :: proc(t: ^testing.T) {
  118. r, v: f16
  119. Datum :: struct {
  120. i: int,
  121. v: f16,
  122. e: f16,
  123. }
  124. @static data := []Datum{
  125. { 0, 10.5, 10 }, // Issue #1574 fract in linalg/glm is broken
  126. { 1, -10.5, -10 },
  127. { 2, math.F16_MAX, math.F16_MAX },
  128. { 3, -math.F16_MAX, -math.F16_MAX },
  129. { 4, math.F16_MIN, 0.0 },
  130. { 5, -math.F16_MIN, -0.0 },
  131. { 6, 0.0, 0.0 },
  132. { 7, -0.0, -0.0 },
  133. { 8, 1, 1 },
  134. { 9, -1, -1 },
  135. { 10, math.INF_F16, math.INF_F16 },
  136. { 11, math.NEG_INF_F16, math.NEG_INF_F16 },
  137. /* From https://en.wikipedia.org/wiki/Half-precision_floating-point_format */
  138. { 12, 0h3C01, 1 }, // 0x1.004p+0 (smallest > 1)
  139. { 13, -0h3C01, -1 },
  140. { 14, 0h3BFF, 0.0 }, // 0x1.ffcp-1 (largest < 1)
  141. { 15, -0h3BFF, -0.0 },
  142. { 16, 0h0001, 0.0 }, // 0x0.004p-14 (smallest subnormal)
  143. { 17, -0h0001, -0.0 },
  144. { 18, 0h03FF, 0.0 }, // 0x0.ffcp-14 (largest subnormal)
  145. { 19, -0h03FF, -0.0 },
  146. { 20, 0hC809, -8 }, // -0x1.024p+3
  147. { 21, 0h4458, 4 }, // 0x1.16p+2
  148. }
  149. for d, i in data {
  150. assert(i == d.i)
  151. r = math.trunc_f16(d.v)
  152. tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %h != %h", i, #procedure, d.v, r, d.e))
  153. }
  154. v = math.SNAN_F16
  155. r = math.trunc_f16(v)
  156. tc.expect(t, math.is_nan_f16(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r))
  157. v = math.QNAN_F16
  158. r = math.trunc_f16(v)
  159. tc.expect(t, math.is_nan_f16(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r))
  160. }
  161. @test
  162. test_trunc_f32 :: proc(t: ^testing.T) {
  163. r, v: f32
  164. Datum :: struct {
  165. i: int,
  166. v: f32,
  167. e: f32,
  168. }
  169. @static data := []Datum{
  170. { 0, 10.5, 10 }, // Issue #1574 fract in linalg/glm is broken
  171. { 1, -10.5, -10 },
  172. { 2, math.F32_MAX, math.F32_MAX },
  173. { 3, -math.F32_MAX, -math.F32_MAX },
  174. { 4, math.F32_MIN, 0.0 },
  175. { 5, -math.F32_MIN, -0.0 },
  176. { 6, 0.0, 0.0 },
  177. { 7, -0.0, -0.0 },
  178. { 8, 1, 1 },
  179. { 9, -1, -1 },
  180. { 10, math.INF_F32, math.INF_F32 },
  181. { 11, math.NEG_INF_F32, math.NEG_INF_F32 },
  182. /* From https://en.wikipedia.org/wiki/Single-precision_floating-point_format */
  183. { 12, 0h3F80_0001, 1 }, // 0x1.000002p+0 (smallest > 1)
  184. { 13, -0h3F80_0001, -1 },
  185. { 14, 0h3F7F_FFFF, 0.0 }, // 0x1.fffffep-1 (largest < 1)
  186. { 15, -0h3F7F_FFFF, -0.0 },
  187. { 16, 0h0000_0001, 0.0 }, // 0x0.000002p-126 (smallest subnormal)
  188. { 17, -0h0000_0001, -0.0 },
  189. { 18, 0h007F_FFFF, 0.0 }, // 0x0.fffffep-126 (largest subnormal)
  190. { 19, -0h007F_FFFF, -0.0 },
  191. /* From libc-test src/math/sanity/truncf.h */
  192. { 20, 0hC101_11D0, -8 }, // -0x1.0223ap+3
  193. { 21, 0h408B_0C34, 4 }, // 0x1.161868p+2
  194. { 22, 0hC106_1A5A, -8 }, // -0x1.0c34b4p+3
  195. { 23, 0hC0D1_0378, -6 }, // -0x1.a206fp+2
  196. { 24, 0h4114_45DE, 9 }, // 0x1.288bbcp+3
  197. { 25, 0h3F29_77E8, 0.0 }, // 0x1.52efdp-1
  198. { 26, 0hBED0_2E64, -0.0 }, // -0x1.a05cc8p-2
  199. { 27, 0h3F0F_CF7D, 0.0 }, // 0x1.1f9efap-1
  200. { 28, 0h3F46_2ED8, 0.0 }, // 0x1.8c5dbp-1
  201. { 29, 0hBF2D_C375, -0.0 }, // -0x1.5b86eap-1
  202. }
  203. for d, i in data {
  204. assert(i == d.i)
  205. r = math.trunc_f32(d.v)
  206. tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %h != %h", i, #procedure, d.v, r, d.e))
  207. }
  208. v = math.SNAN_F32
  209. r = math.trunc_f32(v)
  210. tc.expect(t, math.is_nan_f32(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r))
  211. v = math.QNAN_F32
  212. r = math.trunc_f32(v)
  213. tc.expect(t, math.is_nan_f32(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r))
  214. }
  215. @test
  216. test_trunc_f64 :: proc(t: ^testing.T) {
  217. r, v: f64
  218. Datum :: struct {
  219. i: int,
  220. v: f64,
  221. e: f64,
  222. }
  223. data := []Datum{
  224. { 0, 10.5, 10 }, // Issue #1574 fract in linalg/glm is broken
  225. { 1, -10.5, -10 },
  226. { 2, math.F64_MAX, math.F64_MAX },
  227. { 3, -math.F64_MAX, -math.F64_MAX },
  228. { 4, math.F64_MIN, 0.0 },
  229. { 5, -math.F64_MIN, -0.0 },
  230. { 6, 0.0, 0.0 },
  231. { 7, -0.0, -0.0 },
  232. { 8, 1, 1 },
  233. { 9, -1, -1 },
  234. { 10, math.INF_F64, math.INF_F64 },
  235. { 11, math.NEG_INF_F64, math.NEG_INF_F64 },
  236. /* From https://en.wikipedia.org/wiki/Double-precision_floating-point_format */
  237. { 12, 0h3FF0_0000_0000_0001, 1 }, // 0x1.0000000000001p+0 (smallest > 1)
  238. { 13, -0h3FF0_0000_0000_0001, -1 },
  239. { 14, 0h3FEF_FFFF_FFFF_FFFF, 0.0 }, // 0x1.fffffffffffffp-1 (largest < 1)
  240. { 15, -0h3FEF_FFFF_FFFF_FFFF, -0.0 },
  241. { 16, 0h0000_0000_0000_0001, 0.0 }, // 0x0.0000000000001p-1022 (smallest subnormal)
  242. { 17, -0h0000_0000_0000_0001, -0.0 },
  243. { 18, 0h000F_FFFF_FFFF_FFFF, 0.0 }, // 0x0.fffffffffffffp-1022 (largest subnormal)
  244. { 19, -0h000F_FFFF_FFFF_FFFF, -0.0 },
  245. /* From libc-test src/math/sanity/trunc.h */
  246. { 20, 0hC020_2239_F3C6_A8F1, -8 }, // -0x1.02239f3c6a8f1p+3
  247. { 21, 0h4011_6186_8E18_BC67, 4 }, // 0x1.161868e18bc67p+2
  248. { 22, 0hC020_C34B_3E01_E6E7, -8 }, // -0x1.0c34b3e01e6e7p+3
  249. { 23, 0hC01A_206F_0A19_DCC4, -6 }, // -0x1.a206f0a19dcc4p+2
  250. { 24, 0h4022_88BB_B0D6_A1E6, 9 }, // 0x1.288bbb0d6a1e6p+3
  251. { 25, 0h3FE5_2EFD_0CD8_0497, 0.0 }, // 0x1.52efd0cd80497p-1
  252. { 26, 0hBFDA_05CC_7544_81D1, -0.0 }, // -0x1.a05cc754481d1p-2
  253. { 27, 0h3FE1_F9EF_9347_45CB, 0.0 }, // 0x1.1f9ef934745cbp-1
  254. { 28, 0h3FE8_C5DB_097F_7442, 0.0 }, // 0x1.8c5db097f7442p-1
  255. { 29, 0hBFE5_B86E_A811_8A0E, -0.0 }, // -0x1.5b86ea8118a0ep-1
  256. }
  257. for d, i in data {
  258. assert(i == d.i)
  259. r = math.trunc_f64(d.v)
  260. tc.expect(t, r == d.e, fmt.tprintf("i:%d %s(%h) -> %h != %h", i, #procedure, d.v, r, d.e))
  261. }
  262. v = math.SNAN_F64
  263. r = math.trunc_f64(v)
  264. tc.expect(t, math.is_nan_f64(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r))
  265. v = math.QNAN_F64
  266. r = math.trunc_f64(v)
  267. tc.expect(t, math.is_nan_f64(r), fmt.tprintf("%s(%f) -> %f != NaN", #procedure, v, r))
  268. }
  269. vf := []f64{
  270. 4.9790119248836735e+00,
  271. 7.7388724745781045e+00,
  272. -2.7688005719200159e-01,
  273. -5.0106036182710749e+00,
  274. 9.6362937071984173e+00,
  275. 2.9263772392439646e+00,
  276. 5.2290834314593066e+00,
  277. 2.7279399104360102e+00,
  278. 1.8253080916808550e+00,
  279. -8.6859247685756013e+00,
  280. }
  281. // The expected results below were computed by the high precision calculators at https://keisan.casio.com/.
  282. acos := []f64{
  283. 1.0496193546107222142571536e+00,
  284. 6.8584012813664425171660692e-01,
  285. 1.5984878714577160325521819e+00,
  286. 2.0956199361475859327461799e+00,
  287. 2.7053008467824138592616927e-01,
  288. 1.2738121680361776018155625e+00,
  289. 1.0205369421140629186287407e+00,
  290. 1.2945003481781246062157835e+00,
  291. 1.3872364345374451433846657e+00,
  292. 2.6231510803970463967294145e+00,
  293. }
  294. acosh := []f64{
  295. 2.4743347004159012494457618e+00,
  296. 2.8576385344292769649802701e+00,
  297. 7.2796961502981066190593175e-01,
  298. 2.4796794418831451156471977e+00,
  299. 3.0552020742306061857212962e+00,
  300. 2.044238592688586588942468e+00,
  301. 2.5158701513104513595766636e+00,
  302. 1.99050839282411638174299e+00,
  303. 1.6988625798424034227205445e+00,
  304. 2.9611454842470387925531875e+00,
  305. }
  306. asin := []f64{
  307. 5.2117697218417440497416805e-01,
  308. 8.8495619865825236751471477e-01,
  309. -02.769154466281941332086016e-02,
  310. -5.2482360935268931351485822e-01,
  311. 1.3002662421166552333051524e+00,
  312. 2.9698415875871901741575922e-01,
  313. 5.5025938468083370060258102e-01,
  314. 2.7629597861677201301553823e-01,
  315. 1.83559892257451475846656e-01,
  316. -1.0523547536021497774980928e+00,
  317. }
  318. asinh := []f64{
  319. 2.3083139124923523427628243e+00,
  320. 2.743551594301593620039021e+00,
  321. -2.7345908534880091229413487e-01,
  322. -2.3145157644718338650499085e+00,
  323. 2.9613652154015058521951083e+00,
  324. 1.7949041616585821933067568e+00,
  325. 2.3564032905983506405561554e+00,
  326. 1.7287118790768438878045346e+00,
  327. 1.3626658083714826013073193e+00,
  328. -2.8581483626513914445234004e+00,
  329. }
  330. atan := []f64{
  331. 1.372590262129621651920085e+00,
  332. 1.442290609645298083020664e+00,
  333. -2.7011324359471758245192595e-01,
  334. -1.3738077684543379452781531e+00,
  335. 1.4673921193587666049154681e+00,
  336. 1.2415173565870168649117764e+00,
  337. 1.3818396865615168979966498e+00,
  338. 1.2194305844639670701091426e+00,
  339. 1.0696031952318783760193244e+00,
  340. -1.4561721938838084990898679e+00,
  341. }
  342. atanh := []f64{
  343. 5.4651163712251938116878204e-01,
  344. 1.0299474112843111224914709e+00,
  345. -2.7695084420740135145234906e-02,
  346. -5.5072096119207195480202529e-01,
  347. 1.9943940993171843235906642e+00,
  348. 3.01448604578089708203017e-01,
  349. 5.8033427206942188834370595e-01,
  350. 2.7987997499441511013958297e-01,
  351. 1.8459947964298794318714228e-01,
  352. -1.3273186910532645867272502e+00,
  353. }
  354. atan2 := []f64{
  355. 1.1088291730037004444527075e+00,
  356. 9.1218183188715804018797795e-01,
  357. 1.5984772603216203736068915e+00,
  358. 2.0352918654092086637227327e+00,
  359. 8.0391819139044720267356014e-01,
  360. 1.2861075249894661588866752e+00,
  361. 1.0889904479131695712182587e+00,
  362. 1.3044821793397925293797357e+00,
  363. 1.3902530903455392306872261e+00,
  364. 2.2859857424479142655411058e+00,
  365. }
  366. cos := []f64{
  367. 2.634752140995199110787593e-01,
  368. 1.148551260848219865642039e-01,
  369. 9.6191297325640768154550453e-01,
  370. 2.938141150061714816890637e-01,
  371. -9.777138189897924126294461e-01,
  372. -9.7693041344303219127199518e-01,
  373. 4.940088096948647263961162e-01,
  374. -9.1565869021018925545016502e-01,
  375. -2.517729313893103197176091e-01,
  376. -7.39241351595676573201918e-01,
  377. }
  378. // Results for 1e5 * Pi + vf[i]
  379. cosLarge := []f64{
  380. 2.634752141185559426744e-01,
  381. 1.14855126055543100712e-01,
  382. 9.61912973266488928113e-01,
  383. 2.9381411499556122552e-01,
  384. -9.777138189880161924641e-01,
  385. -9.76930413445147608049e-01,
  386. 4.940088097314976789841e-01,
  387. -9.15658690217517835002e-01,
  388. -2.51772931436786954751e-01,
  389. -7.3924135157173099849e-01,
  390. }
  391. cosh := []f64{
  392. 7.2668796942212842775517446e+01,
  393. 1.1479413465659254502011135e+03,
  394. 1.0385767908766418550935495e+00,
  395. 7.5000957789658051428857788e+01,
  396. 7.655246669605357888468613e+03,
  397. 9.3567491758321272072888257e+00,
  398. 9.331351599270605471131735e+01,
  399. 7.6833430994624643209296404e+00,
  400. 3.1829371625150718153881164e+00,
  401. 2.9595059261916188501640911e+03,
  402. }
  403. sin := []f64{
  404. -9.6466616586009283766724726e-01,
  405. 9.9338225271646545763467022e-01,
  406. -2.7335587039794393342449301e-01,
  407. 9.5586257685042792878173752e-01,
  408. -2.099421066779969164496634e-01,
  409. 2.135578780799860532750616e-01,
  410. -8.694568971167362743327708e-01,
  411. 4.019566681155577786649878e-01,
  412. 9.6778633541687993721617774e-01,
  413. -6.734405869050344734943028e-01,
  414. }
  415. // Results for 1e5 * Pi + vf[i]
  416. sinLarge := []f64{
  417. -9.646661658548936063912e-01,
  418. 9.933822527198506903752e-01,
  419. -2.7335587036246899796e-01,
  420. 9.55862576853689321268e-01,
  421. -2.099421066862688873691e-01,
  422. 2.13557878070308981163e-01,
  423. -8.694568970959221300497e-01,
  424. 4.01956668098863248917e-01,
  425. 9.67786335404528727927e-01,
  426. -6.7344058693131973066e-01,
  427. }
  428. sinh := []f64{
  429. 7.2661916084208532301448439e+01,
  430. 1.1479409110035194500526446e+03,
  431. -2.8043136512812518927312641e-01,
  432. -7.499429091181587232835164e+01,
  433. 7.6552466042906758523925934e+03,
  434. 9.3031583421672014313789064e+00,
  435. 9.330815755828109072810322e+01,
  436. 7.6179893137269146407361477e+00,
  437. 3.021769180549615819524392e+00,
  438. -2.95950575724449499189888e+03,
  439. }
  440. sqrt := []f64{
  441. 2.2313699659365484748756904e+00,
  442. 2.7818829009464263511285458e+00,
  443. 5.2619393496314796848143251e-01,
  444. 2.2384377628763938724244104e+00,
  445. 3.1042380236055381099288487e+00,
  446. 1.7106657298385224403917771e+00,
  447. 2.286718922705479046148059e+00,
  448. 1.6516476350711159636222979e+00,
  449. 1.3510396336454586262419247e+00,
  450. 2.9471892997524949215723329e+00,
  451. }
  452. tan := []f64{
  453. -3.661316565040227801781974e+00,
  454. 8.64900232648597589369854e+00,
  455. -2.8417941955033612725238097e-01,
  456. 3.253290185974728640827156e+00,
  457. 2.147275640380293804770778e-01,
  458. -2.18600910711067004921551e-01,
  459. -1.760002817872367935518928e+00,
  460. -4.389808914752818126249079e-01,
  461. -3.843885560201130679995041e+00,
  462. 9.10988793377685105753416e-01,
  463. }
  464. // Results for 1e5 * Pi + vf[i]
  465. tanLarge := []f64{
  466. -3.66131656475596512705e+00,
  467. 8.6490023287202547927e+00,
  468. -2.841794195104782406e-01,
  469. 3.2532901861033120983e+00,
  470. 2.14727564046880001365e-01,
  471. -2.18600910700688062874e-01,
  472. -1.760002817699722747043e+00,
  473. -4.38980891453536115952e-01,
  474. -3.84388555942723509071e+00,
  475. 9.1098879344275101051e-01,
  476. }
  477. tanh := []f64{
  478. 9.9990531206936338549262119e-01,
  479. 9.9999962057085294197613294e-01,
  480. -2.7001505097318677233756845e-01,
  481. -9.9991110943061718603541401e-01,
  482. 9.9999999146798465745022007e-01,
  483. 9.9427249436125236705001048e-01,
  484. 9.9994257600983138572705076e-01,
  485. 9.9149409509772875982054701e-01,
  486. 9.4936501296239685514466577e-01,
  487. -9.9999994291374030946055701e-01,
  488. }
  489. NaN :: 0h7fff_ffff_ffff_ffff
  490. Pi :: 0h4009_21fb_5444_2d18
  491. // arguments and expected results for special cases
  492. vfacos_sc := []f64{
  493. -Pi,
  494. 1,
  495. Pi,
  496. NaN,
  497. }
  498. acos_sc := []f64{
  499. NaN,
  500. 0,
  501. NaN,
  502. NaN,
  503. }
  504. vfacosh_sc := []f64{
  505. math.inf_f64(-1),
  506. 0.5,
  507. 1,
  508. math.inf_f64(1),
  509. NaN,
  510. }
  511. acosh_sc := []f64{
  512. NaN,
  513. NaN,
  514. 0,
  515. math.inf_f64(1),
  516. NaN,
  517. }
  518. vfasin_sc := []f64{
  519. -Pi,
  520. math.copy_sign_f64(0, -1),
  521. 0,
  522. Pi,
  523. NaN,
  524. }
  525. asin_sc := []f64{
  526. NaN,
  527. math.copy_sign_f64(0, -1),
  528. 0,
  529. NaN,
  530. NaN,
  531. }
  532. vfasinh_sc := []f64{
  533. math.inf_f64(-1),
  534. math.copy_sign_f64(0, -1),
  535. 0,
  536. math.inf_f64(1),
  537. NaN,
  538. }
  539. asinh_sc := []f64{
  540. math.inf_f64(-1),
  541. math.copy_sign_f64(0, -1),
  542. 0,
  543. math.inf_f64(1),
  544. NaN,
  545. }
  546. vfatan_sc := []f64{
  547. math.inf_f64(-1),
  548. math.copy_sign_f64(0, -1),
  549. 0,
  550. math.inf_f64(1),
  551. NaN,
  552. }
  553. atan_sc := []f64{
  554. -Pi / 2,
  555. math.copy_sign_f64(0, -1),
  556. 0,
  557. Pi / 2,
  558. NaN,
  559. }
  560. vfatanh_sc := []f64{
  561. math.inf_f64(-1),
  562. -Pi,
  563. -1,
  564. math.copy_sign_f64(0, -1),
  565. 0,
  566. 1,
  567. Pi,
  568. math.inf_f64(1),
  569. NaN,
  570. }
  571. atanh_sc := []f64{
  572. NaN,
  573. NaN,
  574. math.inf_f64(-1),
  575. math.copy_sign_f64(0, -1),
  576. 0,
  577. math.inf_f64(1),
  578. NaN,
  579. NaN,
  580. NaN,
  581. }
  582. vfatan2_sc := [][2]f64{
  583. {math.inf_f64(-1), math.inf_f64(-1)},
  584. {math.inf_f64(-1), -Pi},
  585. {math.inf_f64(-1), 0},
  586. {math.inf_f64(-1), +Pi},
  587. {math.inf_f64(-1), math.inf_f64(1)},
  588. {math.inf_f64(-1), NaN},
  589. {-Pi, math.inf_f64(-1)},
  590. {-Pi, 0},
  591. {-Pi, math.inf_f64(1)},
  592. {-Pi, NaN},
  593. {math.copy_sign_f64(0, -1), math.inf_f64(-1)},
  594. {math.copy_sign_f64(0, -1), -Pi},
  595. {math.copy_sign_f64(0, -1), math.copy_sign_f64(0, -1)},
  596. {math.copy_sign_f64(0, -1), 0},
  597. {math.copy_sign_f64(0, -1), +Pi},
  598. {math.copy_sign_f64(0, -1), math.inf_f64(1)},
  599. {math.copy_sign_f64(0, -1), NaN},
  600. {0, math.inf_f64(-1)},
  601. {0, -Pi},
  602. {0, math.copy_sign_f64(0, -1)},
  603. {0, 0},
  604. {0, +Pi},
  605. {0, math.inf_f64(1)},
  606. {0, NaN},
  607. {+Pi, math.inf_f64(-1)},
  608. {+Pi, 0},
  609. {+Pi, math.inf_f64(1)},
  610. {1.0, math.inf_f64(1)},
  611. {-1.0, math.inf_f64(1)},
  612. {+Pi, NaN},
  613. {math.inf_f64(1), math.inf_f64(-1)},
  614. {math.inf_f64(1), -Pi},
  615. {math.inf_f64(1), 0},
  616. {math.inf_f64(1), +Pi},
  617. {math.inf_f64(1), math.inf_f64(1)},
  618. {math.inf_f64(1), NaN},
  619. {NaN, NaN},
  620. }
  621. atan2_sc := []f64{
  622. -3 * Pi / 4, // atan2(-Inf, -Inf)
  623. -Pi / 2, // atan2(-Inf, -Pi)
  624. -Pi / 2, // atan2(-Inf, +0)
  625. -Pi / 2, // atan2(-Inf, +Pi)
  626. -Pi / 4, // atan2(-Inf, +Inf)
  627. NaN, // atan2(-Inf, NaN)
  628. -Pi, // atan2(-Pi, -Inf)
  629. -Pi / 2, // atan2(-Pi, +0)
  630. math.copy_sign_f64(0, -1), // atan2(-Pi, Inf)
  631. NaN, // atan2(-Pi, NaN)
  632. -Pi, // atan2(-0, -Inf)
  633. -Pi, // atan2(-0, -Pi)
  634. -Pi, // atan2(-0, -0)
  635. math.copy_sign_f64(0, -1), // atan2(-0, +0)
  636. math.copy_sign_f64(0, -1), // atan2(-0, +Pi)
  637. math.copy_sign_f64(0, -1), // atan2(-0, +Inf)
  638. NaN, // atan2(-0, NaN)
  639. Pi, // atan2(+0, -Inf)
  640. Pi, // atan2(+0, -Pi)
  641. Pi, // atan2(+0, -0)
  642. 0, // atan2(+0, +0)
  643. 0, // atan2(+0, +Pi)
  644. 0, // atan2(+0, +Inf)
  645. NaN, // atan2(+0, NaN)
  646. Pi, // atan2(+Pi, -Inf)
  647. Pi / 2, // atan2(+Pi, +0)
  648. 0, // atan2(+Pi, +Inf)
  649. 0, // atan2(+1, +Inf)
  650. math.copy_sign_f64(0, -1), // atan2(-1, +Inf)
  651. NaN, // atan2(+Pi, NaN)
  652. 3 * Pi / 4, // atan2(+Inf, -Inf)
  653. Pi / 2, // atan2(+Inf, -Pi)
  654. Pi / 2, // atan2(+Inf, +0)
  655. Pi / 2, // atan2(+Inf, +Pi)
  656. Pi / 4, // atan2(+Inf, +Inf)
  657. NaN, // atan2(+Inf, NaN)
  658. NaN, // atan2(NaN, NaN)
  659. }
  660. vfcbrt_sc := []f64{
  661. math.inf_f64(-1),
  662. math.copy_sign_f64(0, -1),
  663. 0,
  664. math.inf_f64(1),
  665. NaN,
  666. }
  667. cbrt_sc := []f64{
  668. math.inf_f64(-1),
  669. math.copy_sign_f64(0, -1),
  670. 0,
  671. math.inf_f64(1),
  672. NaN,
  673. }
  674. vfceil_sc := []f64{
  675. math.inf_f64(-1),
  676. math.copy_sign_f64(0, -1),
  677. 0,
  678. math.inf_f64(1),
  679. NaN,
  680. }
  681. ceil_sc := []f64{
  682. math.inf_f64(-1),
  683. math.copy_sign_f64(0, -1),
  684. 0,
  685. math.inf_f64(1),
  686. NaN,
  687. }
  688. vfcopysign_sc := []f64{
  689. math.inf_f64(-1),
  690. math.inf_f64(1),
  691. NaN,
  692. }
  693. copysign_sc := []f64{
  694. math.inf_f64(-1),
  695. math.inf_f64(-1),
  696. NaN,
  697. }
  698. vfcos_sc := []f64{
  699. math.inf_f64(-1),
  700. math.inf_f64(1),
  701. NaN,
  702. }
  703. cos_sc := []f64{
  704. NaN,
  705. NaN,
  706. NaN,
  707. }
  708. vfcosh_sc := []f64{
  709. math.inf_f64(-1),
  710. math.copy_sign_f64(0, -1),
  711. 0,
  712. math.inf_f64(1),
  713. NaN,
  714. }
  715. cosh_sc := []f64{
  716. math.inf_f64(1),
  717. 1,
  718. 1,
  719. math.inf_f64(1),
  720. NaN,
  721. }
  722. vfsin_sc := []f64{
  723. math.inf_f64(-1),
  724. math.copy_sign_f64(0, -1),
  725. 0,
  726. math.inf_f64(1),
  727. NaN,
  728. }
  729. sin_sc := []f64{
  730. NaN,
  731. math.copy_sign_f64(0, -1),
  732. 0,
  733. NaN,
  734. NaN,
  735. }
  736. vfsinh_sc := []f64{
  737. math.inf_f64(-1),
  738. math.copy_sign_f64(0, -1),
  739. 0,
  740. math.inf_f64(1),
  741. NaN,
  742. }
  743. sinh_sc := []f64{
  744. math.inf_f64(-1),
  745. math.copy_sign_f64(0, -1),
  746. 0,
  747. math.inf_f64(1),
  748. NaN,
  749. }
  750. vftanh_sc := []f64{
  751. math.inf_f64(-1),
  752. math.copy_sign_f64(0, -1),
  753. 0,
  754. math.inf_f64(1),
  755. NaN,
  756. }
  757. tanh_sc := []f64{
  758. -1,
  759. math.copy_sign_f64(0, -1),
  760. 0,
  761. 1,
  762. NaN,
  763. }
  764. tolerance :: proc(a, b, e: f64) -> bool {
  765. // Multiplying by e here can underflow denormal values to zero.
  766. // Check a==b so that at least if a and b are small and identical
  767. // we say they match.
  768. if a == b {
  769. return true
  770. }
  771. e := e
  772. d := a - b
  773. if d < 0 {
  774. d = -d
  775. }
  776. // note: b is correct (expected) value, a is actual value.
  777. // make error tolerance a fraction of b, not a.
  778. if b != 0 {
  779. e = e * b
  780. if e < 0 {
  781. e = -e
  782. }
  783. }
  784. return d < e
  785. }
  786. close :: proc(t: ^testing.T, a, b: f64, loc := #caller_location) -> bool {
  787. ok := tolerance(a, b, 1e-9)
  788. // tc.expect(t, ok, fmt.tprintf("%.15g is not close to %.15g", a, b), loc)
  789. return ok
  790. }
  791. veryclose :: proc(t: ^testing.T, a, b: f64, loc := #caller_location) -> bool {
  792. ok := tolerance(a, b, 4e-14)
  793. // tc.expect(t, ok, fmt.tprintf("%.15g is not veryclose to %.15g", a, b), loc)
  794. return ok
  795. }
  796. soclose :: proc(t: ^testing.T, a, b, e: f64, loc := #caller_location) -> bool {
  797. ok := tolerance(a, b, e)
  798. // tc.expect(t, ok, fmt.tprintf("%.15g is not soclose to %.15g", a, b), loc)
  799. return ok
  800. }
  801. alike :: proc(t: ^testing.T, a, b: f64, loc := #caller_location) -> bool {
  802. ok := false
  803. switch {
  804. case math.is_nan(a) && math.is_nan(b):
  805. ok = true
  806. case a == b:
  807. ok = math.signbit(a) == math.signbit(b)
  808. }
  809. // tc.expect(t, ok, fmt.tprintf("%.15g is not alike to %.15g", a, b), loc)
  810. return ok
  811. }
  812. @test
  813. test_nan :: proc(t: ^testing.T) {
  814. float64 := NaN
  815. if float64 == float64 {
  816. tc.errorf(t, "NaN returns %.15g, expected NaN", float64)
  817. }
  818. float32 := f32(float64)
  819. if float32 == float32 {
  820. tc.errorf(t, "float32(NaN) is %.15g, expected NaN", float32)
  821. }
  822. }
  823. @test
  824. test_acos :: proc(t: ^testing.T) {
  825. for _, i in vf {
  826. a := vf[i] / 10
  827. if f := math.acos(a); !close(t, acos[i], f) {
  828. tc.errorf(t, "math.acos(%.15g) = %.15g, want %.15g", a, f, acos[i])
  829. }
  830. }
  831. for _, i in vfacos_sc {
  832. if f := math.acos(vfacos_sc[i]); !alike(t, acos_sc[i], f) {
  833. tc.errorf(t, "math.acos(%.15g) = %.15g, want %.15g", vfacos_sc[i], f, acos_sc[i])
  834. }
  835. }
  836. }
  837. @test
  838. test_acosh :: proc(t: ^testing.T) {
  839. for _, i in vf {
  840. a := 1 + abs(vf[i])
  841. if f := math.acosh(a); !veryclose(t, acosh[i], f) {
  842. tc.errorf(t, "math.acosh(%.15g) = %.15g, want %.15g", a, f, acosh[i])
  843. }
  844. }
  845. for _, i in vfacosh_sc {
  846. if f := math.acosh(vfacosh_sc[i]); !alike(t, acosh_sc[i], f) {
  847. tc.errorf(t, "math.acosh(%.15g) = %.15g, want %.15g", vfacosh_sc[i], f, acosh_sc[i])
  848. }
  849. }
  850. }
  851. @test
  852. test_asin :: proc(t: ^testing.T) {
  853. for _, i in vf {
  854. a := vf[i] / 10
  855. if f := math.asin(a); !veryclose(t, asin[i], f) {
  856. tc.errorf(t, "math.asin(%.15g) = %.15g, want %.15g", a, f, asin[i])
  857. }
  858. }
  859. for _, i in vfasin_sc {
  860. if f := math.asin(vfasin_sc[i]); !alike(t, asin_sc[i], f) {
  861. tc.errorf(t, "math.asin(%.15g) = %.15g, want %.15g", vfasin_sc[i], f, asin_sc[i])
  862. }
  863. }
  864. }
  865. @test
  866. test_asinh :: proc(t: ^testing.T) {
  867. for _, i in vf {
  868. if f := math.asinh(vf[i]); !veryclose(t, asinh[i], f) {
  869. tc.errorf(t, "math.asinh(%.15g) = %.15g, want %.15g", vf[i], f, asinh[i])
  870. }
  871. }
  872. for _, i in vfasinh_sc {
  873. if f := math.asinh(vfasinh_sc[i]); !alike(t, asinh_sc[i], f) {
  874. tc.errorf(t, "math.asinh(%.15g) = %.15g, want %.15g", vfasinh_sc[i], f, asinh_sc[i])
  875. }
  876. }
  877. }
  878. @test
  879. test_atan :: proc(t: ^testing.T) {
  880. for _, i in vf {
  881. if f := math.atan(vf[i]); !veryclose(t, atan[i], f) {
  882. tc.errorf(t, "math.atan(%.15g) = %.15g, want %.15g", vf[i], f, atan[i])
  883. }
  884. }
  885. for _, i in vfatan_sc {
  886. if f := math.atan(vfatan_sc[i]); !alike(t, atan_sc[i], f) {
  887. tc.errorf(t, "math.atan(%.15g) = %.15g, want %.15g", vfatan_sc[i], f, atan_sc[i])
  888. }
  889. }
  890. }
  891. @test
  892. test_atanh :: proc(t: ^testing.T) {
  893. for _, i in vf {
  894. a := vf[i] / 10
  895. if f := math.atanh(a); !veryclose(t, atanh[i], f) {
  896. tc.errorf(t, "math.atanh(%.15g) = %.15g, want %.15g", a, f, atanh[i])
  897. }
  898. }
  899. for _, i in vfatanh_sc {
  900. if f := math.atanh(vfatanh_sc[i]); !alike(t, atanh_sc[i], f) {
  901. tc.errorf(t, "math.atanh(%.15g) = %.15g, want %.15g", vfatanh_sc[i], f, atanh_sc[i])
  902. }
  903. }
  904. }
  905. @test
  906. test_atan2 :: proc(t: ^testing.T) {
  907. for _, i in vf {
  908. if f := math.atan2(10, vf[i]); !veryclose(t, atan2[i], f) {
  909. tc.errorf(t, "math.atan2(10, %.15g) = %.15g, want %.15g", vf[i], f, atan2[i])
  910. }
  911. }
  912. for _, i in vfatan2_sc {
  913. if f := math.atan2(vfatan2_sc[i][0], vfatan2_sc[i][1]); !alike(t, atan2_sc[i], f) {
  914. tc.errorf(t, "math.atan2(%.15g, %.15g) = %.15g, want %.15g", vfatan2_sc[i][0], vfatan2_sc[i][1], f, atan2_sc[i])
  915. }
  916. }
  917. }
  918. @test
  919. test_cos :: proc(t: ^testing.T) {
  920. for _, i in vf {
  921. if f := math.cos(vf[i]); !veryclose(t, cos[i], f) {
  922. tc.errorf(t, "math.cos(%.15g) = %.15g, want %.15g", vf[i], f, cos[i])
  923. }
  924. }
  925. for _, i in vfcos_sc {
  926. if f := math.cos(vfcos_sc[i]); !alike(t, cos_sc[i], f) {
  927. tc.errorf(t, "math.cos(%.15g) = %.15g, want %.15g", vfcos_sc[i], f, cos_sc[i])
  928. }
  929. }
  930. }
  931. @test
  932. test_cosh :: proc(t: ^testing.T) {
  933. for _, i in vf {
  934. if f := math.cosh(vf[i]); !close(t, cosh[i], f) {
  935. tc.errorf(t, "math.cosh(%.15g) = %.15g, want %.15g", vf[i], f, cosh[i])
  936. }
  937. }
  938. for _, i in vfcosh_sc {
  939. if f := math.cosh(vfcosh_sc[i]); !alike(t, cosh_sc[i], f) {
  940. tc.errorf(t, "math.cosh(%.15g) = %.15g, want %.15g", vfcosh_sc[i], f, cosh_sc[i])
  941. }
  942. }
  943. }
  944. @test
  945. test_sin :: proc(t: ^testing.T) {
  946. for _, i in vf {
  947. if f := math.sin(vf[i]); !veryclose(t, sin[i], f) {
  948. tc.errorf(t, "math.sin(%.15g) = %.15g, want %.15g", vf[i], f, sin[i])
  949. }
  950. }
  951. for _, i in vfsin_sc {
  952. if f := math.sin(vfsin_sc[i]); !alike(t, sin_sc[i], f) {
  953. tc.errorf(t, "math.sin(%.15g) = %.15g, want %.15g", vfsin_sc[i], f, sin_sc[i])
  954. }
  955. }
  956. }
  957. @test
  958. test_sinh :: proc(t: ^testing.T) {
  959. for _, i in vf {
  960. if f := math.sinh(vf[i]); !close(t, sinh[i], f) {
  961. tc.errorf(t, "math.sinh(%.15g) = %.15g, want %.15g", vf[i], f, sinh[i])
  962. }
  963. }
  964. for _, i in vfsinh_sc {
  965. if f := math.sinh(vfsinh_sc[i]); !alike(t, sinh_sc[i], f) {
  966. tc.errorf(t, "math.sinh(%.15g) = %.15g, want %.15g", vfsinh_sc[i], f, sinh_sc[i])
  967. }
  968. }
  969. }
  970. @test
  971. test_sqrt :: proc(t: ^testing.T) {
  972. for _, i in vf {
  973. a := abs(vf[i])
  974. if f := math.sqrt(a); !veryclose(t, sqrt[i], f) {
  975. tc.errorf(t, "math.sqrt(%.15g) = %.15g, want %.15g", a, f, sqrt[i])
  976. }
  977. }
  978. }
  979. @test
  980. test_tan :: proc(t: ^testing.T) {
  981. for _, i in vf {
  982. if f := math.tan(vf[i]); !veryclose(t, tan[i], f) {
  983. tc.errorf(t, "math.tan(%.15g) = %.15g, want %.15g", vf[i], f, tan[i])
  984. }
  985. }
  986. // same special cases as Sin
  987. for _, i in vfsin_sc {
  988. if f := math.tan(vfsin_sc[i]); !alike(t, sin_sc[i], f) {
  989. tc.errorf(t, "math.tan(%.15g) = %.15g, want %.15g", vfsin_sc[i], f, sin_sc[i])
  990. }
  991. }
  992. }
  993. @test
  994. test_tanh :: proc(t: ^testing.T) {
  995. for _, i in vf {
  996. if f := math.tanh(vf[i]); !veryclose(t, tanh[i], f) {
  997. tc.errorf(t, "math.tanh(%.15g) = %.15g, want %.15g", vf[i], f, tanh[i])
  998. }
  999. }
  1000. for _, i in vftanh_sc {
  1001. if f := math.tanh(vftanh_sc[i]); !alike(t, tanh_sc[i], f) {
  1002. tc.errorf(t, "math.tanh(%.15g) = %.15g, want %.15g", vftanh_sc[i], f, tanh_sc[i])
  1003. }
  1004. }
  1005. }
  1006. @test
  1007. test_large_cos :: proc(t: ^testing.T) {
  1008. large := f64(1e5 * Pi)
  1009. for _, i in vf {
  1010. f1 := cosLarge[i]
  1011. f2 := math.cos(vf[i] + large)
  1012. if !close(t, f1, f2) {
  1013. tc.errorf(t, "math.cos(%.15g) = %.15g, want %.15g", vf[i]+large, f2, f1)
  1014. }
  1015. }
  1016. }
  1017. @test
  1018. test_large_sin :: proc(t: ^testing.T) {
  1019. large := f64(1e5 * Pi)
  1020. for _, i in vf {
  1021. f1 := sinLarge[i]
  1022. f2 := math.sin(vf[i] + large)
  1023. if !close(t, f1, f2) {
  1024. tc.errorf(t, "math.sin(%.15g) = %.15g, want %.15g", vf[i]+large, f2, f1)
  1025. }
  1026. }
  1027. }
  1028. @test
  1029. test_large_tan :: proc(t: ^testing.T) {
  1030. large := f64(1e5 * Pi)
  1031. for _, i in vf {
  1032. f1 := tanLarge[i]
  1033. f2 := math.tan(vf[i] + large)
  1034. if !close(t, f1, f2) {
  1035. tc.errorf(t, "math.tan(%.15g) = %.15g, want %.15g", vf[i]+large, f2, f1)
  1036. }
  1037. }
  1038. }