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