test_core_math.odin 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455
  1. // Tests "math.odin" in "core:math".
  2. package test_core_math
  3. import "core:math"
  4. import "core:strconv"
  5. import "core:testing"
  6. @test
  7. test_classify_f16 :: proc(t: ^testing.T) {
  8. r: math.Float_Class
  9. Datum :: struct {
  10. i: int,
  11. v: f16,
  12. e: math.Float_Class,
  13. }
  14. @static data := []Datum{
  15. { 0, 1.2, .Normal },
  16. { 1, 0h0001, .Subnormal },
  17. { 2, 0.0, .Zero },
  18. { 3, -0.0, .Neg_Zero },
  19. { 4, math.SNAN_F16, .NaN },
  20. { 5, math.QNAN_F16, .NaN },
  21. { 6, math.INF_F16, .Inf },
  22. { 7, math.NEG_INF_F16, .Neg_Inf },
  23. }
  24. for d, i in data {
  25. assert(i == d.i)
  26. r = math.classify_f16(d.v)
  27. testing.expectf(t, r == d.e, "%h -> %v != %v", d.v, r, d.e)
  28. }
  29. /* Check all subnormals (exponent 0, 10-bit significand non-zero) */
  30. for i in u16(1)..<0x400 {
  31. v := transmute(f16)i
  32. r = math.classify_f16(v)
  33. e :: math.Float_Class.Subnormal
  34. testing.expectf(t, r == e, "%h -> %v != %v", v, r, e)
  35. }
  36. }
  37. @test
  38. test_classify_f32 :: proc(t: ^testing.T) {
  39. r: math.Float_Class
  40. Datum :: struct {
  41. i: int,
  42. v: f32,
  43. e: math.Float_Class,
  44. }
  45. @static data := []Datum{
  46. { 0, 1.2, .Normal },
  47. { 1, 0h0000_0001, .Subnormal },
  48. { 2, 0.0, .Zero },
  49. { 3, -0.0, .Neg_Zero },
  50. { 4, math.SNAN_F32, .NaN },
  51. { 5, math.QNAN_F32, .NaN },
  52. { 6, math.INF_F32, .Inf },
  53. { 7, math.NEG_INF_F32, .Neg_Inf },
  54. }
  55. for d, i in data {
  56. assert(i == d.i)
  57. r = math.classify_f32(d.v)
  58. testing.expectf(t, r == d.e, "%h -> %v != %v", d.v, r, d.e)
  59. }
  60. }
  61. @test
  62. test_classify_f64 :: proc(t: ^testing.T) {
  63. r: math.Float_Class
  64. Datum :: struct {
  65. i: int,
  66. v: f64,
  67. e: math.Float_Class,
  68. }
  69. @static data := []Datum{
  70. { 0, 1.2, .Normal },
  71. { 1, 0h0000_0000_0000_0001, .Subnormal },
  72. { 2, 0.0, .Zero },
  73. { 3, -0.0, .Neg_Zero },
  74. { 4, math.SNAN_F64, .NaN },
  75. { 5, math.QNAN_F64, .NaN },
  76. { 6, math.INF_F64, .Inf },
  77. { 7, math.NEG_INF_F64, .Neg_Inf },
  78. }
  79. for d, i in data {
  80. assert(i == d.i)
  81. r = math.classify_f64(d.v)
  82. testing.expectf(t, r == d.e, "%h -> %v != %v", d.v, r, d.e)
  83. }
  84. }
  85. @test
  86. test_trunc_f16 :: proc(t: ^testing.T) {
  87. r, v: f16
  88. Datum :: struct {
  89. i: int,
  90. v: f16,
  91. e: f16,
  92. }
  93. @static data := []Datum{
  94. { 0, 10.5, 10 }, // Issue #1574 fract in linalg/glm is broken
  95. { 1, -10.5, -10 },
  96. { 2, math.F16_MAX, math.F16_MAX },
  97. { 3, -math.F16_MAX, -math.F16_MAX },
  98. { 4, math.F16_MIN, 0.0 },
  99. { 5, -math.F16_MIN, -0.0 },
  100. { 6, 0.0, 0.0 },
  101. { 7, -0.0, -0.0 },
  102. { 8, 1, 1 },
  103. { 9, -1, -1 },
  104. { 10, math.INF_F16, math.INF_F16 },
  105. { 11, math.NEG_INF_F16, math.NEG_INF_F16 },
  106. /* From https://en.wikipedia.org/wiki/Half-precision_floating-point_format */
  107. { 12, 0h3C01, 1 }, // 0x1.004p+0 (smallest > 1)
  108. { 13, -0h3C01, -1 },
  109. { 14, 0h3BFF, 0.0 }, // 0x1.ffcp-1 (largest < 1)
  110. { 15, -0h3BFF, -0.0 },
  111. { 16, 0h0001, 0.0 }, // 0x0.004p-14 (smallest subnormal)
  112. { 17, -0h0001, -0.0 },
  113. { 18, 0h03FF, 0.0 }, // 0x0.ffcp-14 (largest subnormal)
  114. { 19, -0h03FF, -0.0 },
  115. { 20, 0hC809, -8 }, // -0x1.024p+3
  116. { 21, 0h4458, 4 }, // 0x1.16p+2
  117. }
  118. for d, i in data {
  119. assert(i == d.i)
  120. r = math.trunc_f16(d.v)
  121. testing.expectf(t, r == d.e, "%h -> %h != %h", d.v, r, d.e)
  122. }
  123. v = math.SNAN_F16
  124. r = math.trunc_f16(v)
  125. testing.expectf(t, math.is_nan_f16(r), "%f != NaN", v, r)
  126. v = math.QNAN_F16
  127. r = math.trunc_f16(v)
  128. testing.expectf(t, math.is_nan_f16(r), "%f != NaN", v, r)
  129. }
  130. @test
  131. test_trunc_f32 :: proc(t: ^testing.T) {
  132. r, v: f32
  133. Datum :: struct {
  134. i: int,
  135. v: f32,
  136. e: f32,
  137. }
  138. @static data := []Datum{
  139. { 0, 10.5, 10 }, // Issue #1574 fract in linalg/glm is broken
  140. { 1, -10.5, -10 },
  141. { 2, math.F32_MAX, math.F32_MAX },
  142. { 3, -math.F32_MAX, -math.F32_MAX },
  143. { 4, math.F32_MIN, 0.0 },
  144. { 5, -math.F32_MIN, -0.0 },
  145. { 6, 0.0, 0.0 },
  146. { 7, -0.0, -0.0 },
  147. { 8, 1, 1 },
  148. { 9, -1, -1 },
  149. { 10, math.INF_F32, math.INF_F32 },
  150. { 11, math.NEG_INF_F32, math.NEG_INF_F32 },
  151. /* From https://en.wikipedia.org/wiki/Single-precision_floating-point_format */
  152. { 12, 0h3F80_0001, 1 }, // 0x1.000002p+0 (smallest > 1)
  153. { 13, -0h3F80_0001, -1 },
  154. { 14, 0h3F7F_FFFF, 0.0 }, // 0x1.fffffep-1 (largest < 1)
  155. { 15, -0h3F7F_FFFF, -0.0 },
  156. { 16, 0h0000_0001, 0.0 }, // 0x0.000002p-126 (smallest subnormal)
  157. { 17, -0h0000_0001, -0.0 },
  158. { 18, 0h007F_FFFF, 0.0 }, // 0x0.fffffep-126 (largest subnormal)
  159. { 19, -0h007F_FFFF, -0.0 },
  160. /* From libc-test src/math/sanity/truncf.h */
  161. { 20, 0hC101_11D0, -8 }, // -0x1.0223ap+3
  162. { 21, 0h408B_0C34, 4 }, // 0x1.161868p+2
  163. { 22, 0hC106_1A5A, -8 }, // -0x1.0c34b4p+3
  164. { 23, 0hC0D1_0378, -6 }, // -0x1.a206fp+2
  165. { 24, 0h4114_45DE, 9 }, // 0x1.288bbcp+3
  166. { 25, 0h3F29_77E8, 0.0 }, // 0x1.52efdp-1
  167. { 26, 0hBED0_2E64, -0.0 }, // -0x1.a05cc8p-2
  168. { 27, 0h3F0F_CF7D, 0.0 }, // 0x1.1f9efap-1
  169. { 28, 0h3F46_2ED8, 0.0 }, // 0x1.8c5dbp-1
  170. { 29, 0hBF2D_C375, -0.0 }, // -0x1.5b86eap-1
  171. }
  172. for d, i in data {
  173. assert(i == d.i)
  174. r = math.trunc_f32(d.v)
  175. testing.expectf(t, r == d.e, "%h -> %h != %h", d.v, r, d.e)
  176. }
  177. v = math.SNAN_F32
  178. r = math.trunc_f32(v)
  179. testing.expectf(t, math.is_nan_f32(r), "%f -> %f != NaN", v, r)
  180. v = math.QNAN_F32
  181. r = math.trunc_f32(v)
  182. testing.expectf(t, math.is_nan_f32(r), "%f -> %f != NaN", v, r)
  183. }
  184. @test
  185. test_trunc_f64 :: proc(t: ^testing.T) {
  186. r, v: f64
  187. Datum :: struct {
  188. i: int,
  189. v: f64,
  190. e: f64,
  191. }
  192. data := []Datum{
  193. { 0, 10.5, 10 }, // Issue #1574 fract in linalg/glm is broken
  194. { 1, -10.5, -10 },
  195. { 2, math.F64_MAX, math.F64_MAX },
  196. { 3, -math.F64_MAX, -math.F64_MAX },
  197. { 4, math.F64_MIN, 0.0 },
  198. { 5, -math.F64_MIN, -0.0 },
  199. { 6, 0.0, 0.0 },
  200. { 7, -0.0, -0.0 },
  201. { 8, 1, 1 },
  202. { 9, -1, -1 },
  203. { 10, math.INF_F64, math.INF_F64 },
  204. { 11, math.NEG_INF_F64, math.NEG_INF_F64 },
  205. /* From https://en.wikipedia.org/wiki/Double-precision_floating-point_format */
  206. { 12, 0h3FF0_0000_0000_0001, 1 }, // 0x1.0000000000001p+0 (smallest > 1)
  207. { 13, -0h3FF0_0000_0000_0001, -1 },
  208. { 14, 0h3FEF_FFFF_FFFF_FFFF, 0.0 }, // 0x1.fffffffffffffp-1 (largest < 1)
  209. { 15, -0h3FEF_FFFF_FFFF_FFFF, -0.0 },
  210. { 16, 0h0000_0000_0000_0001, 0.0 }, // 0x0.0000000000001p-1022 (smallest subnormal)
  211. { 17, -0h0000_0000_0000_0001, -0.0 },
  212. { 18, 0h000F_FFFF_FFFF_FFFF, 0.0 }, // 0x0.fffffffffffffp-1022 (largest subnormal)
  213. { 19, -0h000F_FFFF_FFFF_FFFF, -0.0 },
  214. /* From libc-test src/math/sanity/trunc.h */
  215. { 20, 0hC020_2239_F3C6_A8F1, -8 }, // -0x1.02239f3c6a8f1p+3
  216. { 21, 0h4011_6186_8E18_BC67, 4 }, // 0x1.161868e18bc67p+2
  217. { 22, 0hC020_C34B_3E01_E6E7, -8 }, // -0x1.0c34b3e01e6e7p+3
  218. { 23, 0hC01A_206F_0A19_DCC4, -6 }, // -0x1.a206f0a19dcc4p+2
  219. { 24, 0h4022_88BB_B0D6_A1E6, 9 }, // 0x1.288bbb0d6a1e6p+3
  220. { 25, 0h3FE5_2EFD_0CD8_0497, 0.0 }, // 0x1.52efd0cd80497p-1
  221. { 26, 0hBFDA_05CC_7544_81D1, -0.0 }, // -0x1.a05cc754481d1p-2
  222. { 27, 0h3FE1_F9EF_9347_45CB, 0.0 }, // 0x1.1f9ef934745cbp-1
  223. { 28, 0h3FE8_C5DB_097F_7442, 0.0 }, // 0x1.8c5db097f7442p-1
  224. { 29, 0hBFE5_B86E_A811_8A0E, -0.0 }, // -0x1.5b86ea8118a0ep-1
  225. }
  226. for d, i in data {
  227. assert(i == d.i)
  228. r = math.trunc_f64(d.v)
  229. testing.expectf(t, r == d.e, "%h -> %h != %h", d.v, r, d.e)
  230. }
  231. v = math.SNAN_F64
  232. r = math.trunc_f64(v)
  233. testing.expectf(t, math.is_nan_f64(r), "%f -> %f != NaN", v, r)
  234. v = math.QNAN_F64
  235. r = math.trunc_f64(v)
  236. testing.expectf(t, math.is_nan_f64(r), "%f -> %f != NaN", v, r)
  237. }
  238. @test
  239. test_round_f16 :: proc(t: ^testing.T) {
  240. r, v: f16
  241. Datum :: struct {
  242. i: int,
  243. v: f16,
  244. e: f16,
  245. }
  246. @static data := []Datum{
  247. { 0, 10.5, 11 },
  248. { 1, -10.5, -11 },
  249. { 2, math.F16_MAX, math.F16_MAX },
  250. { 3, -math.F16_MAX, -math.F16_MAX },
  251. { 4, math.F16_MIN, 0.0 },
  252. { 5, -math.F16_MIN, -0.0 },
  253. { 6, 0.0, 0.0 },
  254. { 7, -0.0, -0.0 },
  255. { 8, 1, 1 },
  256. { 9, -1, -1 },
  257. { 10, math.INF_F16, math.INF_F16 },
  258. { 11, math.NEG_INF_F16, math.NEG_INF_F16 },
  259. /* From https://en.wikipedia.org/wiki/Half-precision_floating-point_format */
  260. { 12, 0h3C01, 1 }, // 0x1.004p+0 (smallest > 1)
  261. { 13, -0h3C01, -1 },
  262. { 14, 0h3BFF, 1 }, // 0x1.ffcp-1 (largest < 1)
  263. { 15, -0h3BFF, -1 },
  264. { 16, 0h0001, 0.0 }, // 0x0.004p-14 (smallest subnormal)
  265. { 17, -0h0001, -0.0 },
  266. { 18, 0h03FF, 0.0 }, // 0x0.ffcp-14 (largest subnormal)
  267. { 19, -0h03FF, -0.0 },
  268. { 20, 0hC809, -8 }, // -0x1.024p+3
  269. { 21, 0h4458, 4 }, // 0x1.16p+2
  270. }
  271. for d, i in data {
  272. assert(i == d.i)
  273. r = math.round_f16(d.v)
  274. testing.expectf(t, r == d.e, "%h -> %h != %h", d.v, r, d.e)
  275. }
  276. v = math.SNAN_F16
  277. r = math.round_f16(v)
  278. testing.expectf(t, math.is_nan_f16(r), "%f -> %f != NaN", v, r)
  279. v = math.QNAN_F16
  280. r = math.round_f16(v)
  281. testing.expectf(t, math.is_nan_f16(r), "%f -> %f != NaN", v, r)
  282. }
  283. @test
  284. test_round_f32 :: proc(t: ^testing.T) {
  285. r, v: f32
  286. Datum :: struct {
  287. i: int,
  288. v: f32,
  289. e: f32,
  290. }
  291. @static data := []Datum{
  292. { 0, 10.5, 11 },
  293. { 1, -10.5, -11 },
  294. { 2, math.F32_MAX, math.F32_MAX },
  295. { 3, -math.F32_MAX, -math.F32_MAX },
  296. { 4, math.F32_MIN, 0.0 },
  297. { 5, -math.F32_MIN, -0.0 },
  298. { 6, 0.0, 0.0 },
  299. { 7, -0.0, -0.0 },
  300. { 8, 1, 1 },
  301. { 9, -1, -1 },
  302. { 10, math.INF_F32, math.INF_F32 },
  303. { 11, math.NEG_INF_F32, math.NEG_INF_F32 },
  304. /* From https://en.wikipedia.org/wiki/Single-precision_floating-point_format */
  305. { 12, 0h3F80_0001, 1 }, // 0x1.000002p+0 (smallest > 1)
  306. { 13, -0h3F80_0001, -1 },
  307. { 14, 0h3F7F_FFFF, 1 }, // 0x1.fffffep-1 (largest < 1)
  308. { 15, -0h3F7F_FFFF, -1 },
  309. { 16, 0h0000_0001, 0.0 }, // 0x0.000002p-126 (smallest subnormal)
  310. { 17, -0h0000_0001, -0.0 },
  311. { 18, 0h007F_FFFF, 0.0 }, // 0x0.fffffep-126 (largest subnormal)
  312. { 19, -0h007F_FFFF, -0.0 },
  313. /* From libc-test src/math/sanity/roundf.h */
  314. { 20, 0hC101_11D0, -8 }, // -0x1.0223ap+3
  315. { 21, 0h408B_0C34, 4 }, // 0x1.161868p+2
  316. { 22, 0hC106_1A5A, -8 }, // -0x1.0c34b4p+3
  317. { 23, 0hC0D1_0378, -7 }, // -0x1.a206fp+2
  318. { 24, 0h4114_45DE, 9 }, // 0x1.288bbcp+3
  319. { 25, 0h3F29_77E8, 1.0 }, // 0x1.52efdp-1
  320. { 26, 0hBED0_2E64, -0.0 }, // -0x1.a05cc8p-2
  321. { 27, 0h3F0F_CF7D, 1.0 }, // 0x1.1f9efap-1
  322. { 28, 0h3F46_2ED8, 1.0 }, // 0x1.8c5dbp-1
  323. { 29, 0hBF2D_C375, -1.0 }, // -0x1.5b86eap-1
  324. }
  325. for d, i in data {
  326. assert(i == d.i)
  327. r = math.round_f32(d.v)
  328. testing.expectf(t, r == d.e, "%h -> %h != %h", i, d.v, r, d.e)
  329. }
  330. v = math.SNAN_F32
  331. r = math.round_f32(v)
  332. testing.expectf(t, math.is_nan_f32(r), "%f -> %f != NaN", v, r)
  333. v = math.QNAN_F32
  334. r = math.round_f32(v)
  335. testing.expectf(t, math.is_nan_f32(r), "%f -> %f != NaN", v, r)
  336. }
  337. @test
  338. test_round_f64 :: proc(t: ^testing.T) {
  339. r, v: f64
  340. Datum :: struct {
  341. i: int,
  342. v: f64,
  343. e: f64,
  344. }
  345. data := []Datum{
  346. { 0, 10.5, 11 }, // Issue #1574 fract in linalg/glm is broken
  347. { 1, -10.5, -11 },
  348. { 2, math.F64_MAX, math.F64_MAX },
  349. { 3, -math.F64_MAX, -math.F64_MAX },
  350. { 4, math.F64_MIN, 0.0 },
  351. { 5, -math.F64_MIN, -0.0 },
  352. { 6, 0.0, 0.0 },
  353. { 7, -0.0, -0.0 },
  354. { 8, 1, 1 },
  355. { 9, -1, -1 },
  356. { 10, math.INF_F64, math.INF_F64 },
  357. { 11, math.NEG_INF_F64, math.NEG_INF_F64 },
  358. /* From https://en.wikipedia.org/wiki/Double-precision_floating-point_format */
  359. { 12, 0h3FF0_0000_0000_0001, 1 }, // 0x1.0000000000001p+0 (smallest > 1)
  360. { 13, -0h3FF0_0000_0000_0001, -1 },
  361. { 14, 0h3FEF_FFFF_FFFF_FFFF, 1 }, // 0x1.fffffffffffffp-1 (largest < 1)
  362. { 15, -0h3FEF_FFFF_FFFF_FFFF, -1 },
  363. { 16, 0h0000_0000_0000_0001, 0.0 }, // 0x0.0000000000001p-1022 (smallest subnormal)
  364. { 17, -0h0000_0000_0000_0001, -0.0 },
  365. { 18, 0h000F_FFFF_FFFF_FFFF, 0.0 }, // 0x0.fffffffffffffp-1022 (largest subnormal)
  366. { 19, -0h000F_FFFF_FFFF_FFFF, -0.0 },
  367. /* From libc-test src/math/sanity/round.h */
  368. { 20, 0hC020_2239_F3C6_A8F1, -8 }, // -0x1.02239f3c6a8f1p+3
  369. { 21, 0h4011_6186_8E18_BC67, 4 }, // 0x1.161868e18bc67p+2
  370. { 22, 0hC020_C34B_3E01_E6E7, -8 }, // -0x1.0c34b3e01e6e7p+3
  371. { 23, 0hC01A_206F_0A19_DCC4, -7 }, // -0x1.a206f0a19dcc4p+2
  372. { 24, 0h4022_88BB_B0D6_A1E6, 9 }, // 0x1.288bbb0d6a1e6p+3
  373. { 25, 0h3FE5_2EFD_0CD8_0497, 1.0 }, // 0x1.52efd0cd80497p-1
  374. { 26, 0hBFDA_05CC_7544_81D1, -0.0 }, // -0x1.a05cc754481d1p-2
  375. { 27, 0h3FE1_F9EF_9347_45CB, 1.0 }, // 0x1.1f9ef934745cbp-1
  376. { 28, 0h3FE8_C5DB_097F_7442, 1.0 }, // 0x1.8c5db097f7442p-1
  377. { 29, 0hBFE5_B86E_A811_8A0E, -1.0 }, // -0x1.5b86ea8118a0ep-1
  378. }
  379. for d, i in data {
  380. assert(i == d.i)
  381. r = math.round_f64(d.v)
  382. testing.expectf(t, r == d.e, "%h -> %h != %h", d.v, r, d.e)
  383. }
  384. v = math.SNAN_F64
  385. r = math.round_f64(v)
  386. testing.expectf(t, math.is_nan_f64(r), "%f -> %f != NaN", v, r)
  387. v = math.QNAN_F64
  388. r = math.round_f64(v)
  389. testing.expectf(t, math.is_nan_f64(r), "%f -> %f != NaN", v, r)
  390. }
  391. vf := []f64{
  392. 4.9790119248836735e+00,
  393. 7.7388724745781045e+00,
  394. -2.7688005719200159e-01,
  395. -5.0106036182710749e+00,
  396. 9.6362937071984173e+00,
  397. 2.9263772392439646e+00,
  398. 5.2290834314593066e+00,
  399. 2.7279399104360102e+00,
  400. 1.8253080916808550e+00,
  401. -8.6859247685756013e+00,
  402. }
  403. // The expected results below were computed by the high precision calculators at https://keisan.casio.com/.
  404. acos := []f64{
  405. 1.0496193546107222142571536e+00,
  406. 6.8584012813664425171660692e-01,
  407. 1.5984878714577160325521819e+00,
  408. 2.0956199361475859327461799e+00,
  409. 2.7053008467824138592616927e-01,
  410. 1.2738121680361776018155625e+00,
  411. 1.0205369421140629186287407e+00,
  412. 1.2945003481781246062157835e+00,
  413. 1.3872364345374451433846657e+00,
  414. 2.6231510803970463967294145e+00,
  415. }
  416. acosh := []f64{
  417. 2.4743347004159012494457618e+00,
  418. 2.8576385344292769649802701e+00,
  419. 7.2796961502981066190593175e-01,
  420. 2.4796794418831451156471977e+00,
  421. 3.0552020742306061857212962e+00,
  422. 2.044238592688586588942468e+00,
  423. 2.5158701513104513595766636e+00,
  424. 1.99050839282411638174299e+00,
  425. 1.6988625798424034227205445e+00,
  426. 2.9611454842470387925531875e+00,
  427. }
  428. asin := []f64{
  429. 5.2117697218417440497416805e-01,
  430. 8.8495619865825236751471477e-01,
  431. -02.769154466281941332086016e-02,
  432. -5.2482360935268931351485822e-01,
  433. 1.3002662421166552333051524e+00,
  434. 2.9698415875871901741575922e-01,
  435. 5.5025938468083370060258102e-01,
  436. 2.7629597861677201301553823e-01,
  437. 1.83559892257451475846656e-01,
  438. -1.0523547536021497774980928e+00,
  439. }
  440. asinh := []f64{
  441. 2.3083139124923523427628243e+00,
  442. 2.743551594301593620039021e+00,
  443. -2.7345908534880091229413487e-01,
  444. -2.3145157644718338650499085e+00,
  445. 2.9613652154015058521951083e+00,
  446. 1.7949041616585821933067568e+00,
  447. 2.3564032905983506405561554e+00,
  448. 1.7287118790768438878045346e+00,
  449. 1.3626658083714826013073193e+00,
  450. -2.8581483626513914445234004e+00,
  451. }
  452. atan := []f64{
  453. 1.372590262129621651920085e+00,
  454. 1.442290609645298083020664e+00,
  455. -2.7011324359471758245192595e-01,
  456. -1.3738077684543379452781531e+00,
  457. 1.4673921193587666049154681e+00,
  458. 1.2415173565870168649117764e+00,
  459. 1.3818396865615168979966498e+00,
  460. 1.2194305844639670701091426e+00,
  461. 1.0696031952318783760193244e+00,
  462. -1.4561721938838084990898679e+00,
  463. }
  464. atanh := []f64{
  465. 5.4651163712251938116878204e-01,
  466. 1.0299474112843111224914709e+00,
  467. -2.7695084420740135145234906e-02,
  468. -5.5072096119207195480202529e-01,
  469. 1.9943940993171843235906642e+00,
  470. 3.01448604578089708203017e-01,
  471. 5.8033427206942188834370595e-01,
  472. 2.7987997499441511013958297e-01,
  473. 1.8459947964298794318714228e-01,
  474. -1.3273186910532645867272502e+00,
  475. }
  476. atan2 := []f64{
  477. 1.1088291730037004444527075e+00,
  478. 9.1218183188715804018797795e-01,
  479. 1.5984772603216203736068915e+00,
  480. 2.0352918654092086637227327e+00,
  481. 8.0391819139044720267356014e-01,
  482. 1.2861075249894661588866752e+00,
  483. 1.0889904479131695712182587e+00,
  484. 1.3044821793397925293797357e+00,
  485. 1.3902530903455392306872261e+00,
  486. 2.2859857424479142655411058e+00,
  487. }
  488. cos := []f64{
  489. 2.634752140995199110787593e-01,
  490. 1.148551260848219865642039e-01,
  491. 9.6191297325640768154550453e-01,
  492. 2.938141150061714816890637e-01,
  493. -9.777138189897924126294461e-01,
  494. -9.7693041344303219127199518e-01,
  495. 4.940088096948647263961162e-01,
  496. -9.1565869021018925545016502e-01,
  497. -2.517729313893103197176091e-01,
  498. -7.39241351595676573201918e-01,
  499. }
  500. // Results for 1e5 * Pi + vf[i]
  501. cosLarge := []f64{
  502. 2.634752141185559426744e-01,
  503. 1.14855126055543100712e-01,
  504. 9.61912973266488928113e-01,
  505. 2.9381411499556122552e-01,
  506. -9.777138189880161924641e-01,
  507. -9.76930413445147608049e-01,
  508. 4.940088097314976789841e-01,
  509. -9.15658690217517835002e-01,
  510. -2.51772931436786954751e-01,
  511. -7.3924135157173099849e-01,
  512. }
  513. cosh := []f64{
  514. 7.2668796942212842775517446e+01,
  515. 1.1479413465659254502011135e+03,
  516. 1.0385767908766418550935495e+00,
  517. 7.5000957789658051428857788e+01,
  518. 7.655246669605357888468613e+03,
  519. 9.3567491758321272072888257e+00,
  520. 9.331351599270605471131735e+01,
  521. 7.6833430994624643209296404e+00,
  522. 3.1829371625150718153881164e+00,
  523. 2.9595059261916188501640911e+03,
  524. }
  525. sin := []f64{
  526. -9.6466616586009283766724726e-01,
  527. 9.9338225271646545763467022e-01,
  528. -2.7335587039794393342449301e-01,
  529. 9.5586257685042792878173752e-01,
  530. -2.099421066779969164496634e-01,
  531. 2.135578780799860532750616e-01,
  532. -8.694568971167362743327708e-01,
  533. 4.019566681155577786649878e-01,
  534. 9.6778633541687993721617774e-01,
  535. -6.734405869050344734943028e-01,
  536. }
  537. // Results for 1e5 * Pi + vf[i]
  538. sinLarge := []f64{
  539. -9.646661658548936063912e-01,
  540. 9.933822527198506903752e-01,
  541. -2.7335587036246899796e-01,
  542. 9.55862576853689321268e-01,
  543. -2.099421066862688873691e-01,
  544. 2.13557878070308981163e-01,
  545. -8.694568970959221300497e-01,
  546. 4.01956668098863248917e-01,
  547. 9.67786335404528727927e-01,
  548. -6.7344058693131973066e-01,
  549. }
  550. sinh := []f64{
  551. 7.2661916084208532301448439e+01,
  552. 1.1479409110035194500526446e+03,
  553. -2.8043136512812518927312641e-01,
  554. -7.499429091181587232835164e+01,
  555. 7.6552466042906758523925934e+03,
  556. 9.3031583421672014313789064e+00,
  557. 9.330815755828109072810322e+01,
  558. 7.6179893137269146407361477e+00,
  559. 3.021769180549615819524392e+00,
  560. -2.95950575724449499189888e+03,
  561. }
  562. sqrt := []f64{
  563. 2.2313699659365484748756904e+00,
  564. 2.7818829009464263511285458e+00,
  565. 5.2619393496314796848143251e-01,
  566. 2.2384377628763938724244104e+00,
  567. 3.1042380236055381099288487e+00,
  568. 1.7106657298385224403917771e+00,
  569. 2.286718922705479046148059e+00,
  570. 1.6516476350711159636222979e+00,
  571. 1.3510396336454586262419247e+00,
  572. 2.9471892997524949215723329e+00,
  573. }
  574. tan := []f64{
  575. -3.661316565040227801781974e+00,
  576. 8.64900232648597589369854e+00,
  577. -2.8417941955033612725238097e-01,
  578. 3.253290185974728640827156e+00,
  579. 2.147275640380293804770778e-01,
  580. -2.18600910711067004921551e-01,
  581. -1.760002817872367935518928e+00,
  582. -4.389808914752818126249079e-01,
  583. -3.843885560201130679995041e+00,
  584. 9.10988793377685105753416e-01,
  585. }
  586. // Results for 1e5 * Pi + vf[i]
  587. tanLarge := []f64{
  588. -3.66131656475596512705e+00,
  589. 8.6490023287202547927e+00,
  590. -2.841794195104782406e-01,
  591. 3.2532901861033120983e+00,
  592. 2.14727564046880001365e-01,
  593. -2.18600910700688062874e-01,
  594. -1.760002817699722747043e+00,
  595. -4.38980891453536115952e-01,
  596. -3.84388555942723509071e+00,
  597. 9.1098879344275101051e-01,
  598. }
  599. tanh := []f64{
  600. 9.9990531206936338549262119e-01,
  601. 9.9999962057085294197613294e-01,
  602. -2.7001505097318677233756845e-01,
  603. -9.9991110943061718603541401e-01,
  604. 9.9999999146798465745022007e-01,
  605. 9.9427249436125236705001048e-01,
  606. 9.9994257600983138572705076e-01,
  607. 9.9149409509772875982054701e-01,
  608. 9.4936501296239685514466577e-01,
  609. -9.9999994291374030946055701e-01,
  610. }
  611. NaN :: 0h7fff_ffff_ffff_ffff
  612. Pi :: 0h4009_21fb_5444_2d18
  613. // arguments and expected results for special cases
  614. vfacos_sc := []f64{
  615. -Pi,
  616. 1,
  617. Pi,
  618. NaN,
  619. }
  620. acos_sc := []f64{
  621. NaN,
  622. 0,
  623. NaN,
  624. NaN,
  625. }
  626. vfacosh_sc := []f64{
  627. math.inf_f64(-1),
  628. 0.5,
  629. 1,
  630. math.inf_f64(1),
  631. NaN,
  632. }
  633. acosh_sc := []f64{
  634. NaN,
  635. NaN,
  636. 0,
  637. math.inf_f64(1),
  638. NaN,
  639. }
  640. vfasin_sc := []f64{
  641. -Pi,
  642. math.copy_sign_f64(0, -1),
  643. 0,
  644. Pi,
  645. NaN,
  646. }
  647. asin_sc := []f64{
  648. NaN,
  649. math.copy_sign_f64(0, -1),
  650. 0,
  651. NaN,
  652. NaN,
  653. }
  654. vfasinh_sc := []f64{
  655. math.inf_f64(-1),
  656. math.copy_sign_f64(0, -1),
  657. 0,
  658. math.inf_f64(1),
  659. NaN,
  660. }
  661. asinh_sc := []f64{
  662. math.inf_f64(-1),
  663. math.copy_sign_f64(0, -1),
  664. 0,
  665. math.inf_f64(1),
  666. NaN,
  667. }
  668. vfatan_sc := []f64{
  669. math.inf_f64(-1),
  670. math.copy_sign_f64(0, -1),
  671. 0,
  672. math.inf_f64(1),
  673. NaN,
  674. }
  675. atan_sc := []f64{
  676. -Pi / 2,
  677. math.copy_sign_f64(0, -1),
  678. 0,
  679. Pi / 2,
  680. NaN,
  681. }
  682. vfatanh_sc := []f64{
  683. math.inf_f64(-1),
  684. -Pi,
  685. -1,
  686. math.copy_sign_f64(0, -1),
  687. 0,
  688. 1,
  689. Pi,
  690. math.inf_f64(1),
  691. NaN,
  692. }
  693. atanh_sc := []f64{
  694. NaN,
  695. NaN,
  696. math.inf_f64(-1),
  697. math.copy_sign_f64(0, -1),
  698. 0,
  699. math.inf_f64(1),
  700. NaN,
  701. NaN,
  702. NaN,
  703. }
  704. vfatan2_sc := [][2]f64{
  705. {math.inf_f64(-1), math.inf_f64(-1)},
  706. {math.inf_f64(-1), -Pi},
  707. {math.inf_f64(-1), 0},
  708. {math.inf_f64(-1), +Pi},
  709. {math.inf_f64(-1), math.inf_f64(1)},
  710. {math.inf_f64(-1), NaN},
  711. {-Pi, math.inf_f64(-1)},
  712. {-Pi, 0},
  713. {-Pi, math.inf_f64(1)},
  714. {-Pi, NaN},
  715. {math.copy_sign_f64(0, -1), math.inf_f64(-1)},
  716. {math.copy_sign_f64(0, -1), -Pi},
  717. {math.copy_sign_f64(0, -1), math.copy_sign_f64(0, -1)},
  718. {math.copy_sign_f64(0, -1), 0},
  719. {math.copy_sign_f64(0, -1), +Pi},
  720. {math.copy_sign_f64(0, -1), math.inf_f64(1)},
  721. {math.copy_sign_f64(0, -1), NaN},
  722. {0, math.inf_f64(-1)},
  723. {0, -Pi},
  724. {0, math.copy_sign_f64(0, -1)},
  725. {0, 0},
  726. {0, +Pi},
  727. {0, math.inf_f64(1)},
  728. {0, NaN},
  729. {+Pi, math.inf_f64(-1)},
  730. {+Pi, 0},
  731. {+Pi, math.inf_f64(1)},
  732. {1.0, math.inf_f64(1)},
  733. {-1.0, math.inf_f64(1)},
  734. {+Pi, NaN},
  735. {math.inf_f64(1), math.inf_f64(-1)},
  736. {math.inf_f64(1), -Pi},
  737. {math.inf_f64(1), 0},
  738. {math.inf_f64(1), +Pi},
  739. {math.inf_f64(1), math.inf_f64(1)},
  740. {math.inf_f64(1), NaN},
  741. {NaN, NaN},
  742. }
  743. atan2_sc := []f64{
  744. -3 * Pi / 4, // atan2(-Inf, -Inf)
  745. -Pi / 2, // atan2(-Inf, -Pi)
  746. -Pi / 2, // atan2(-Inf, +0)
  747. -Pi / 2, // atan2(-Inf, +Pi)
  748. -Pi / 4, // atan2(-Inf, +Inf)
  749. NaN, // atan2(-Inf, NaN)
  750. -Pi, // atan2(-Pi, -Inf)
  751. -Pi / 2, // atan2(-Pi, +0)
  752. math.copy_sign_f64(0, -1), // atan2(-Pi, Inf)
  753. NaN, // atan2(-Pi, NaN)
  754. -Pi, // atan2(-0, -Inf)
  755. -Pi, // atan2(-0, -Pi)
  756. -Pi, // atan2(-0, -0)
  757. math.copy_sign_f64(0, -1), // atan2(-0, +0)
  758. math.copy_sign_f64(0, -1), // atan2(-0, +Pi)
  759. math.copy_sign_f64(0, -1), // atan2(-0, +Inf)
  760. NaN, // atan2(-0, NaN)
  761. Pi, // atan2(+0, -Inf)
  762. Pi, // atan2(+0, -Pi)
  763. Pi, // atan2(+0, -0)
  764. 0, // atan2(+0, +0)
  765. 0, // atan2(+0, +Pi)
  766. 0, // atan2(+0, +Inf)
  767. NaN, // atan2(+0, NaN)
  768. Pi, // atan2(+Pi, -Inf)
  769. Pi / 2, // atan2(+Pi, +0)
  770. 0, // atan2(+Pi, +Inf)
  771. 0, // atan2(+1, +Inf)
  772. math.copy_sign_f64(0, -1), // atan2(-1, +Inf)
  773. NaN, // atan2(+Pi, NaN)
  774. 3 * Pi / 4, // atan2(+Inf, -Inf)
  775. Pi / 2, // atan2(+Inf, -Pi)
  776. Pi / 2, // atan2(+Inf, +0)
  777. Pi / 2, // atan2(+Inf, +Pi)
  778. Pi / 4, // atan2(+Inf, +Inf)
  779. NaN, // atan2(+Inf, NaN)
  780. NaN, // atan2(NaN, NaN)
  781. }
  782. vfcbrt_sc := []f64{
  783. math.inf_f64(-1),
  784. math.copy_sign_f64(0, -1),
  785. 0,
  786. math.inf_f64(1),
  787. NaN,
  788. }
  789. cbrt_sc := []f64{
  790. math.inf_f64(-1),
  791. math.copy_sign_f64(0, -1),
  792. 0,
  793. math.inf_f64(1),
  794. NaN,
  795. }
  796. vfceil_sc := []f64{
  797. math.inf_f64(-1),
  798. math.copy_sign_f64(0, -1),
  799. 0,
  800. math.inf_f64(1),
  801. NaN,
  802. }
  803. ceil_sc := []f64{
  804. math.inf_f64(-1),
  805. math.copy_sign_f64(0, -1),
  806. 0,
  807. math.inf_f64(1),
  808. NaN,
  809. }
  810. vfcopysign_sc := []f64{
  811. math.inf_f64(-1),
  812. math.inf_f64(1),
  813. NaN,
  814. }
  815. copysign_sc := []f64{
  816. math.inf_f64(-1),
  817. math.inf_f64(-1),
  818. NaN,
  819. }
  820. vfcos_sc := []f64{
  821. math.inf_f64(-1),
  822. math.inf_f64(1),
  823. NaN,
  824. }
  825. cos_sc := []f64{
  826. NaN,
  827. NaN,
  828. NaN,
  829. }
  830. vfcosh_sc := []f64{
  831. math.inf_f64(-1),
  832. math.copy_sign_f64(0, -1),
  833. 0,
  834. math.inf_f64(1),
  835. NaN,
  836. }
  837. cosh_sc := []f64{
  838. math.inf_f64(1),
  839. 1,
  840. 1,
  841. math.inf_f64(1),
  842. NaN,
  843. }
  844. vfsin_sc := []f64{
  845. math.inf_f64(-1),
  846. math.copy_sign_f64(0, -1),
  847. 0,
  848. math.inf_f64(1),
  849. NaN,
  850. }
  851. sin_sc := []f64{
  852. NaN,
  853. math.copy_sign_f64(0, -1),
  854. 0,
  855. NaN,
  856. NaN,
  857. }
  858. vfsinh_sc := []f64{
  859. math.inf_f64(-1),
  860. math.copy_sign_f64(0, -1),
  861. 0,
  862. math.inf_f64(1),
  863. NaN,
  864. }
  865. sinh_sc := []f64{
  866. math.inf_f64(-1),
  867. math.copy_sign_f64(0, -1),
  868. 0,
  869. math.inf_f64(1),
  870. NaN,
  871. }
  872. vftanh_sc := []f64{
  873. math.inf_f64(-1),
  874. math.copy_sign_f64(0, -1),
  875. 0,
  876. math.inf_f64(1),
  877. NaN,
  878. }
  879. tanh_sc := []f64{
  880. -1,
  881. math.copy_sign_f64(0, -1),
  882. 0,
  883. 1,
  884. NaN,
  885. }
  886. tolerance :: proc(a, b, e: f64) -> bool {
  887. // Multiplying by e here can underflow denormal values to zero.
  888. // Check a==b so that at least if a and b are small and identical
  889. // we say they match.
  890. if a == b {
  891. return true
  892. }
  893. e := e
  894. d := a - b
  895. if d < 0 {
  896. d = -d
  897. }
  898. // note: b is correct (expected) value, a is actual value.
  899. // make error tolerance a fraction of b, not a.
  900. if b != 0 {
  901. e = e * b
  902. if e < 0 {
  903. e = -e
  904. }
  905. }
  906. return d < e
  907. }
  908. close :: proc(t: ^testing.T, a, b: f64, loc := #caller_location) -> bool {
  909. ok := tolerance(a, b, 1e-9)
  910. testing.expectf(t, ok, "%.15g is not close to %.15g", a, b, loc=loc)
  911. return ok
  912. }
  913. veryclose :: proc(t: ^testing.T, a, b: f64, loc := #caller_location) -> bool {
  914. ok := tolerance(a, b, 4e-14)
  915. testing.expectf(t, ok, "%.15g is not veryclose to %.15g", a, b, loc=loc)
  916. return ok
  917. }
  918. soclose :: proc(t: ^testing.T, a, b, e: f64, loc := #caller_location) -> bool {
  919. ok := tolerance(a, b, e)
  920. testing.expectf(t, ok, "%.15g is not soclose to %.15g", a, b, loc=loc)
  921. return ok
  922. }
  923. alike :: proc(t: ^testing.T, a, b: f64, loc := #caller_location) -> bool {
  924. ok := false
  925. switch {
  926. case math.is_nan(a) && math.is_nan(b):
  927. ok = true
  928. case a == b:
  929. ok = math.sign_bit(a) == math.sign_bit(b)
  930. }
  931. testing.expectf(t, ok, "%.15g is not alike to %.15g", a, b, loc=loc)
  932. return ok
  933. }
  934. @test
  935. test_nan32 :: proc(t: ^testing.T) {
  936. float32 := f32(NaN)
  937. equal := float32 == float32
  938. testing.expectf(t, !equal, "float32(NaN) is %.15g, expected NaN", float32)
  939. }
  940. @test
  941. test_nan64 :: proc(t: ^testing.T) {
  942. float64 := NaN
  943. equal := float64 == float64
  944. testing.expectf(t, !equal, "NaN returns %.15g, expected NaN", float64)
  945. }
  946. @test
  947. test_acos :: proc(t: ^testing.T) {
  948. for _, i in vf {
  949. a := vf[i] / 10
  950. f := math.acos(a)
  951. testing.expectf(t, close(t, acos[i], f), "math.acos(%.15g) = %.15g, want %.15g", a, f, acos[i])
  952. }
  953. for _, i in vfacos_sc {
  954. f := math.acos(vfacos_sc[i])
  955. testing.expectf(t, alike(t, acos_sc[i], f), "math.acos(%.15g) = %.15g, want %.15g", vfacos_sc[i], f, acos_sc[i])
  956. }
  957. }
  958. @test
  959. test_acosh :: proc(t: ^testing.T) {
  960. for _, i in vf {
  961. a := 1 + abs(vf[i])
  962. f := math.acosh(a)
  963. testing.expectf(t, veryclose(t, acosh[i], f), "math.acosh(%.15g) = %.15g, want %.15g", a, f, acosh[i])
  964. }
  965. for _, i in vfacosh_sc {
  966. f := math.acosh(vfacosh_sc[i])
  967. testing.expectf(t, alike(t, acosh_sc[i], f), "math.acosh(%.15g) = %.15g, want %.15g", vfacosh_sc[i], f, acosh_sc[i])
  968. }
  969. }
  970. @test
  971. test_asin :: proc(t: ^testing.T) {
  972. for _, i in vf {
  973. a := vf[i] / 10
  974. f := math.asin(a)
  975. testing.expectf(t, veryclose(t, asin[i], f), "math.asin(%.15g) = %.15g, want %.15g", a, f, asin[i])
  976. }
  977. for _, i in vfasin_sc {
  978. f := math.asin(vfasin_sc[i])
  979. testing.expectf(t, alike(t, asin_sc[i], f), "math.asin(%.15g) = %.15g, want %.15g", vfasin_sc[i], f, asin_sc[i])
  980. }
  981. }
  982. @test
  983. test_asinh :: proc(t: ^testing.T) {
  984. for _, i in vf {
  985. f := math.asinh(vf[i])
  986. testing.expectf(t, veryclose(t, asinh[i], f), "math.asinh(%.15g) = %.15g, want %.15g", vf[i], f, asinh[i])
  987. }
  988. for _, i in vfasinh_sc {
  989. f := math.asinh(vfasinh_sc[i])
  990. testing.expectf(t, alike(t, asinh_sc[i], f), "math.asinh(%.15g) = %.15g, want %.15g", vfasinh_sc[i], f, asinh_sc[i])
  991. }
  992. }
  993. @test
  994. test_atan :: proc(t: ^testing.T) {
  995. for _, i in vf {
  996. f := math.atan(vf[i])
  997. testing.expectf(t, veryclose(t, atan[i], f), "math.atan(%.15g) = %.15g, want %.15g", vf[i], f, atan[i])
  998. }
  999. for _, i in vfatan_sc {
  1000. f := math.atan(vfatan_sc[i])
  1001. testing.expectf(t, alike(t, atan_sc[i], f), "math.atan(%.15g) = %.15g, want %.15g", vfatan_sc[i], f, atan_sc[i])
  1002. }
  1003. }
  1004. @test
  1005. test_atanh :: proc(t: ^testing.T) {
  1006. for _, i in vf {
  1007. a := vf[i] / 10
  1008. f := math.atanh(a)
  1009. testing.expectf(t, veryclose(t, atanh[i], f), "math.atanh(%.15g) = %.15g, want %.15g", a, f, atanh[i])
  1010. }
  1011. for _, i in vfatanh_sc {
  1012. f := math.atanh(vfatanh_sc[i])
  1013. testing.expectf(t, alike(t, atanh_sc[i], f), "math.atanh(%.15g) = %.15g, want %.15g", vfatanh_sc[i], f, atanh_sc[i])
  1014. }
  1015. }
  1016. @test
  1017. test_atan2 :: proc(t: ^testing.T) {
  1018. for _, i in vf {
  1019. f := math.atan2(10, vf[i])
  1020. testing.expectf(t, veryclose(t, atan2[i], f), "math.atan2(10, %.15g) = %.15g, want %.15g", vf[i], f, atan2[i])
  1021. }
  1022. for _, i in vfatan2_sc {
  1023. f := math.atan2(vfatan2_sc[i][0], vfatan2_sc[i][1])
  1024. testing.expectf(t, alike(t, atan2_sc[i], f), "math.atan2(%.15g, %.15g) = %.15g, want %.15g", vfatan2_sc[i][0], vfatan2_sc[i][1], f, atan2_sc[i])
  1025. }
  1026. }
  1027. @test
  1028. test_cos :: proc(t: ^testing.T) {
  1029. for _, i in vf {
  1030. f := math.cos(vf[i])
  1031. testing.expectf(t, veryclose(t, cos[i], f), "math.cos(%.15g) = %.15g, want %.15g", vf[i], f, cos[i])
  1032. }
  1033. for _, i in vfcos_sc {
  1034. f := math.cos(vfcos_sc[i])
  1035. testing.expectf(t, alike(t, cos_sc[i], f), "math.cos(%.15g) = %.15g, want %.15g", vfcos_sc[i], f, cos_sc[i])
  1036. }
  1037. }
  1038. @test
  1039. test_cosh :: proc(t: ^testing.T) {
  1040. for _, i in vf {
  1041. f := math.cosh(vf[i])
  1042. testing.expectf(t, close(t, cosh[i], f), "math.cosh(%.15g) = %.15g, want %.15g", vf[i], f, cosh[i])
  1043. }
  1044. for _, i in vfcosh_sc {
  1045. f := math.cosh(vfcosh_sc[i])
  1046. testing.expectf(t, alike(t, cosh_sc[i], f), "math.cosh(%.15g) = %.15g, want %.15g", vfcosh_sc[i], f, cosh_sc[i])
  1047. }
  1048. }
  1049. @test
  1050. test_sin :: proc(t: ^testing.T) {
  1051. for _, i in vf {
  1052. f := math.sin(vf[i])
  1053. testing.expectf(t, veryclose(t, sin[i], f), "math.sin(%.15g) = %.15g, want %.15g", vf[i], f, sin[i])
  1054. }
  1055. for _, i in vfsin_sc {
  1056. f := math.sin(vfsin_sc[i])
  1057. testing.expectf(t, alike(t, sin_sc[i], f), "math.sin(%.15g) = %.15g, want %.15g", vfsin_sc[i], f, sin_sc[i])
  1058. }
  1059. }
  1060. @test
  1061. test_sinh :: proc(t: ^testing.T) {
  1062. for _, i in vf {
  1063. f := math.sinh(vf[i])
  1064. testing.expectf(t, close(t, sinh[i], f), "math.sinh(%.15g) = %.15g, want %.15g", vf[i], f, sinh[i])
  1065. }
  1066. for _, i in vfsinh_sc {
  1067. f := math.sinh(vfsinh_sc[i])
  1068. testing.expectf(t, alike(t, sinh_sc[i], f), "math.sinh(%.15g) = %.15g, want %.15g", vfsinh_sc[i], f, sinh_sc[i])
  1069. }
  1070. }
  1071. @test
  1072. test_sqrt :: proc(t: ^testing.T) {
  1073. for _, i in vf {
  1074. a := abs(vf[i])
  1075. f := math.sqrt(a)
  1076. testing.expectf(t, veryclose(t, sqrt[i], f), "math.sqrt(%.15g) = %.15g, want %.15g", a, f, sqrt[i])
  1077. }
  1078. }
  1079. @test
  1080. test_tan :: proc(t: ^testing.T) {
  1081. for _, i in vf {
  1082. f := math.tan(vf[i])
  1083. testing.expectf(t, veryclose(t, tan[i], f), "math.tan(%.15g) = %.15g, want %.15g", vf[i], f, tan[i])
  1084. }
  1085. // same special cases as Sin
  1086. for _, i in vfsin_sc {
  1087. f := math.tan(vfsin_sc[i])
  1088. testing.expectf(t, alike(t, sin_sc[i], f), "math.tan(%.15g) = %.15g, want %.15g", vfsin_sc[i], f, sin_sc[i])
  1089. }
  1090. }
  1091. @test
  1092. test_tanh :: proc(t: ^testing.T) {
  1093. for _, i in vf {
  1094. f := math.tanh(vf[i])
  1095. testing.expectf(t, veryclose(t, tanh[i], f), "math.tanh(%.15g) = %.15g, want %.15g", vf[i], f, tanh[i])
  1096. }
  1097. for _, i in vftanh_sc {
  1098. f := math.tanh(vftanh_sc[i])
  1099. testing.expectf(t, alike(t, tanh_sc[i], f), "math.tanh(%.15g) = %.15g, want %.15g", vftanh_sc[i], f, tanh_sc[i])
  1100. }
  1101. }
  1102. @test
  1103. test_large_cos :: proc(t: ^testing.T) {
  1104. large := f64(1e5 * Pi)
  1105. for _, i in vf {
  1106. f1 := cosLarge[i]
  1107. f2 := math.cos(vf[i] + large)
  1108. testing.expectf(t, close(t, f1, f2), "math.cos(%.15g) = %.15g, want %.15g", vf[i]+large, f2, f1)
  1109. }
  1110. }
  1111. @test
  1112. test_large_sin :: proc(t: ^testing.T) {
  1113. large := f64(1e5 * Pi)
  1114. for _, i in vf {
  1115. f1 := sinLarge[i]
  1116. f2 := math.sin(vf[i] + large)
  1117. testing.expectf(t, close(t, f1, f2), "math.sin(%.15g) = %.15g, want %.15g", vf[i]+large, f2, f1)
  1118. }
  1119. }
  1120. @test
  1121. test_large_tan :: proc(t: ^testing.T) {
  1122. large := f64(1e5 * Pi)
  1123. for _, i in vf {
  1124. f1 := tanLarge[i]
  1125. f2 := math.tan(vf[i] + large)
  1126. testing.expectf(t, close(t, f1, f2), "math.tan(%.15g) = %.15g, want %.15g", vf[i]+large, f2, f1)
  1127. }
  1128. }
  1129. @test
  1130. test_count_digits :: proc(t: ^testing.T) {
  1131. _run_test :: proc(t: ^testing.T, $base: int) {
  1132. buf: [64]u8
  1133. for n in 0..<i64(base*base*base) {
  1134. count := math.count_digits_of_base(n, base)
  1135. str := strconv.write_int(buf[:], n, base)
  1136. if !testing.expectf(t,
  1137. len(str) == count,
  1138. "decimal %i in base-%i digit count is %i, does not match length %i of %q",
  1139. n, base, count, len(str), str) {
  1140. break
  1141. }
  1142. }
  1143. }
  1144. _run_test(t, 2)
  1145. _run_test(t, 3)
  1146. _run_test(t, 4)
  1147. _run_test(t, 5)
  1148. _run_test(t, 6)
  1149. _run_test(t, 7)
  1150. _run_test(t, 8)
  1151. _run_test(t, 9)
  1152. _run_test(t, 10)
  1153. _run_test(t, 11)
  1154. _run_test(t, 12)
  1155. _run_test(t, 13)
  1156. _run_test(t, 14)
  1157. _run_test(t, 15)
  1158. _run_test(t, 16)
  1159. }
  1160. @test
  1161. test_nextafter :: proc(t: ^testing.T) {
  1162. Datum :: struct($F: typeid) {
  1163. x, y, r: F,
  1164. }
  1165. @static f16_data := [?]Datum(f16) {
  1166. {0h3c00, 0h7c42, 0h7e00}, // +1 -> +NaN = +canonical NaN
  1167. {0h3c00, 0hfc42, 0h7e00}, // +1 -> -NaN = +canonical NaN
  1168. {0hbc00, 0h7c42, 0h7e00}, // -1 -> +NaN = +canonical NaN
  1169. {0hbc00, 0hfc42, 0h7e00}, // -1 -> -NaN = +canonical NaN
  1170. {0h7c42, 0h3c00, 0h7e00}, // +NaN -> +1 = +canonical NaN
  1171. {0hfc42, 0h3c00, 0h7e00}, // -NaN -> +1 = +canonical NaN
  1172. {0h7c42, 0hbc00, 0h7e00}, // +NaN -> -1 = +canonical NaN
  1173. {0hfc42, 0hbc00, 0h7e00}, // -NaN -> -1 = +canonical NaN
  1174. {0h0000, 0h8000, 0h0000}, // +0 -> -0 = +0
  1175. {0h0000, +1, 0h0001}, // +0 -> +1 = +smallest subnormal
  1176. {0h0000, -1, 0h8001}, // +0 -> -1 = -smallest subnormal
  1177. {0h0000, 0h0000, 0h0000}, // +0 -> +0 = +0
  1178. {0h0000, 0h8000, 0h0000}, // +0 -> -0 = +0
  1179. {0h0000, +1, 0h0001}, // +0 -> +1 = +smallest subnormal
  1180. {0h0000, -1, 0h8001}, // +0 -> -1 = -smallest subnormal
  1181. {0h8000, 0h0000, 0h8000}, // -0 -> +0 = -0
  1182. {0h8000, 0h8000, 0h8000}, // -0 -> -0 = -0
  1183. {0h8000, +1, 0h0001}, // -0 -> +1 = +smallest subnormal
  1184. {0h8000, -1, 0h8001}, // -0 -> -1 = -smallest subnormal
  1185. {0h0001, -1, 0h0000}, // +smallest subnormal -> -1 = +0
  1186. {0h8001, +1, 0h8000}, // -smallest subnormal -> +1 = -0
  1187. {0h03ff, +1, 0h0400}, // +largest subnormal -> +1 = +smallest normal
  1188. {0h0400, -1, 0h03ff}, // +smallest normal -> -1 = +largest subnormal
  1189. {0h83ff, -1, 0h8400}, // -largest subnormal -> -1 = -smallest normal
  1190. {0h8400, +1, 0h83ff}, // -smallest normal -> +1 = -largest subnormal
  1191. {0h3c00, 0, 0h3bff}, // +1 -> 0 = +1-ulp
  1192. {0h3c00, +1, 0h3c00}, // +1 -> +1 = +1
  1193. {0h3c00, +2, 0h3c01}, // +1 -> +2 = +1+ulp
  1194. {0hbc00, 0, 0hbbff}, // -1 -> 0 = -1+ulp
  1195. {0hbc00, -1, 0hbc00}, // -1 -> -1 = -1
  1196. {0hbc00, -2, 0hbc01}, // -1 -> +2 = -1-ulp
  1197. {0h3c00, 0hfc00, 0h3bff}, // +1 -> -inf = +1-ulp
  1198. {0hbc00, 0h7c00, 0hbbff}, // -1 -> +inf = -1+ulp
  1199. {0h7bff, 0h7c00, 0h7c00}, // +max -> +inf = +inf
  1200. {0h7c00, 0h7c00, 0h7c00}, // +inf -> +inf = +inf
  1201. {0h7c00, 0, 0h7bff}, // +inf -> 0 = +max
  1202. {0hfbff, 0hfc00, 0hfc00}, // -max -> -inf = -inf
  1203. {0hfc00, 0hfc00, 0hfc00}, // -inf -> -inf = -inf
  1204. {0hfc00, 0, 0hfbff}, // -inf -> 0 = -max
  1205. }
  1206. for datum in f16_data {
  1207. r := math.nextafter_f16(datum.x, datum.y)
  1208. testing.expectf(t,
  1209. transmute(u16)r == transmute(u16)datum.r,
  1210. "%h, %h -> %h != %h", datum.x, datum.y, r, datum.r)
  1211. }
  1212. @(static, rodata)
  1213. f32_data := [?]Datum(f32) {
  1214. { +1, 0h7f842000, 0h7fc00000}, // +1 -> +NaN = +canonical NaN
  1215. { +1, 0hff842000, 0h7fc00000}, // +1 -> -NaN = +canonical NaN
  1216. { -1, 0h7f842000, 0h7fc00000}, // -1 -> +NaN = +canonical NaN
  1217. { -1, 0hff842000, 0h7fc00000}, // -1 -> -NaN = +canonical NaN
  1218. {0h7f842000, +1, 0h7fc00000}, // +NaN -> +1 = +canonical NaN
  1219. {0hff842000, +1, 0h7fc00000}, // -NaN -> +1 = +canonical NaN
  1220. {0h7f842000, -1, 0h7fc00000}, // +NaN -> -1 = +canonical NaN
  1221. {0hff842000, -1, 0h7fc00000}, // -NaN -> -1 = +canonical NaN
  1222. {0h00000000, 0h80000000, 0h00000000}, // +0 -> -0 = +0
  1223. {0h00000000, +1, 0h00000001}, // +0 -> +1 = +smallest subnormal
  1224. {0h00000000, -1, 0h80000001}, // +0 -> -1 = -smallest subnormal
  1225. {0h00000000, 0h00000000, 0h00000000}, // +0 -> +0 = +0
  1226. {0h00000000, 0h80000000, 0h00000000}, // +0 -> -0 = +0
  1227. {0h00000000, +1, 0h00000001}, // +0 -> +1 = +smallest subnormal
  1228. {0h00000000, -1, 0h80000001}, // +0 -> -1 = -smallest subnormal
  1229. {0h80000000, 0h00000000, 0h80000000}, // -0 -> +0 = -0
  1230. {0h80000000, 0h80000000, 0h80000000}, // -0 -> -0 = -0
  1231. {0h80000000, +1, 0h00000001}, // -0 -> +1 = +smallest subnormal
  1232. {0h80000000, -1, 0h80000001}, // -0 -> -1 = -smallest subnormal
  1233. {0h00000001, -1, 0h00000000}, // +smallest subnormal -> -1 = +0
  1234. {0h80000001, +1, 0h80000000}, // -smallest subnormal -> +1 = -0
  1235. {0h03ffffff, +1, 0h04000000}, // +largest subnormal -> +1 = +smallest normal
  1236. {0h04000000, -1, 0h03ffffff}, // +smallest normal -> -1 = +largest subnormal
  1237. {0h83ffffff, -1, 0h84000000}, // -largest subnormal -> -1 = -smallest normal
  1238. {0h84000000, +1, 0h83ffffff}, // -smallest normal -> +1 = -largest subnormal
  1239. {0h3f800000, 0, 0h3f7fffff}, // +1 -> 0 = +1-ulp
  1240. {0h3f800000, +1, 0h3f800000}, // +1 -> +1 = +1
  1241. {0h3f800000, +2, 0h3f800001}, // +1 -> +2 = +1+ulp
  1242. {0hbf800000, 0, 0hbf7fffff}, // -1 -> 0 = -1+ulp
  1243. {0hbf800000, -1, 0hbf800000}, // -1 -> -1 = -1
  1244. {0hbf800000, -2, 0hbf800001}, // -1 -> +2 = -1-ulp
  1245. {0h3c000000, 0hfc000000, 0h3bffffff}, // +1 -> -inf = +1-ulp
  1246. {0hbc000000, 0h7c000000, 0hbbffffff}, // -1 -> +inf = -1+ulp
  1247. {0h7bffffff, 0h7c000000, 0h7c000000}, // +max -> +inf = +inf
  1248. {0h7c000000, 0h7c000000, 0h7c000000}, // +inf -> +inf = +inf
  1249. {0h7c000000, 0, 0h7bffffff}, // +inf -> 0 = +max
  1250. {0hfbffffff, 0hfc000000, 0hfc000000}, // -max -> -inf = -inf
  1251. {0hfc000000, 0hfc000000, 0hfc000000}, // -inf -> -inf = -inf
  1252. {0hfc000000, 0, 0hfbffffff}, // -inf -> 0 = -max
  1253. }
  1254. for datum in f32_data {
  1255. r := math.nextafter_f32(datum.x, datum.y)
  1256. testing.expectf(t,
  1257. transmute(u32)r == transmute(u32)datum.r,
  1258. "%h, %h -> %h != %h", datum.x, datum.y, r, datum.r)
  1259. }
  1260. @(static, rodata)
  1261. f64_data := [?]Datum(f64) {
  1262. {0h3c00000000000000, 0h7ff4200000000000, 0h7ff8000000000001}, // +1 -> +NaN = +canonical NaN
  1263. {0h3c00000000000000, 0hfff4200000000000, 0h7ff8000000000001}, // +1 -> -NaN = +canonical NaN
  1264. {0hbc00000000000000, 0h7ff4200000000000, 0h7ff8000000000001}, // -1 -> +NaN = +canonical NaN
  1265. {0hbc00000000000000, 0hfff4200000000000, 0h7ff8000000000001}, // -1 -> -NaN = +canonical NaN
  1266. {0h7ff4200000000000, 0h3c00000000000000, 0h7ff8000000000001}, // +NaN -> +1 = +canonical NaN
  1267. {0hfff4200000000000, 0h3c00000000000000, 0h7ff8000000000001}, // -NaN -> +1 = +canonical NaN
  1268. {0h7ff4200000000000, 0hbc00000000000000, 0h7ff8000000000001}, // +NaN -> -1 = +canonical NaN
  1269. {0hfff4200000000000, 0hbc00000000000000, 0h7ff8000000000001}, // -NaN -> -1 = +canonical NaN
  1270. {0h0000000000000000, 0h8000000000000000, 0h0000000000000000}, // +0 -> -0 = +0
  1271. {0h0000000000000000, +1, 0h0000000000000001}, // +0 -> +1 = +smallest subnormal
  1272. {0h0000000000000000, -1, 0h8000000000000001}, // +0 -> -1 = -smallest subnormal
  1273. {0h0000000000000000, 0h0000000000000000, 0h0000000000000000}, // +0 -> +0 = +0
  1274. {0h0000000000000000, 0h8000000000000000, 0h0000000000000000}, // +0 -> -0 = +0
  1275. {0h0000000000000000, +1, 0h0000000000000001}, // +0 -> +1 = +smallest subnormal
  1276. {0h0000000000000000, -1, 0h8000000000000001}, // +0 -> -1 = -smallest subnormal
  1277. {0h8000000000000000, 0h0000000000000000, 0h8000000000000000}, // -0 -> +0 = -0
  1278. {0h8000000000000000, 0h8000000000000000, 0h8000000000000000}, // -0 -> -0 = -0
  1279. {0h8000000000000000, +1, 0h0000000000000001}, // -0 -> +1 = +smallest subnormal
  1280. {0h8000000000000000, -1, 0h8000000000000001}, // -0 -> -1 = -smallest subnormal
  1281. {0h0000000000000001, -1, 0h0000000000000000}, // +smallest subnormal -> -1 = +0
  1282. {0h8000000000000001, +1, 0h8000000000000000}, // -smallest subnormal -> +1 = -0
  1283. {0h03ffffffffffffff, +1, 0h0400000000000000}, // +largest subnormal -> +1 = +smallest normal
  1284. {0h0400000000000000, -1, 0h03ffffffffffffff}, // +smallest normal -> -1 = +largest subnormal
  1285. {0h83ffffffffffffff, -1, 0h8400000000000000}, // -largest subnormal -> -1 = -smallest normal
  1286. {0h8400000000000000, +1, 0h83ffffffffffffff}, // -smallest normal -> +1 = -largest subnormal
  1287. {0h3ff0000000000000, 0, 0h3fefffffffffffff}, // +1 -> 0 = +1-ulp
  1288. {0h3ff0000000000000, +1, 0h3ff0000000000000}, // +1 -> +1 = +1
  1289. {0h3ff0000000000000, +2, 0h3ff0000000000001}, // +1 -> +2 = +1+ulp
  1290. {0hbff0000000000000, 0, 0hbfefffffffffffff}, // -1 -> 0 = -1+ulp
  1291. {0hbff0000000000000, -1, 0hbff0000000000000}, // -1 -> -1 = -1
  1292. {0hbff0000000000000, -2, 0hbff0000000000001}, // -1 -> +2 = -1-ulp
  1293. {0h3ff0000000000000, 0hfff0000000000000, 0h3fefffffffffffff}, // +1 -> -inf = +1-ulp
  1294. {0hbff0000000000000, 0h7ff0000000000000, 0hbfefffffffffffff}, // -1 -> +inf = -1+ulp
  1295. {0h7fefffffffffffff, 0h7ff0000000000000, 0h7ff0000000000000}, // +max -> +inf = +inf
  1296. {0h7ff0000000000000, 0h7ff0000000000000, 0h7ff0000000000000}, // +inf -> +inf = +inf
  1297. {0h7ff0000000000000, 0, 0h7fefffffffffffff}, // +inf -> 0 = +max
  1298. {0hffefffffffffffff, 0hfff0000000000000, 0hfff0000000000000}, // -max -> -inf = -inf
  1299. {0hfff0000000000000, 0hfff0000000000000, 0hfff0000000000000}, // -inf -> -inf = -inf
  1300. {0hfff0000000000000, 0, 0hffefffffffffffff}, // -inf -> 0 = -max
  1301. }
  1302. for datum in f64_data {
  1303. r := math.nextafter_f64(datum.x, datum.y)
  1304. testing.expectf(t,
  1305. transmute(u64)r == transmute(u64)datum.r,
  1306. "%h, %h -> %h != %h", datum.x, datum.y, r, datum.r)
  1307. }
  1308. }