ref: 90d9a10c0234f5868c2e86882aae72fc931d53fd
dir: /lib/math/tan-impl.myr/
use std use "fpmath" /* We need trig_reduce only. */ use "sin-impl" use "util" /* See sin-impl.myr, this implementation is a very close copy; [GB91] provides the guide for implementation. As with sin and cos, our polynomials are of lower degree, and we restrict the polynomial approximation to a smaller range than in [GB91]. See files pi-constants.c, generate-triples-for-GB91.c, and generate-minimax-by-Remez.gp for where the constants come from. */ pkg math = pkglocal const tan32 : (x : flt32 -> flt32) pkglocal const tan64 : (x : flt64 -> flt64) pkglocal const cot32 : (x : flt32 -> flt32) pkglocal const cot64 : (x : flt64 -> flt64) ;; /* Coefficients for minimax polynomial approximating p(x), with tan(x) = x*p(x^2), expanding out to a degree 7 polynomial for tan(x). */ const tan_coeff : uint64[4] = [ 0x3ff0000000000000, 0x3fd5555555555555, 0x3fc1111111111111, 0x3faba1c7ec067952, ] /* Coefficients for minimax polynomial approximating p(x), with cot(x) = p(x^2)/x, expanding to a degree 7 polynomial for cot(x). */ const cot_coeff : uint64[5] = [ 0x3ff0000000000000, 0xbfd5555555555555, 0xbf96c16c16c16c17, 0xbf61566abc00f016, 0xbf2bbd7be567ea80, ] /* Coefficients for a minimax polynomial approximating p(x), with tan(x) = x*p(x^2), expanding out to a degree 11 polynomial for tan(x). This is slower than the tan_coeff version and overkill for the typical range of delta. */ const tan_coeff_good : uint64[6] = [ 0x3ff0000000000000, 0x3fd5555555555557, 0x3fc1111111124b1b, 0x3faba1ba5c206e2d, 0x3f96660414be66b8, 0x3f829ece970a9ba2, ] /* Split 21 zeros out, for special cot() computation */ const split_mask : uint64 = 0xffffffffffffffff << 21 /* The Highly Accurate Tables for use in a [GB91]-type algorithm; generated by ancillary/generate-triples-for-GB91.c. Note the 0th entry has infinite cotangent: we have to specially handle arguments close to 0 to avoid inf pollution. */ const C : (uint64, uint64, uint64)[257] = [ /* xi cot(xi) tan(xi) */ (0x0000000000000000, 0x7ff0000000000000, 0x0000000000000000), (0x3f6921fb43c5e5fb, 0x40745f2c4ad38437, 0x3f6922006eb65bc4), (0x3f7921fb69404898, 0x40645f1f9b724978, 0x3f7922101511c956), (0x3f82d97c65697c99, 0x405b2963c8d7c55e, 0x3f82d99f4785288e), (0x3f8921fb51371df1, 0x40545eed6acdf109, 0x3f89224e01710949), (0x3f8f6a7a2c57dd2f, 0x40504bd2f5b9fc24, 0x3f8f6b1badf01256), (0x3f92d97c892e0401, 0x404b28ccc8515f8d, 0x3f92da0815417fe7), (0x3f95fdbbfe00c048, 0x4047474caf184945, 0x3f95fe99994b31ca), (0x3f9921fb362e82a0, 0x40445e246e48a7ee, 0x3f9923460660434c), (0x3f9c463aa05ba8df, 0x40421a8bbcf0d59c, 0x3f9c4811ad83840e), (0x3f9f6a7a32fd798b, 0x40404ad799698985, 0x3f9f6d0068177f47), (0x3fa1475cadce672e, 0x403d9ed9b607478d, 0x3fa1490ac38b33a8), (0x3fa2d97c804f3e96, 0x403b267194186780, 0x3fa2dbaaeabcdd1f), (0x3fa46b9c34e4ab15, 0x40390f4a6551abeb, 0x3fa46e623ffdc4da), (0x3fa5fdbbfbcb8cbd, 0x4037448cde3bdf75, 0x3fa60132e6a3c57c), (0x3fa78fdba272466d, 0x4035b6f0dc2e1d02, 0x3fa7941e9f8a200e), (0x3fa921fb46f590b9, 0x40345afff7eb9ed9, 0x3fa927277ce43c43), (0x3faab41af9b5a4a1, 0x403327f64d5ddbe8, 0x3faaba4f83b868b9), (0x3fac463aa15aa204, 0x40321702ba17ae76, 0x3fac4d988fd3c37d), (0x3fadd85a541eb1e6, 0x403122c3623e77ea, 0x3fade104ad5a19ae), (0x3faf6a7a28fb8b3c, 0x403046e9fe8f3bcb, 0x3faf7495e9e533ba), (0x3fb07e4cd90f69c4, 0x402efff4fb017e86, 0x3fb08426e73b18e9), (0x3fb1475ccf08bc32, 0x402d9634f7939f69, 0x3fb14e17812554ba), (0x3fb2106c9ca80bcd, 0x402c4bde69326818, 0x3fb2181d64f21f1e), (0x3fb2d97c6e8f0d99, 0x402b1d03d8431e54, 0x3fb2e239bc43f5ea), (0x3fb3a28c5e9cda74, 0x402a0658d1258f8a, 0x3fb3ac6d9e61f454), (0x3fb46b9c1af1ca7b, 0x40290513541f6bae, 0x3fb476b9b6a5b103), (0x3fb534abf74c4f86, 0x402816d25c8e2911, 0x3fb5411f577b5e4b), (0x3fb5fdbbe76972c5, 0x4027398c5a6a94ca, 0x3fb60b9f7341612c), (0x3fb6c6cbcafad5b1, 0x40266b7fbfc9a854, 0x3fb6d63ae89faaee), (0x3fb78fdb9c7d39ab, 0x4025ab26d260cbba, 0x3fb7a0f2b1ba77b4), (0x3fb858eb82b930eb, 0x4024f72dfaa05197, 0x3fb86bc7f5f32f7d), (0x3fb921fb549b731e, 0x40244e6c591405be, 0x3fb936bb8cb34c63), (0x3fb9eb0b2e8adcf9, 0x4023afdcd1160af4, 0x3fba01ce94149e0a), (0x3fbab41b1e68f64c, 0x40231a990b29843b, 0x3fbacd021c321ede), (0x3fbb7d2ad90eb4c1, 0x40228dd5408b39fd, 0x3fbb9856dbc170d0), (0x3fbc463aa9e0e6e1, 0x402208dbe8546fd1, 0x3fbc63ce22521e17), (0x3fbd0f4a9ed6ac6b, 0x40218b0b447a840e, 0x3fbd2f69021ade8d), (0x3fbdd85a6a1e3500, 0x402113d2d3340c0f, 0x3fbdfb283104590b), (0x3fbea16a43111eb3, 0x4020a2b0974c728d, 0x3fbec70cec8d28e2), (0x3fbf6a7a152ae159, 0x4020372fbdef0db6, 0x3fbf93182614dae9), (0x3fc019c5091530ae, 0x401fa1cd6c211be1, 0x3fc02fa58b882864), (0x3fc07e4cd60bb2ac, 0x401edeecb2e792c1, 0x3fc095d31b7ab15a), (0x3fc0e2d4f9759641, 0x401e250f354f8dbe, 0x3fc0fc15d1664ec5), (0x3fc1475ccb271aea, 0x401d7398cf43b80c, 0x3fc1626d86e71cc7), (0x3fc1abe4ae6b768f, 0x401cc9f96a972d15, 0x3fc1c8db2614cbc0), (0x3fc2106c905dda31, 0x401c27ae41d1edd4, 0x3fc22f5f2139f59d), (0x3fc274f4896db29e, 0x401b8c3f6c6a4a71, 0x3fc295fa1740027b), (0x3fc2d97c6d32e764, 0x401af73f66c3ead4, 0x3fc2fcac61406613), (0x3fc33e045f0619c2, 0x401a6849297d859a, 0x3fc36376aa36e713), (0x3fc3a28c3a37c404, 0x4019df00269fbec5, 0x3fc3ca5953fa7c1a), (0x3fc407144075ebd8, 0x40195b0e8afc5158, 0x3fc4315529a44c20), (0x3fc46b9c2c6b4a28, 0x4018dc25cb0e86a9, 0x3fc4986a6c8dde38), (0x3fc4d02440498d08, 0x401861fca0c2727d, 0x3fc4ff99e978d677), (0x3fc534ac1fd87d02, 0x4017ec4fef47d5ac, 0x3fc566e3cb1ac3b8), (0x3fc59933e96f8d02, 0x40177ae0ebe39dcb, 0x3fc5ce48ba6cbc8c), (0x3fc5fdbbe79e8588, 0x40170d751b4b5351, 0x3fc635c98ea0a06e), (0x3fc66243c3de5553, 0x4016a3d6c893e89c, 0x3fc69d6679ac9090), (0x3fc6c6cbd97ff2eb, 0x40163dd33b7cd8a1, 0x3fc70520654e8fbc), (0x3fc72b53b2dfa886, 0x4015db3bfb9718c5, 0x3fc76cf7644f5456), (0x3fc78fdba07a2b15, 0x40157be4e94511b4, 0x3fc7d4ec5682b6ec), (0x3fc7f4639158cb7b, 0x40151fa5267b1359, 0x3fc83cffb7c5bd13), (0x3fc858eb5d585717, 0x4014c6568b6182c0, 0x3fc8a531ec767b5b), (0x3fc8bd735284b4b1, 0x40146fd4f60aa6ea, 0x3fc90d83d41787e6), (0x3fc921fb44d8c003, 0x40141bfeeeeb615b, 0x3fc975f5d04d9510), (0x3fc986833b7f08e5, 0x4013cab4e2b1ea03, 0x3fc9de8878736efe), (0x3fc9eb0b3ba4fca5, 0x40137bd929ce2e37, 0x3fca473c62857446), (0x3fca4f9336067d8d, 0x40132f4ff1744efc, 0x3fcab0120fe01a1b), (0x3fcab41b018ad3ad, 0x4012e4ff1bf8fe76, 0x3fcb1909e77f6d3f), (0x3fcb18a2f15fe343, 0x40129ccdb5a1a27c, 0x3fcb8224d2de4be1), (0x3fcb7d2ae4498be8, 0x401256a48b1995d8, 0x3fcbeb6342b07ca5), (0x3fcbe1b2c39aaa4c, 0x4012126daf49101c, 0x3fcc54c5b349b00d), (0x3fcc463acb8ca010, 0x4011d01436249f34, 0x3fccbe4cf8afd08f), (0x3fccaac2bf18961b, 0x40118f84a7fdac06, 0x3fcd27f968798e0c), (0x3fcd0f4a797c05fe, 0x401150ac8980c6bc, 0x3fcd91cb72380077), (0x3fcd73d270bdc038, 0x40111379fd8fc155, 0x3fcdfbc42953c563), (0x3fcdd85a6542243b, 0x4010d7dc85aa36a5, 0x3fce65e3e2d8019c), (0x3fce3ce24380c9db, 0x40109dc463970d1f, 0x3fced02b22de7ced), (0x3fcea16a4eb76e81, 0x4010652276f8722a, 0x3fcf3a9aca25e284), (0x3fcf05f225fcc8fc, 0x40102de8be5f5e9b, 0x3fcfa5330c823e20), (0x3fcf6a7a2e7e6f81, 0x400ff01300763015, 0x3fd007fa78443530), (0x3fcfcf021570cd37, 0x400f86f024238a5e, 0x3fd03d705d41a70c), (0x3fd019c4e66f72bd, 0x400f205085a9838c, 0x3fd072fb7c3be48f), (0x3fd04c08e54cf113, 0x400ebc1c6d564497, 0x3fd0a89c62f5e593), (0x3fd07e4ceb3a2775, 0x400e5a3df148f481, 0x3fd0de53430437af), (0x3fd0b090d14d1132, 0x400dfaa0416fb320, 0x3fd1142042a947fe), (0x3fd0e2d4e9b68203, 0x400d9d2ea3b4f2db, 0x3fd14a040a4c0488), (0x3fd11518dadb07fc, 0x400d41d68d4614b2, 0x3fd17ffe8abf93f8), (0x3fd1475cabbbd1a5, 0x400ce8859a42336f, 0x3fd1b6101cb2785a), (0x3fd179a0b7f1e7a4, 0x400c9129a990cfbb, 0x3fd1ec3974987375), (0x3fd1abe4b50fd9a0, 0x400c3bb2863ab5e2, 0x3fd2227a94b976bd), (0x3fd1de28a830b251, 0x400be8102968bfac, 0x3fd258d3d564ded0), (0x3fd2106ca9bf313e, 0x400b96331fe26d7e, 0x3fd28f45a4688f6e), (0x3fd242b0b89d73ec, 0x400b460cca6bd89f, 0x3fd2c5d0548f5454), (0x3fd274f47ec75990, 0x400af78fac257637, 0x3fd2fc73dccd4043), (0x3fd2a738a04751ef, 0x400aaaad59bb9e25, 0x3fd3333144835986), (0x3fd2d97c85bb113f, 0x400a5f59df55d5a8, 0x3fd36a083c7e2ced), (0x3fd30bc06f220a02, 0x400a1588855353e2, 0x3fd3a0f96085b6dd), (0x3fd33e046e3c6329, 0x4009cd2d5e7d9094, 0x3fd3d8051ac8b850), (0x3fd370486fc1fac0, 0x4009863d2da63ac8, 0x3fd40f2bad85dbce), (0x3fd3a28c45f65785, 0x400940ad4be7678c, 0x3fd4466d3e4e392f), (0x3fd3d4d04d809c18, 0x4008fc72c1faf287, 0x3fd47dca8b7b83b2), (0x3fd407143dded9c0, 0x4008b983e519bfd8, 0x3fd4b5439e5d1536), (0x3fd439583676eabf, 0x400877d6e093e9da, 0x3fd4ecd8f3427dcc), (0x3fd46b9c4f298d45, 0x400837624b870e31, 0x3fd5248aff0c1bb9), (0x3fd49de0389dbfc9, 0x4007f81d9a994879, 0x3fd55c59c4bc190f), (0x3fd4d02415978a87, 0x4007ba0005be9705, 0x3fd59445c6583fea), (0x3fd502680d976ddd, 0x40077d0114c36575, 0x3fd5cc4f8c28a849), (0x3fd534ac009ad6ad, 0x40074118f5d5a027, 0x3fd604774f854e2e), (0x3fd566effa9677a1, 0x4007063fec410192, 0x3fd63cbd7b6d7874), (0x3fd59933e0e9ba24, 0x4006cc6eafc7e66d, 0x3fd675225058af7c), (0x3fd5cb77eb6b2450, 0x4006939dddeba442, 0x3fd6ada66c018e76), (0x3fd5fdbbdfcd5e78, 0x40065bc6d77251ea, 0x3fd6e649eca3c379), (0x3fd62ffff08a2e0c, 0x400624e2c13b5a9b, 0x3fd71f0d6b9a2d05), (0x3fd66243f23b0c45, 0x4005eeeb636b3b0e, 0x3fd757f1191ef14c), (0x3fd69487b10a42f2, 0x4005b9dac4d6f74e, 0x3fd790f51c268135), (0x3fd6c6cbae457fb1, 0x400585aa64d56be0, 0x3fd7ca1a6a0740e5), (0x3fd6f90fbd5ea7f3, 0x40055254afeb627f, 0x3fd8036133dcb0d0), (0x3fd72b539c1458e5, 0x40051fd4572bd740, 0x3fd83cc99243b1cc), (0x3fd75d97a0772b20, 0x4004ee23a1eecaf5, 0x3fd876544c81706d), (0x3fd78fdba1490a6d, 0x4004bd3d85c95693, 0x3fd8b001995400f4), (0x3fd7c21f93c9a6f0, 0x40048d1d04c633fd, 0x3fd8e9d1d2f476b5), (0x3fd7f463804f4cfb, 0x40045dbd38ab6945, 0x3fd923c56a5915d6), (0x3fd826a7892f6d44, 0x40042f194c51167e, 0x3fd95ddcef7a54f2), (0x3fd858eb80c2f052, 0x4004012cdbe1f350, 0x3fd9981896c629e4), (0x3fd88b2f737b7ea4, 0x4003d3f372664ef1, 0x3fd9d278d890d001), (0x3fd8bd735b872d13, 0x4003a768cf7d7edb, 0x3fda0cfe18e865e8), (0x3fd8efb749b5b0fa, 0x40037b88c14a0190, 0x3fda47a8d71f4a59), (0x3fd921fb4f73c582, 0x4003504f375b8a3b, 0x3fda827994591520), (0x3fd9543f498e072b, 0x400325b86e2a7edc, 0x3fdabd70950976a6), (0x3fd986833cb12fe2, 0x4002fbc09df08da7, 0x3fdaf88e4d1af906), (0x3fd9b8c735da9e8f, 0x4002d26415c0dcf8, 0x3fdb33d33b48b23c), (0x3fd9eb0b2b14f6b2, 0x4002a99f541052bd, 0x3fdb6f3fc4412f63), (0x3fda1d4f1f259ed7, 0x4002816ee7faf9c9, 0x3fdbaad45ca7ae2f), (0x3fda4f9317d51314, 0x400259cf78974618, 0x3fdbe6917dba0bac), (0x3fda81d71d9a00d3, 0x400232bdc46748af, 0x3fdc2277a4fbcf04), (0x3fdab41b1864b159, 0x40020c36bb584296, 0x3fdc5e872a26269b), (0x3fdae65f0eadda20, 0x4001e6374cd17a1a, 0x3fdc9ac08a4bd320), (0x3fdb18a2f6bdb980, 0x4001c0bc8b1148ee, 0x3fdcd724302664c9), (0x3fdb4ae6f429a87d, 0x40019bc37c9e36a0, 0x3fdd13b2be0455c5), (0x3fdb7d2adbb2f0d4, 0x400177497734de95, 0x3fdd506c786465b9), (0x3fdbaf6ee37914fd, 0x4001534b9ddfc460, 0x3fdd8d521a67ad8d), (0x3fdbe1b2dd912d13, 0x40012fc76f757964, 0x3fddca63e75202cb), (0x3fdc13f6cc9e4889, 0x40010cba5a491b0c, 0x3fde07a25e238018), (0x3fdc463ad9174142, 0x4000ea21c51caa0c, 0x3fde450e2d5365b9), (0x3fdc787e9c84e6c4, 0x4000c7fb8a2ba964, 0x3fde82a755ab4856), (0x3fdcaac2926527ca, 0x4000a644fa83f84e, 0x3fdec06eedc91cd2), (0x3fdcdd06a43ce130, 0x400084fbdbdf1711, 0x3fdefe655b10819e), (0x3fdd0f4a88e8826e, 0x4000641e23e987e1, 0x3fdf3c8ac50fd12d), (0x3fdd418e8374c347, 0x400043a97b437c0b, 0x3fdf7ae00195ead5), (0x3fdd73d27c65ab26, 0x4000239bd4e2229d, 0x3fdfb96577e9d701), (0x3fdda6167d37836d, 0x400003f31ca39f94, 0x3fdff81bb96f0bef), (0x3fddd85a68c19b42, 0x3fffc95ac8d38084, 0x3fe01b81944403fa), (0x3fde0a9e587b4fd8, 0x3fff8b91526e80e7, 0x3fe03b0e368fb566), (0x3fde3ce26298b772, 0x3fff4e85ef7772cc, 0x3fe05ab4165d6dbe), (0x3fde6f26438b72e7, 0x3fff12353eaec03d, 0x3fe07a734e81ae40), (0x3fdea16a54d3b255, 0x3ffed69b3a1ab4c7, 0x3fe09a4c5da07b69), (0x3fded3ae2f825dc7, 0x3ffe9bb4d86851dd, 0x3fe0ba3f4945c2d6), (0x3fdf05f21cdb9169, 0x3ffe617e5679952d, 0x3fe0da4c8763cb70), (0x3fdf38363eaf5154, 0x3ffe27f4381597d6, 0x3fe0fa7475f5d590), (0x3fdf6a7a098dc074, 0x3ffdef13dafcc870, 0x3fe11ab7049a4fea), (0x3fdf9cbe1c32adf4, 0x3ffdb6d95ebfe258, 0x3fe13b14e2ceeb4a), (0x3fdfcf01fc1a98f2, 0x3ffd7f4234582037, 0x3fe15b8e0c2a1e89), (0x3fe000a30caf6ef5, 0x3ffd484adae8622e, 0x3fe17c23144ba5c9), (0x3fe019c503e450d1, 0x3ffd11f0d6c93084, 0x3fe19cd4010aead7), (0x3fe032e705d8ff9a, 0x3ffcdc30fd97dc6d, 0x3fe1bda14b7f7db5), (0x3fe04c08e5135e13, 0x3ffca708e170a297, 0x3fe1de8b05a932bb), (0x3fe0652af2ed30d5, 0x3ffc7275198adb9d, 0x3fe1ff91e87789c0), (0x3fe07e4ce6bf0049, 0x3ffc3e7392215303, 0x3fe220b5e3b802d7), (0x3fe0976f08fafefc, 0x3ffc0b0119a5b475, 0x3fe241f7a70e93a4), (0x3fe0b090df3a9868, 0x3ffbd81c1d0ca878, 0x3fe26356e120198a), (0x3fe0c9b2ead68147, 0x3ffba5c118435eb7, 0x3fe284d48f30abf1), (0x3fe0e2d4dd7a7e38, 0x3ffb73ee3a8bbffd, 0x3fe2a6709b9c98c5), (0x3fe0fbf6ec9a1e2c, 0x3ffb42a0b9cabf46, 0x3fe2c82ba151a704), (0x3fe11518d95be884, 0x3ffb11d6bed203fe, 0x3fe2ea05a03d2b1c), (0x3fe12e3acb91e4cc, 0x3ffae18db6b570dc, 0x3fe30bff230686f5), (0x3fe1475cd97c8037, 0x3ffab1c3401e1903, 0x3fe32e189e288a82), (0x3fe1607ecb17c3cc, 0x3ffa82759ac22a53, 0x3fe350521cba4339), (0x3fe179a0be38d76d, 0x3ffa53a26f5af984, 0x3fe372ac1f34797e), (0x3fe192c2b4ff17e0, 0x3ffa2547a7d6b75e, 0x3fe39527018c28f4), (0x3fe1abe4a9d366b4, 0x3ff9f763480dbddc, 0x3fe3b7c316198532), (0x3fe1c506b8926f4d, 0x3ff9c9f322aecbea, 0x3fe3da80de6b2be4), (0x3fe1de289627ee62, 0x3ff99cf5cedc0b11, 0x3fe3fd604e8e3dcd), (0x3fe1f74aa0f1e663, 0x3ff97068be5efcbc, 0x3fe4206246783e1e), (0x3fe2106cc47cbcd5, 0x3ff9444a3c9eec82, 0x3fe4438708557940), (0x3fe2298e9b74941b, 0x3ff9189929b725cd, 0x3fe466ce653433d7), (0x3fe242b0875b781e, 0x3ff8ed53144242d5, 0x3fe48a3945bd5bdc), (0x3fe25bd2a2ef236a, 0x3ff8c276131e7537, 0x3fe4adc83188d315), (0x3fe274f49cd2ff63, 0x3ff89800fe076bc9, 0x3fe4d17b180d8e25), (0x3fe28e16910c215f, 0x3ff86df1fa8545fa, 0x3fe4f552845a769c), (0x3fe2a7387dfc7bb2, 0x3ff8444769c189a7, 0x3fe5194ed8c26526), (0x3fe2c05a7c12d2de, 0x3ff81aff8aec0241, 0x3fe53d709e4082fa), (0x3fe2d97c7c743349, 0x3ff7f218e6cd24d9, 0x3fe561b826bf35d4), (0x3fe2f29e9716e420, 0x3ff7c991cf39c7a9, 0x3fe58625fd66563d), (0x3fe30bc06e7f4a84, 0x3ff7a1695a457c1d, 0x3fe5aaba03e29b8c), (0x3fe324e27374f758, 0x3ff7799d5b5545db, 0x3fe5cf7548f044c5), (0x3fe33e047e936633, 0x3ff7522ca19d9740, 0x3fe5f457ff83db15), (0x3fe35726746c3aee, 0x3ff72b15ef009b93, 0x3fe619626c900682), (0x3fe3704880dc13de, 0x3ff704579db64f16, 0x3fe63e953f64e98f), (0x3fe3896a79a01dfd, 0x3ff6ddf094709c2e, 0x3fe663f0a979932c), (0x3fe3a28c5a0ef0b4, 0x3ff6b7df85cf5700, 0x3fe6897514cb6700), (0x3fe3bbae72257473, 0x3ff69222ac668190, 0x3fe6af236bc6b21d), (0x3fe3d4d05198d166, 0x3ff66cb96a79e48f, 0x3fe6d4fb7a2ab498), (0x3fe3edf2390d7a1b, 0x3ff647a21ef19a42, 0x3fe6fafe165c04e5), (0x3fe4071446b9849f, 0x3ff622db64677758, 0x3fe7212be57c166b), (0x3fe4203660cc90a3, 0x3ff5fe642df6afa6, 0x3fe74785394a80fe), (0x3fe4395830f053c5, 0x3ff5da3bca164098, 0x3fe76e0a075c1f61), (0x3fe4527a51ef6abd, 0x3ff5b6603251fdeb, 0x3fe794bbb8782811), (0x3fe46b9c35efc871, 0x3ff592d10f30a380, 0x3fe7bb99ef70fcb0), (0x3fe484be1da35a2f, 0x3ff56f8ce774b6cf, 0x3fe7e2a58e4d7f2c), (0x3fe49de0204a38f7, 0x3ff54c9283b95dee, 0x3fe809df39ac0a62), (0x3fe4b70222176b17, 0x3ff529e0f9169404, 0x3fe83147483ce15a), (0x3fe4d02423eab88d, 0x3ff50777396a8b69, 0x3fe858de3ecfe279), (0x3fe4e9460a6bd40d, 0x3ff4e55461ce669f, 0x3fe880a47725d222), (0x3fe50268221eb1c5, 0x3ff4c37707b189e0, 0x3fe8a89af16b273d), (0x3fe51b8a1a015c9e, 0x3ff4a1de9a4d2715, 0x3fe8d0c1b5967d2c), (0x3fe534abef35b431, 0x3ff4808a22df6aeb, 0x3fe8f91948a87d95), (0x3fe54dce0e654a86, 0x3ff45f781cf2f1af, 0x3fe921a2e5a509da), (0x3fe566effca9d1d5, 0x3ff43ea83a204e02, 0x3fe94a5e54941ccd), (0x3fe58011f1e2647b, 0x3ff41e1944ab750f, 0x3fe9734c7f58c26c), (0x3fe59933f5e86301, 0x3ff3fdca4ada27bb, 0x3fe99c6e04b5c577), (0x3fe5b2560aab7515, 0x3ff3ddba66ec8460, 0x3fe9c5c37bdd6320), (0x3fe5cb77e480bb2a, 0x3ff3bde919244f1b, 0x3fe9ef4cfd75f328), (0x3fe5e499d2fe12b9, 0x3ff39e552085ea71, 0x3fea190ba428e394), (0x3fe5fdbbd711540c, 0x3ff37efda4b7da0b, 0x3fea43000ba79067), (0x3fe616dde7b3195c, 0x3ff35fe1dd7a4fd0, 0x3fea6d2ac0ff2200), (0x3fe62fffe292e013, 0x3ff3410124e06ee8, 0x3fea978c284b69e9), (0x3fe64921d3354ae1, 0x3ff3225a9fb1c71e, 0x3feac224f47e4717), (0x3fe66243d9450683, 0x3ff303ed5e631dff, 0x3feaecf5fd84dff9), (0x3fe67b65c258c493, 0x3ff2e5b8d84a4bf9, 0x3feb17ff91b6c931), (0x3fe69487ced483eb, 0x3ff2c7bbfde79a7d, 0x3feb4342c6025af0), (0x3fe6ada9d635f2e4, 0x3ff2a9f641170b2e, 0x3feb6ebffdf58dac), (0x3fe6c6cbb61f0b15, 0x3ff28c670e616749, 0x3feb9a77a8b3dd2c), (0x3fe6dfedafa2adc5, 0x3ff26f0d60a506c4, 0x3febc66ae4d5e2a0), (0x3fe6f90fbe78ac86, 0x3ff251e88829ec96, 0x3febf29a5b89d1cc), (0x3fe71231ac5b981e, 0x3ff234f81179eb17, 0x3fec1f065fb7e3ae), (0x3fe72b539a5b2817, 0x3ff2183b26da1bf7, 0x3fec4bafe056a3e8), (0x3fe74475a88b9513, 0x3ff1fbb0f7a7f5d2, 0x3fec7897ce6c8a57), (0x3fe75d979d84d1b4, 0x3ff1df591bae6879, 0x3feca5be7daa52f0), (0x3fe776b996729f58, 0x3ff1c332cb1b268b, 0x3fecd324def80a12), (0x3fe78fdbb6c61400, 0x3ff1a73d3acc02d5, 0x3fed00cbf2860934), (0x3fe7a8fd8e5473ec, 0x3ff18b7845e8ff44, 0x3fed2eb3ae59bf1f), (0x3fe7c21fa821e9ae, 0x3ff16fe2b42697c2, 0x3fed5cddd5595691), (0x3fe7db419cad411c, 0x3ff1547c5b66dd8f, 0x3fed8b4a71c71e74), (0x3fe7f4638e3011f5, 0x3ff139447c65650b, 0x3fedb9fa8d11c553), (0x3fe80d858178d451, 0x3ff11e3a7adfe5dc, 0x3fede8eefdefdd61), (0x3fe826a79a4bde87, 0x3ff1035d9c2731dc, 0x3fee1828d8aa0d05), (0x3fe83fc97febfc73, 0x3ff0e8adacafb5e2, 0x3fee47a84a31b400), (0x3fe858eb90a17ea9, 0x3ff0ce29b858ff89, 0x3fee776edba13ed6), (0x3fe8720d5f79bf77, 0x3ff0b3d1a433bc56, 0x3feea77c97bb286a), (0x3fe88b2f85704599, 0x3ff099a444afc50a, 0x3feed7d380dfa51f), (0x3fe8a4516bc9e19d, 0x3ff07fa1adcd5635, 0x3fef087356602ce4), (0x3fe8bd7375248413, 0x3ff065c8f21e21d3, 0x3fef395dbac2fb6d), (0x3fe8d69552cff0a1, 0x3ff04c19dd7ddf24, 0x3fef6a92fc644460), (0x3fe8efb76cb96eab, 0x3ff0329382f2fcfc, 0x3fef9c14d23b84cb), (0x3fe908d951162887, 0x3ff01935d537533b, 0x3fefcde34b070181), (0x3fe921fb54442d18, 0x3ff0000000000000, 0x3ff0000000000000), ] const tan32 = {x : flt32 /* A rather irritating special rounding case */ if std.flt32bits(x) == 0xdffd33a4 -> std.flt32frombits(0xbfd06c8c) ;; var r, s (r, s) = tanorcot((x : flt64), true) -> round_down(r, s) } const cot32 = {x : flt32 /* Two more irritating special cases */ if std.flt32bits(x) == 0x33de86a9 -> std.flt32frombits(0x4b134133) elif std.flt32bits(x) == 0xb3de86a9 -> std.flt32frombits(0xcb134133) ;; var r, s (r, s) = tanorcot((x : flt64), false) -> round_down(r, s) } const tan64 = {x : flt64 var r (r, _) = tanorcot(x, true) -> r } const cot64 = {x : flt64 var r (r, _) = tanorcot(x, false) -> r } const tanorcot = {x : flt64, want_tan : bool var n : bool, e : int64, s : uint64 (n, e, s) = std.flt64explode(x) if e == 1024 -> (std.flt64nan(), 0.0) ;; if e == -1023 && s == 0x0 /* Special handling for +/-0.0 */ match (n, want_tan) | (false, false): -> (std.flt64frombits(0x7ff0000000000000), 0.0) | (false, true ): -> (std.flt64frombits(0x0000000000000000), 0.0) | (true , false): -> (std.flt64frombits(0xfff0000000000000), 0.0) | (true , true ): -> (std.flt64frombits(0x8000000000000000), 0.0) ;; ;; var N : int64 var x1 : flt64, x2 : flt64 (N, x1, x2) = trig_reduce(x) var then_negate : bool = false if (N % 2 != 0) /* tan(x + Pi/2) = -cot(x) */ want_tan = !want_tan then_negate = true ;; if (x1 < 0.0) then_negate = !then_negate x1 = -1.0 * x1 x2 = -1.0 * x2 ;; /* from sin-impl.myr */ var xi, tan_xi, cot_xi (xi, cot_xi, tan_xi) = trig_table_approx(x1, C) var cot = std.flt64frombits(cot_xi) var tan = std.flt64frombits(tan_xi) var ret1 : flt64 = 0.0, ret2 : flt64 = 0.0 if xi == 0x0 /* Special case to avoid infinity in cotan */ if want_tan (ret1, ret2) = ptan(x1, x2) else (ret1, ret2) = pcot(x1, x2) ;; goto have_result ;; var delta1, delta2, deltat (delta1, deltat) = fast2sum(-std.flt64frombits(xi), x1) (delta2, _) = fast2sum(deltat, x2) var p1, p2 /* Since cot() can blow up close to 0, just fall back to polynomial approximation. We use a stricter cutoff than given in [GB91] since our C table is more accurate than theirs, meaning we're safe to use it closer to 0. */ if x1 < 0.03 var s = x1 * x1 p1 = x1 * horner_polyu(s, tan_coeff_good[:]) p2 = x2 + 3.0*s*x2 if want_tan (ret1, ret2) = fast2sum(p1, p2) goto have_result ;; (p1, p2) = fast2sum(p1, p2) var f = std.flt64frombits(std.flt64bits(p1) & split_mask) var g = (p1 - f) + p2 var u0 = 1.0/f var u1 = std.flt64frombits(std.flt64bits(u0) & split_mask) var u2 = u0 - u1 (ret1, ret2) = fast2sum(u0 - u0*u0*g, u0*((1.0 - u1*f) - u2*f)) goto have_result ;; if want_tan (p1, p2) = ptan(delta1, delta2) var num = cot + tan var den = (cot - p1) - p2 var f = num/den var q1 = tan var q2 = p1 * f var q3 = p2 * f (q1, q2) = fast2sum(q1, q2) (ret1, ret2) = fast2sum(q1, q2 + q3) else (p1, p2) = ptan(delta1, delta2) var num = cot + tan var den = (tan + p1) + p2 var f = num/den var q1 = cot var q2 = -1.0 * p1 * f var q3 = -1.0 * p2 * f (q1, q2) = fast2sum(q1, q2) (ret1, ret2) = fast2sum(q1, q2 + q3) ;; :have_result if then_negate ret1 = -1.0 * ret1 ret2 = -1.0 * ret2 ;; -> (ret1, ret2) } const ptan = {x1 : flt64, x2 : flt64 var s : flt64 = x1 * x1 var p : flt64 = horner_polyu(s, tan_coeff[:]) var r1, r2 (r1, r2) = two_by_two(p, x1) -> fast2sum(r1, r2 + x2) } const pcot = {x1 : flt64, x2 : flt64 var s : flt64 = x1 * x1 var p : flt64 = horner_polyu(s, cot_coeff[:]) -> fast2sum(p/x1, std.flt64frombits(0x3fd5555555555555)*x2) }