libm/math/
rem_pio2_large.rs

1#![allow(unused_unsafe)]
2/* origin: FreeBSD /usr/src/lib/msun/src/k_rem_pio2.c */
3/*
4 * ====================================================
5 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
6 *
7 * Developed at SunSoft, a Sun Microsystems, Inc. business.
8 * Permission to use, copy, modify, and distribute this
9 * software is freely granted, provided that this notice
10 * is preserved.
11 * ====================================================
12 */
13
14use super::floor;
15use super::scalbn;
16
17// initial value for jk
18const INIT_JK: [usize; 4] = [3, 4, 4, 6];
19
20// Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
21//
22//              integer array, contains the (24*i)-th to (24*i+23)-th
23//              bit of 2/pi after binary point. The corresponding
24//              floating value is
25//
26//                      ipio2[i] * 2^(-24(i+1)).
27//
28// NB: This table must have at least (e0-3)/24 + jk terms.
29//     For quad precision (e0 <= 16360, jk = 6), this is 686.
30#[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))]
31const IPIO2: [i32; 66] = [
32    0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C, 0x439041, 0xFE5163,
33    0xABDEBB, 0xC561B7, 0x246E3A, 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
34    0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, 0x3991D6, 0x398353, 0x39F49C,
35    0x845F8B, 0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
36    0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, 0xF17B3D, 0x0739F7, 0x8A5292,
37    0xEA6BFB, 0x5FB11F, 0x8D5D08, 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
38    0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA,
39    0x73A8C9, 0x60E27B, 0xC08C6B,
40];
41
42#[cfg(target_pointer_width = "64")]
43const IPIO2: [i32; 690] = [
44    0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C, 0x439041, 0xFE5163,
45    0xABDEBB, 0xC561B7, 0x246E3A, 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
46    0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, 0x3991D6, 0x398353, 0x39F49C,
47    0x845F8B, 0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
48    0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, 0xF17B3D, 0x0739F7, 0x8A5292,
49    0xEA6BFB, 0x5FB11F, 0x8D5D08, 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
50    0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA,
51    0x73A8C9, 0x60E27B, 0xC08C6B, 0x47C419, 0xC367CD, 0xDCE809, 0x2A8359, 0xC4768B, 0x961CA6,
52    0xDDAF44, 0xD15719, 0x053EA5, 0xFF0705, 0x3F7E33, 0xE832C2, 0xDE4F98, 0x327DBB, 0xC33D26,
53    0xEF6B1E, 0x5EF89F, 0x3A1F35, 0xCAF27F, 0x1D87F1, 0x21907C, 0x7C246A, 0xFA6ED5, 0x772D30,
54    0x433B15, 0xC614B5, 0x9D19C3, 0xC2C4AD, 0x414D2C, 0x5D000C, 0x467D86, 0x2D71E3, 0x9AC69B,
55    0x006233, 0x7CD2B4, 0x97A7B4, 0xD55537, 0xF63ED7, 0x1810A3, 0xFC764D, 0x2A9D64, 0xABD770,
56    0xF87C63, 0x57B07A, 0xE71517, 0x5649C0, 0xD9D63B, 0x3884A7, 0xCB2324, 0x778AD6, 0x23545A,
57    0xB91F00, 0x1B0AF1, 0xDFCE19, 0xFF319F, 0x6A1E66, 0x615799, 0x47FBAC, 0xD87F7E, 0xB76522,
58    0x89E832, 0x60BFE6, 0xCDC4EF, 0x09366C, 0xD43F5D, 0xD7DE16, 0xDE3B58, 0x929BDE, 0x2822D2,
59    0xE88628, 0x4D58E2, 0x32CAC6, 0x16E308, 0xCB7DE0, 0x50C017, 0xA71DF3, 0x5BE018, 0x34132E,
60    0x621283, 0x014883, 0x5B8EF5, 0x7FB0AD, 0xF2E91E, 0x434A48, 0xD36710, 0xD8DDAA, 0x425FAE,
61    0xCE616A, 0xA4280A, 0xB499D3, 0xF2A606, 0x7F775C, 0x83C2A3, 0x883C61, 0x78738A, 0x5A8CAF,
62    0xBDD76F, 0x63A62D, 0xCBBFF4, 0xEF818D, 0x67C126, 0x45CA55, 0x36D9CA, 0xD2A828, 0x8D61C2,
63    0x77C912, 0x142604, 0x9B4612, 0xC459C4, 0x44C5C8, 0x91B24D, 0xF31700, 0xAD43D4, 0xE54929,
64    0x10D5FD, 0xFCBE00, 0xCC941E, 0xEECE70, 0xF53E13, 0x80F1EC, 0xC3E7B3, 0x28F8C7, 0x940593,
65    0x3E71C1, 0xB3092E, 0xF3450B, 0x9C1288, 0x7B20AB, 0x9FB52E, 0xC29247, 0x2F327B, 0x6D550C,
66    0x90A772, 0x1FE76B, 0x96CB31, 0x4A1679, 0xE27941, 0x89DFF4, 0x9794E8, 0x84E6E2, 0x973199,
67    0x6BED88, 0x365F5F, 0x0EFDBB, 0xB49A48, 0x6CA467, 0x427271, 0x325D8D, 0xB8159F, 0x09E5BC,
68    0x25318D, 0x3974F7, 0x1C0530, 0x010C0D, 0x68084B, 0x58EE2C, 0x90AA47, 0x02E774, 0x24D6BD,
69    0xA67DF7, 0x72486E, 0xEF169F, 0xA6948E, 0xF691B4, 0x5153D1, 0xF20ACF, 0x339820, 0x7E4BF5,
70    0x6863B2, 0x5F3EDD, 0x035D40, 0x7F8985, 0x295255, 0xC06437, 0x10D86D, 0x324832, 0x754C5B,
71    0xD4714E, 0x6E5445, 0xC1090B, 0x69F52A, 0xD56614, 0x9D0727, 0x50045D, 0xDB3BB4, 0xC576EA,
72    0x17F987, 0x7D6B49, 0xBA271D, 0x296996, 0xACCCC6, 0x5414AD, 0x6AE290, 0x89D988, 0x50722C,
73    0xBEA404, 0x940777, 0x7030F3, 0x27FC00, 0xA871EA, 0x49C266, 0x3DE064, 0x83DD97, 0x973FA3,
74    0xFD9443, 0x8C860D, 0xDE4131, 0x9D3992, 0x8C70DD, 0xE7B717, 0x3BDF08, 0x2B3715, 0xA0805C,
75    0x93805A, 0x921110, 0xD8E80F, 0xAF806C, 0x4BFFDB, 0x0F9038, 0x761859, 0x15A562, 0xBBCB61,
76    0xB989C7, 0xBD4010, 0x04F2D2, 0x277549, 0xF6B6EB, 0xBB22DB, 0xAA140A, 0x2F2689, 0x768364,
77    0x333B09, 0x1A940E, 0xAA3A51, 0xC2A31D, 0xAEEDAF, 0x12265C, 0x4DC26D, 0x9C7A2D, 0x9756C0,
78    0x833F03, 0xF6F009, 0x8C402B, 0x99316D, 0x07B439, 0x15200C, 0x5BC3D8, 0xC492F5, 0x4BADC6,
79    0xA5CA4E, 0xCD37A7, 0x36A9E6, 0x9492AB, 0x6842DD, 0xDE6319, 0xEF8C76, 0x528B68, 0x37DBFC,
80    0xABA1AE, 0x3115DF, 0xA1AE00, 0xDAFB0C, 0x664D64, 0xB705ED, 0x306529, 0xBF5657, 0x3AFF47,
81    0xB9F96A, 0xF3BE75, 0xDF9328, 0x3080AB, 0xF68C66, 0x15CB04, 0x0622FA, 0x1DE4D9, 0xA4B33D,
82    0x8F1B57, 0x09CD36, 0xE9424E, 0xA4BE13, 0xB52333, 0x1AAAF0, 0xA8654F, 0xA5C1D2, 0x0F3F0B,
83    0xCD785B, 0x76F923, 0x048B7B, 0x721789, 0x53A6C6, 0xE26E6F, 0x00EBEF, 0x584A9B, 0xB7DAC4,
84    0xBA66AA, 0xCFCF76, 0x1D02D1, 0x2DF1B1, 0xC1998C, 0x77ADC3, 0xDA4886, 0xA05DF7, 0xF480C6,
85    0x2FF0AC, 0x9AECDD, 0xBC5C3F, 0x6DDED0, 0x1FC790, 0xB6DB2A, 0x3A25A3, 0x9AAF00, 0x9353AD,
86    0x0457B6, 0xB42D29, 0x7E804B, 0xA707DA, 0x0EAA76, 0xA1597B, 0x2A1216, 0x2DB7DC, 0xFDE5FA,
87    0xFEDB89, 0xFDBE89, 0x6C76E4, 0xFCA906, 0x70803E, 0x156E85, 0xFF87FD, 0x073E28, 0x336761,
88    0x86182A, 0xEABD4D, 0xAFE7B3, 0x6E6D8F, 0x396795, 0x5BBF31, 0x48D784, 0x16DF30, 0x432DC7,
89    0x356125, 0xCE70C9, 0xB8CB30, 0xFD6CBF, 0xA200A4, 0xE46C05, 0xA0DD5A, 0x476F21, 0xD21262,
90    0x845CB9, 0x496170, 0xE0566B, 0x015299, 0x375550, 0xB7D51E, 0xC4F133, 0x5F6E13, 0xE4305D,
91    0xA92E85, 0xC3B21D, 0x3632A1, 0xA4B708, 0xD4B1EA, 0x21F716, 0xE4698F, 0x77FF27, 0x80030C,
92    0x2D408D, 0xA0CD4F, 0x99A520, 0xD3A2B3, 0x0A5D2F, 0x42F9B4, 0xCBDA11, 0xD0BE7D, 0xC1DB9B,
93    0xBD17AB, 0x81A2CA, 0x5C6A08, 0x17552E, 0x550027, 0xF0147F, 0x8607E1, 0x640B14, 0x8D4196,
94    0xDEBE87, 0x2AFDDA, 0xB6256B, 0x34897B, 0xFEF305, 0x9EBFB9, 0x4F6A68, 0xA82A4A, 0x5AC44F,
95    0xBCF82D, 0x985AD7, 0x95C7F4, 0x8D4D0D, 0xA63A20, 0x5F57A4, 0xB13F14, 0x953880, 0x0120CC,
96    0x86DD71, 0xB6DEC9, 0xF560BF, 0x11654D, 0x6B0701, 0xACB08C, 0xD0C0B2, 0x485551, 0x0EFB1E,
97    0xC37295, 0x3B06A3, 0x3540C0, 0x7BDC06, 0xCC45E0, 0xFA294E, 0xC8CAD6, 0x41F3E8, 0xDE647C,
98    0xD8649B, 0x31BED9, 0xC397A4, 0xD45877, 0xC5E369, 0x13DAF0, 0x3C3ABA, 0x461846, 0x5F7555,
99    0xF5BDD2, 0xC6926E, 0x5D2EAC, 0xED440E, 0x423E1C, 0x87C461, 0xE9FD29, 0xF3D6E7, 0xCA7C22,
100    0x35916F, 0xC5E008, 0x8DD7FF, 0xE26A6E, 0xC6FDB0, 0xC10893, 0x745D7C, 0xB2AD6B, 0x9D6ECD,
101    0x7B723E, 0x6A11C6, 0xA9CFF7, 0xDF7329, 0xBAC9B5, 0x5100B7, 0x0DB2E2, 0x24BA74, 0x607DE5,
102    0x8AD874, 0x2C150D, 0x0C1881, 0x94667E, 0x162901, 0x767A9F, 0xBEFDFD, 0xEF4556, 0x367ED9,
103    0x13D9EC, 0xB9BA8B, 0xFC97C4, 0x27A831, 0xC36EF1, 0x36C594, 0x56A8D8, 0xB5A8B4, 0x0ECCCF,
104    0x2D8912, 0x34576F, 0x89562C, 0xE3CE99, 0xB920D6, 0xAA5E6B, 0x9C2A3E, 0xCC5F11, 0x4A0BFD,
105    0xFBF4E1, 0x6D3B8E, 0x2C86E2, 0x84D4E9, 0xA9B4FC, 0xD1EEEF, 0xC9352E, 0x61392F, 0x442138,
106    0xC8D91B, 0x0AFC81, 0x6A4AFB, 0xD81C2F, 0x84B453, 0x8C994E, 0xCC2254, 0xDC552A, 0xD6C6C0,
107    0x96190B, 0xB8701A, 0x649569, 0x605A26, 0xEE523F, 0x0F117F, 0x11B5F4, 0xF5CBFC, 0x2DBC34,
108    0xEEBC34, 0xCC5DE8, 0x605EDD, 0x9B8E67, 0xEF3392, 0xB817C9, 0x9B5861, 0xBC57E1, 0xC68351,
109    0x103ED8, 0x4871DD, 0xDD1C2D, 0xA118AF, 0x462C21, 0xD7F359, 0x987AD9, 0xC0549E, 0xFA864F,
110    0xFC0656, 0xAE79E5, 0x362289, 0x22AD38, 0xDC9367, 0xAAE855, 0x382682, 0x9BE7CA, 0xA40D51,
111    0xB13399, 0x0ED7A9, 0x480569, 0xF0B265, 0xA7887F, 0x974C88, 0x36D1F9, 0xB39221, 0x4A827B,
112    0x21CF98, 0xDC9F40, 0x5547DC, 0x3A74E1, 0x42EB67, 0xDF9DFE, 0x5FD45E, 0xA4677B, 0x7AACBA,
113    0xA2F655, 0x23882B, 0x55BA41, 0x086E59, 0x862A21, 0x834739, 0xE6E389, 0xD49EE5, 0x40FB49,
114    0xE956FF, 0xCA0F1C, 0x8A59C5, 0x2BFA94, 0xC5C1D3, 0xCFC50F, 0xAE5ADB, 0x86C547, 0x624385,
115    0x3B8621, 0x94792C, 0x876110, 0x7B4C2A, 0x1A2C80, 0x12BF43, 0x902688, 0x893C78, 0xE4C4A8,
116    0x7BDBE5, 0xC23AC4, 0xEAF426, 0x8A67F7, 0xBF920D, 0x2BA365, 0xB1933D, 0x0B7CBD, 0xDC51A4,
117    0x63DD27, 0xDDE169, 0x19949A, 0x9529A8, 0x28CE68, 0xB4ED09, 0x209F44, 0xCA984E, 0x638270,
118    0x237C7E, 0x32B90F, 0x8EF5A7, 0xE75614, 0x08F121, 0x2A9DB5, 0x4D7E6F, 0x5119A5, 0xABF9B5,
119    0xD6DF82, 0x61DD96, 0x023616, 0x9F3AC4, 0xA1A283, 0x6DED72, 0x7A8D39, 0xA9B882, 0x5C326B,
120    0x5B2746, 0xED3400, 0x7700D2, 0x55F4FC, 0x4D5901, 0x8071E0,
121];
122
123const PIO2: [f64; 8] = [
124    1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
125    7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
126    5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
127    3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */
128    1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */
129    1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */
130    2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */
131    2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
132];
133
134// fn rem_pio2_large(x : &[f64], y : &mut [f64], e0 : i32, prec : usize) -> i32
135//
136// Input parameters:
137//      x[]     The input value (must be positive) is broken into nx
138//              pieces of 24-bit integers in double precision format.
139//              x[i] will be the i-th 24 bit of x. The scaled exponent
140//              of x[0] is given in input parameter e0 (i.e., x[0]*2^e0
141//              match x's up to 24 bits.
142//
143//              Example of breaking a double positive z into x[0]+x[1]+x[2]:
144//                      e0 = ilogb(z)-23
145//                      z  = scalbn(z,-e0)
146//              for i = 0,1,2
147//                      x[i] = floor(z)
148//                      z    = (z-x[i])*2**24
149//
150//      y[]     ouput result in an array of double precision numbers.
151//              The dimension of y[] is:
152//                      24-bit  precision       1
153//                      53-bit  precision       2
154//                      64-bit  precision       2
155//                      113-bit precision       3
156//              The actual value is the sum of them. Thus for 113-bit
157//              precison, one may have to do something like:
158//
159//              long double t,w,r_head, r_tail;
160//              t = (long double)y[2] + (long double)y[1];
161//              w = (long double)y[0];
162//              r_head = t+w;
163//              r_tail = w - (r_head - t);
164//
165//      e0      The exponent of x[0]. Must be <= 16360 or you need to
166//              expand the ipio2 table.
167//
168//      prec    an integer indicating the precision:
169//                      0       24  bits (single)
170//                      1       53  bits (double)
171//                      2       64  bits (extended)
172//                      3       113 bits (quad)
173//
174// Here is the description of some local variables:
175//
176//      jk      jk+1 is the initial number of terms of ipio2[] needed
177//              in the computation. The minimum and recommended value
178//              for jk is 3,4,4,6 for single, double, extended, and quad.
179//              jk+1 must be 2 larger than you might expect so that our
180//              recomputation test works. (Up to 24 bits in the integer
181//              part (the 24 bits of it that we compute) and 23 bits in
182//              the fraction part may be lost to cancelation before we
183//              recompute.)
184//
185//      jz      local integer variable indicating the number of
186//              terms of ipio2[] used.
187//
188//      jx      nx - 1
189//
190//      jv      index for pointing to the suitable ipio2[] for the
191//              computation. In general, we want
192//                      ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8
193//              is an integer. Thus
194//                      e0-3-24*jv >= 0 or (e0-3)/24 >= jv
195//              Hence jv = max(0,(e0-3)/24).
196//
197//      jp      jp+1 is the number of terms in PIo2[] needed, jp = jk.
198//
199//      q[]     double array with integral value, representing the
200//              24-bits chunk of the product of x and 2/pi.
201//
202//      q0      the corresponding exponent of q[0]. Note that the
203//              exponent for q[i] would be q0-24*i.
204//
205//      PIo2[]  double precision array, obtained by cutting pi/2
206//              into 24 bits chunks.
207//
208//      f[]     ipio2[] in floating point
209//
210//      iq[]    integer array by breaking up q[] in 24-bits chunk.
211//
212//      fq[]    final product of x*(2/pi) in fq[0],..,fq[jk]
213//
214//      ih      integer. If >0 it indicates q[] is >= 0.5, hence
215//              it also indicates the *sign* of the result.
216
217/// Return the last three digits of N with y = x - N*pi/2
218/// so that |y| < pi/2.
219///
220/// The method is to compute the integer (mod 8) and fraction parts of
221/// (2/pi)*x without doing the full multiplication. In general we
222/// skip the part of the product that are known to be a huge integer (
223/// more accurately, = 0 mod 8 ). Thus the number of operations are
224/// independent of the exponent of the input.
225#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
226pub(crate) fn rem_pio2_large(x: &[f64], y: &mut [f64], e0: i32, prec: usize) -> i32 {
227    let x1p24 = f64::from_bits(0x4170000000000000); // 0x1p24 === 2 ^ 24
228    let x1p_24 = f64::from_bits(0x3e70000000000000); // 0x1p_24 === 2 ^ (-24)
229
230    #[cfg(all(target_pointer_width = "64", feature = "checked"))]
231    assert!(e0 <= 16360);
232
233    let nx = x.len();
234
235    let mut fw: f64;
236    let mut n: i32;
237    let mut ih: i32;
238    let mut z: f64;
239    let mut f: [f64; 20] = [0.; 20];
240    let mut fq: [f64; 20] = [0.; 20];
241    let mut q: [f64; 20] = [0.; 20];
242    let mut iq: [i32; 20] = [0; 20];
243
244    /* initialize jk*/
245    let jk = i!(INIT_JK, prec);
246    let jp = jk;
247
248    /* determine jx,jv,q0, note that 3>q0 */
249    let jx = nx - 1;
250    let mut jv = div!(e0 - 3, 24);
251    if jv < 0 {
252        jv = 0;
253    }
254    let mut q0 = e0 - 24 * (jv + 1);
255    let jv = jv as usize;
256
257    /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
258    let mut j = (jv as i32) - (jx as i32);
259    let m = jx + jk;
260    for i in 0..=m {
261        i!(f, i, =, if j < 0 {
262            0.
263        } else {
264            i!(IPIO2, j as usize) as f64
265        });
266        j += 1;
267    }
268
269    /* compute q[0],q[1],...q[jk] */
270    for i in 0..=jk {
271        fw = 0f64;
272        for j in 0..=jx {
273            fw += i!(x, j) * i!(f, jx + i - j);
274        }
275        i!(q, i, =, fw);
276    }
277
278    let mut jz = jk;
279
280    'recompute: loop {
281        /* distill q[] into iq[] reversingly */
282        let mut i = 0i32;
283        z = i!(q, jz);
284        for j in (1..=jz).rev() {
285            fw = (x1p_24 * z) as i32 as f64;
286            i!(iq, i as usize, =, (z - x1p24 * fw) as i32);
287            z = i!(q, j - 1) + fw;
288            i += 1;
289        }
290
291        /* compute n */
292        z = scalbn(z, q0); /* actual value of z */
293        z -= 8.0 * floor(z * 0.125); /* trim off integer >= 8 */
294        n = z as i32;
295        z -= n as f64;
296        ih = 0;
297        if q0 > 0 {
298            /* need iq[jz-1] to determine n */
299            i = i!(iq, jz - 1) >> (24 - q0);
300            n += i;
301            i!(iq, jz - 1, -=, i << (24 - q0));
302            ih = i!(iq, jz - 1) >> (23 - q0);
303        } else if q0 == 0 {
304            ih = i!(iq, jz - 1) >> 23;
305        } else if z >= 0.5 {
306            ih = 2;
307        }
308
309        if ih > 0 {
310            /* q > 0.5 */
311            n += 1;
312            let mut carry = 0i32;
313            for i in 0..jz {
314                /* compute 1-q */
315                let j = i!(iq, i);
316                if carry == 0 {
317                    if j != 0 {
318                        carry = 1;
319                        i!(iq, i, =, 0x1000000 - j);
320                    }
321                } else {
322                    i!(iq, i, =, 0xffffff - j);
323                }
324            }
325            if q0 > 0 {
326                /* rare case: chance is 1 in 12 */
327                match q0 {
328                    1 => {
329                        i!(iq, jz - 1, &=, 0x7fffff);
330                    }
331                    2 => {
332                        i!(iq, jz - 1, &=, 0x3fffff);
333                    }
334                    _ => {}
335                }
336            }
337            if ih == 2 {
338                z = 1. - z;
339                if carry != 0 {
340                    z -= scalbn(1., q0);
341                }
342            }
343        }
344
345        /* check if recomputation is needed */
346        if z == 0. {
347            let mut j = 0;
348            for i in (jk..=jz - 1).rev() {
349                j |= i!(iq, i);
350            }
351            if j == 0 {
352                /* need recomputation */
353                let mut k = 1;
354                while i!(iq, jk - k, ==, 0) {
355                    k += 1; /* k = no. of terms needed */
356                }
357
358                for i in (jz + 1)..=(jz + k) {
359                    /* add q[jz+1] to q[jz+k] */
360                    i!(f, jx + i, =, i!(IPIO2, jv + i) as f64);
361                    fw = 0f64;
362                    for j in 0..=jx {
363                        fw += i!(x, j) * i!(f, jx + i - j);
364                    }
365                    i!(q, i, =, fw);
366                }
367                jz += k;
368                continue 'recompute;
369            }
370        }
371
372        break;
373    }
374
375    /* chop off zero terms */
376    if z == 0. {
377        jz -= 1;
378        q0 -= 24;
379        while i!(iq, jz) == 0 {
380            jz -= 1;
381            q0 -= 24;
382        }
383    } else {
384        /* break z into 24-bit if necessary */
385        z = scalbn(z, -q0);
386        if z >= x1p24 {
387            fw = (x1p_24 * z) as i32 as f64;
388            i!(iq, jz, =, (z - x1p24 * fw) as i32);
389            jz += 1;
390            q0 += 24;
391            i!(iq, jz, =, fw as i32);
392        } else {
393            i!(iq, jz, =, z as i32);
394        }
395    }
396
397    /* convert integer "bit" chunk to floating-point value */
398    fw = scalbn(1., q0);
399    for i in (0..=jz).rev() {
400        i!(q, i, =, fw * (i!(iq, i) as f64));
401        fw *= x1p_24;
402    }
403
404    /* compute PIo2[0,...,jp]*q[jz,...,0] */
405    for i in (0..=jz).rev() {
406        fw = 0f64;
407        let mut k = 0;
408        while (k <= jp) && (k <= jz - i) {
409            fw += i!(PIO2, k) * i!(q, i + k);
410            k += 1;
411        }
412        i!(fq, jz - i, =, fw);
413    }
414
415    /* compress fq[] into y[] */
416    match prec {
417        0 => {
418            fw = 0f64;
419            for i in (0..=jz).rev() {
420                fw += i!(fq, i);
421            }
422            i!(y, 0, =, if ih == 0 { fw } else { -fw });
423        }
424        1 | 2 => {
425            fw = 0f64;
426            for i in (0..=jz).rev() {
427                fw += i!(fq, i);
428            }
429            // TODO: drop excess precision here once double_t is used
430            fw = fw as f64;
431            i!(y, 0, =, if ih == 0 { fw } else { -fw });
432            fw = i!(fq, 0) - fw;
433            for i in 1..=jz {
434                fw += i!(fq, i);
435            }
436            i!(y, 1, =, if ih == 0 { fw } else { -fw });
437        }
438        3 => {
439            /* painful */
440            for i in (1..=jz).rev() {
441                fw = i!(fq, i - 1) + i!(fq, i);
442                i!(fq, i, +=, i!(fq, i - 1) - fw);
443                i!(fq, i - 1, =, fw);
444            }
445            for i in (2..=jz).rev() {
446                fw = i!(fq, i - 1) + i!(fq, i);
447                i!(fq, i, +=, i!(fq, i - 1) - fw);
448                i!(fq, i - 1, =, fw);
449            }
450            fw = 0f64;
451            for i in (2..=jz).rev() {
452                fw += i!(fq, i);
453            }
454            if ih == 0 {
455                i!(y, 0, =, i!(fq, 0));
456                i!(y, 1, =, i!(fq, 1));
457                i!(y, 2, =, fw);
458            } else {
459                i!(y, 0, =, -i!(fq, 0));
460                i!(y, 1, =, -i!(fq, 1));
461                i!(y, 2, =, -fw);
462            }
463        }
464        #[cfg(debug_assertions)]
465        _ => unreachable!(),
466        #[cfg(not(debug_assertions))]
467        _ => {}
468    }
469    n & 7
470}