1*61046927SAndroid Build Coastguard Worker/* 2*61046927SAndroid Build Coastguard Worker * The implementations contained in this file are heavily based on the 3*61046927SAndroid Build Coastguard Worker * implementations found in the Berkeley SoftFloat library. As such, they are 4*61046927SAndroid Build Coastguard Worker * licensed under the same 3-clause BSD license: 5*61046927SAndroid Build Coastguard Worker * 6*61046927SAndroid Build Coastguard Worker * License for Berkeley SoftFloat Release 3e 7*61046927SAndroid Build Coastguard Worker * 8*61046927SAndroid Build Coastguard Worker * John R. Hauser 9*61046927SAndroid Build Coastguard Worker * 2018 January 20 10*61046927SAndroid Build Coastguard Worker * 11*61046927SAndroid Build Coastguard Worker * The following applies to the whole of SoftFloat Release 3e as well as to 12*61046927SAndroid Build Coastguard Worker * each source file individually. 13*61046927SAndroid Build Coastguard Worker * 14*61046927SAndroid Build Coastguard Worker * Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the 15*61046927SAndroid Build Coastguard Worker * University of California. All rights reserved. 16*61046927SAndroid Build Coastguard Worker * 17*61046927SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without 18*61046927SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions are met: 19*61046927SAndroid Build Coastguard Worker * 20*61046927SAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright notice, 21*61046927SAndroid Build Coastguard Worker * this list of conditions, and the following disclaimer. 22*61046927SAndroid Build Coastguard Worker * 23*61046927SAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright 24*61046927SAndroid Build Coastguard Worker * notice, this list of conditions, and the following disclaimer in the 25*61046927SAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution. 26*61046927SAndroid Build Coastguard Worker * 27*61046927SAndroid Build Coastguard Worker * 3. Neither the name of the University nor the names of its contributors 28*61046927SAndroid Build Coastguard Worker * may be used to endorse or promote products derived from this software 29*61046927SAndroid Build Coastguard Worker * without specific prior written permission. 30*61046927SAndroid Build Coastguard Worker * 31*61046927SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY 32*61046927SAndroid Build Coastguard Worker * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 33*61046927SAndroid Build Coastguard Worker * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE 34*61046927SAndroid Build Coastguard Worker * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 35*61046927SAndroid Build Coastguard Worker * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 36*61046927SAndroid Build Coastguard Worker * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 37*61046927SAndroid Build Coastguard Worker * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 38*61046927SAndroid Build Coastguard Worker * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 39*61046927SAndroid Build Coastguard Worker * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 40*61046927SAndroid Build Coastguard Worker * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41*61046927SAndroid Build Coastguard Worker*/ 42*61046927SAndroid Build Coastguard Worker 43*61046927SAndroid Build Coastguard Worker#version 400 44*61046927SAndroid Build Coastguard Worker#extension GL_ARB_gpu_shader_int64 : enable 45*61046927SAndroid Build Coastguard Worker#extension GL_ARB_shader_bit_encoding : enable 46*61046927SAndroid Build Coastguard Worker#extension GL_EXT_shader_integer_mix : enable 47*61046927SAndroid Build Coastguard Worker#extension GL_MESA_shader_integer_functions : enable 48*61046927SAndroid Build Coastguard Worker 49*61046927SAndroid Build Coastguard Worker#pragma warning(off) 50*61046927SAndroid Build Coastguard Worker 51*61046927SAndroid Build Coastguard Worker/* Software IEEE floating-point rounding mode. 52*61046927SAndroid Build Coastguard Worker * GLSL spec section "4.7.1 Range and Precision": 53*61046927SAndroid Build Coastguard Worker * The rounding mode cannot be set and is undefined. 54*61046927SAndroid Build Coastguard Worker * But here, we are able to define the rounding mode at the compilation time. 55*61046927SAndroid Build Coastguard Worker */ 56*61046927SAndroid Build Coastguard Worker#define FLOAT_ROUND_NEAREST_EVEN 0 57*61046927SAndroid Build Coastguard Worker#define FLOAT_ROUND_TO_ZERO 1 58*61046927SAndroid Build Coastguard Worker#define FLOAT_ROUND_DOWN 2 59*61046927SAndroid Build Coastguard Worker#define FLOAT_ROUND_UP 3 60*61046927SAndroid Build Coastguard Worker#define FLOAT_ROUNDING_MODE FLOAT_ROUND_NEAREST_EVEN 61*61046927SAndroid Build Coastguard Worker 62*61046927SAndroid Build Coastguard Worker/* Relax propagation of NaN. Binary operations with a NaN source will still 63*61046927SAndroid Build Coastguard Worker * produce a NaN result, but it won't follow strict IEEE rules. 64*61046927SAndroid Build Coastguard Worker */ 65*61046927SAndroid Build Coastguard Worker#define RELAXED_NAN_PROPAGATION 66*61046927SAndroid Build Coastguard Worker 67*61046927SAndroid Build Coastguard Worker/* Absolute value of a Float64 : 68*61046927SAndroid Build Coastguard Worker * Clear the sign bit 69*61046927SAndroid Build Coastguard Worker */ 70*61046927SAndroid Build Coastguard Workeruint64_t 71*61046927SAndroid Build Coastguard Worker__fabs64(uint64_t __a) 72*61046927SAndroid Build Coastguard Worker{ 73*61046927SAndroid Build Coastguard Worker uvec2 a = unpackUint2x32(__a); 74*61046927SAndroid Build Coastguard Worker a.y &= 0x7FFFFFFFu; 75*61046927SAndroid Build Coastguard Worker return packUint2x32(a); 76*61046927SAndroid Build Coastguard Worker} 77*61046927SAndroid Build Coastguard Worker 78*61046927SAndroid Build Coastguard Worker/* Returns 1 if the double-precision floating-point value `a' is a NaN; 79*61046927SAndroid Build Coastguard Worker * otherwise returns 0. 80*61046927SAndroid Build Coastguard Worker */ 81*61046927SAndroid Build Coastguard Workerbool 82*61046927SAndroid Build Coastguard Worker__is_nan(uint64_t __a) 83*61046927SAndroid Build Coastguard Worker{ 84*61046927SAndroid Build Coastguard Worker uvec2 a = unpackUint2x32(__a); 85*61046927SAndroid Build Coastguard Worker return (0xFFE00000u <= (a.y<<1)) && 86*61046927SAndroid Build Coastguard Worker ((a.x != 0u) || ((a.y & 0x000FFFFFu) != 0u)); 87*61046927SAndroid Build Coastguard Worker} 88*61046927SAndroid Build Coastguard Worker 89*61046927SAndroid Build Coastguard Worker/* Negate value of a Float64 : 90*61046927SAndroid Build Coastguard Worker * Toggle the sign bit 91*61046927SAndroid Build Coastguard Worker */ 92*61046927SAndroid Build Coastguard Workeruint64_t 93*61046927SAndroid Build Coastguard Worker__fneg64(uint64_t __a) 94*61046927SAndroid Build Coastguard Worker{ 95*61046927SAndroid Build Coastguard Worker uvec2 a = unpackUint2x32(__a); 96*61046927SAndroid Build Coastguard Worker a.y ^= (1u << 31); 97*61046927SAndroid Build Coastguard Worker return packUint2x32(a); 98*61046927SAndroid Build Coastguard Worker} 99*61046927SAndroid Build Coastguard Worker 100*61046927SAndroid Build Coastguard Workeruint64_t 101*61046927SAndroid Build Coastguard Worker__fsign64(uint64_t __a) 102*61046927SAndroid Build Coastguard Worker{ 103*61046927SAndroid Build Coastguard Worker uvec2 a = unpackUint2x32(__a); 104*61046927SAndroid Build Coastguard Worker uvec2 retval; 105*61046927SAndroid Build Coastguard Worker retval.x = 0u; 106*61046927SAndroid Build Coastguard Worker retval.y = mix((a.y & 0x80000000u) | 0x3FF00000u, 0u, (a.y << 1 | a.x) == 0u); 107*61046927SAndroid Build Coastguard Worker return packUint2x32(retval); 108*61046927SAndroid Build Coastguard Worker} 109*61046927SAndroid Build Coastguard Worker 110*61046927SAndroid Build Coastguard Worker/* Returns the fraction bits of the double-precision floating-point value `a'.*/ 111*61046927SAndroid Build Coastguard Workeruint 112*61046927SAndroid Build Coastguard Worker__extractFloat64FracLo(uint64_t a) 113*61046927SAndroid Build Coastguard Worker{ 114*61046927SAndroid Build Coastguard Worker return unpackUint2x32(a).x; 115*61046927SAndroid Build Coastguard Worker} 116*61046927SAndroid Build Coastguard Worker 117*61046927SAndroid Build Coastguard Workeruint 118*61046927SAndroid Build Coastguard Worker__extractFloat64FracHi(uint64_t a) 119*61046927SAndroid Build Coastguard Worker{ 120*61046927SAndroid Build Coastguard Worker return unpackUint2x32(a).y & 0x000FFFFFu; 121*61046927SAndroid Build Coastguard Worker} 122*61046927SAndroid Build Coastguard Worker 123*61046927SAndroid Build Coastguard Worker/* Returns the exponent bits of the double-precision floating-point value `a'.*/ 124*61046927SAndroid Build Coastguard Workerint 125*61046927SAndroid Build Coastguard Worker__extractFloat64Exp(uint64_t __a) 126*61046927SAndroid Build Coastguard Worker{ 127*61046927SAndroid Build Coastguard Worker uvec2 a = unpackUint2x32(__a); 128*61046927SAndroid Build Coastguard Worker return int((a.y>>20) & 0x7FFu); 129*61046927SAndroid Build Coastguard Worker} 130*61046927SAndroid Build Coastguard Worker 131*61046927SAndroid Build Coastguard Workerbool 132*61046927SAndroid Build Coastguard Worker__feq64_nonnan(uint64_t __a, uint64_t __b) 133*61046927SAndroid Build Coastguard Worker{ 134*61046927SAndroid Build Coastguard Worker uvec2 a = unpackUint2x32(__a); 135*61046927SAndroid Build Coastguard Worker uvec2 b = unpackUint2x32(__b); 136*61046927SAndroid Build Coastguard Worker return (a.x == b.x) && 137*61046927SAndroid Build Coastguard Worker ((a.y == b.y) || ((a.x == 0u) && (((a.y | b.y)<<1) == 0u))); 138*61046927SAndroid Build Coastguard Worker} 139*61046927SAndroid Build Coastguard Worker 140*61046927SAndroid Build Coastguard Worker/* Returns true if the double-precision floating-point value `a' is equal to the 141*61046927SAndroid Build Coastguard Worker * corresponding value `b', and false otherwise. The comparison is performed 142*61046927SAndroid Build Coastguard Worker * according to the IEEE Standard for Floating-Point Arithmetic. 143*61046927SAndroid Build Coastguard Worker */ 144*61046927SAndroid Build Coastguard Workerbool 145*61046927SAndroid Build Coastguard Worker__feq64(uint64_t a, uint64_t b) 146*61046927SAndroid Build Coastguard Worker{ 147*61046927SAndroid Build Coastguard Worker if (__is_nan(a) || __is_nan(b)) 148*61046927SAndroid Build Coastguard Worker return false; 149*61046927SAndroid Build Coastguard Worker 150*61046927SAndroid Build Coastguard Worker return __feq64_nonnan(a, b); 151*61046927SAndroid Build Coastguard Worker} 152*61046927SAndroid Build Coastguard Worker 153*61046927SAndroid Build Coastguard Worker/* Returns true if the double-precision floating-point value `a' is not equal 154*61046927SAndroid Build Coastguard Worker * to the corresponding value `b', and false otherwise. The comparison is 155*61046927SAndroid Build Coastguard Worker * performed according to the IEEE Standard for Floating-Point Arithmetic. 156*61046927SAndroid Build Coastguard Worker */ 157*61046927SAndroid Build Coastguard Workerbool 158*61046927SAndroid Build Coastguard Worker__fneu64(uint64_t a, uint64_t b) 159*61046927SAndroid Build Coastguard Worker{ 160*61046927SAndroid Build Coastguard Worker if (__is_nan(a) || __is_nan(b)) 161*61046927SAndroid Build Coastguard Worker return true; 162*61046927SAndroid Build Coastguard Worker 163*61046927SAndroid Build Coastguard Worker return !__feq64_nonnan(a, b); 164*61046927SAndroid Build Coastguard Worker} 165*61046927SAndroid Build Coastguard Worker 166*61046927SAndroid Build Coastguard Worker/* Returns the sign bit of the double-precision floating-point value `a'.*/ 167*61046927SAndroid Build Coastguard Workeruint 168*61046927SAndroid Build Coastguard Worker__extractFloat64Sign(uint64_t a) 169*61046927SAndroid Build Coastguard Worker{ 170*61046927SAndroid Build Coastguard Worker return unpackUint2x32(a).y & 0x80000000u; 171*61046927SAndroid Build Coastguard Worker} 172*61046927SAndroid Build Coastguard Worker 173*61046927SAndroid Build Coastguard Worker/* Returns true if the signed 64-bit value formed by concatenating `a0' and 174*61046927SAndroid Build Coastguard Worker * `a1' is less than the signed 64-bit value formed by concatenating `b0' and 175*61046927SAndroid Build Coastguard Worker * `b1'. Otherwise, returns false. 176*61046927SAndroid Build Coastguard Worker */ 177*61046927SAndroid Build Coastguard Workerbool 178*61046927SAndroid Build Coastguard Workerilt64(uint a0, uint a1, uint b0, uint b1) 179*61046927SAndroid Build Coastguard Worker{ 180*61046927SAndroid Build Coastguard Worker return (int(a0) < int(b0)) || ((a0 == b0) && (a1 < b1)); 181*61046927SAndroid Build Coastguard Worker} 182*61046927SAndroid Build Coastguard Worker 183*61046927SAndroid Build Coastguard Workerbool 184*61046927SAndroid Build Coastguard Worker__flt64_nonnan(uint64_t __a, uint64_t __b) 185*61046927SAndroid Build Coastguard Worker{ 186*61046927SAndroid Build Coastguard Worker uvec2 a = unpackUint2x32(__a); 187*61046927SAndroid Build Coastguard Worker uvec2 b = unpackUint2x32(__b); 188*61046927SAndroid Build Coastguard Worker 189*61046927SAndroid Build Coastguard Worker /* IEEE 754 floating point numbers are specifically designed so that, with 190*61046927SAndroid Build Coastguard Worker * two exceptions, values can be compared by bit-casting to signed integers 191*61046927SAndroid Build Coastguard Worker * with the same number of bits. 192*61046927SAndroid Build Coastguard Worker * 193*61046927SAndroid Build Coastguard Worker * From https://en.wikipedia.org/wiki/IEEE_754-1985#Comparing_floating-point_numbers: 194*61046927SAndroid Build Coastguard Worker * 195*61046927SAndroid Build Coastguard Worker * When comparing as 2's-complement integers: If the sign bits differ, 196*61046927SAndroid Build Coastguard Worker * the negative number precedes the positive number, so 2's complement 197*61046927SAndroid Build Coastguard Worker * gives the correct result (except that negative zero and positive zero 198*61046927SAndroid Build Coastguard Worker * should be considered equal). If both values are positive, the 2's 199*61046927SAndroid Build Coastguard Worker * complement comparison again gives the correct result. Otherwise (two 200*61046927SAndroid Build Coastguard Worker * negative numbers), the correct FP ordering is the opposite of the 2's 201*61046927SAndroid Build Coastguard Worker * complement ordering. 202*61046927SAndroid Build Coastguard Worker * 203*61046927SAndroid Build Coastguard Worker * The logic implied by the above quotation is: 204*61046927SAndroid Build Coastguard Worker * 205*61046927SAndroid Build Coastguard Worker * !both_are_zero(a, b) && (both_negative(a, b) ? a > b : a < b) 206*61046927SAndroid Build Coastguard Worker * 207*61046927SAndroid Build Coastguard Worker * This is equivalent to 208*61046927SAndroid Build Coastguard Worker * 209*61046927SAndroid Build Coastguard Worker * fneu(a, b) && (both_negative(a, b) ? a >= b : a < b) 210*61046927SAndroid Build Coastguard Worker * 211*61046927SAndroid Build Coastguard Worker * fneu(a, b) && (both_negative(a, b) ? !(a < b) : a < b) 212*61046927SAndroid Build Coastguard Worker * 213*61046927SAndroid Build Coastguard Worker * fneu(a, b) && ((both_negative(a, b) && !(a < b)) || 214*61046927SAndroid Build Coastguard Worker * (!both_negative(a, b) && (a < b))) 215*61046927SAndroid Build Coastguard Worker * 216*61046927SAndroid Build Coastguard Worker * (A!|B)&(A|!B) is (A xor B) which is implemented here using !=. 217*61046927SAndroid Build Coastguard Worker * 218*61046927SAndroid Build Coastguard Worker * fneu(a, b) && (both_negative(a, b) != (a < b)) 219*61046927SAndroid Build Coastguard Worker */ 220*61046927SAndroid Build Coastguard Worker bool lt = ilt64(a.y, a.x, b.y, b.x); 221*61046927SAndroid Build Coastguard Worker bool both_negative = (a.y & b.y & 0x80000000u) != 0; 222*61046927SAndroid Build Coastguard Worker 223*61046927SAndroid Build Coastguard Worker return !__feq64_nonnan(__a, __b) && (lt != both_negative); 224*61046927SAndroid Build Coastguard Worker} 225*61046927SAndroid Build Coastguard Worker 226*61046927SAndroid Build Coastguard Workerbool 227*61046927SAndroid Build Coastguard Worker__flt64_nonnan_minmax(uint64_t __a, uint64_t __b) 228*61046927SAndroid Build Coastguard Worker{ 229*61046927SAndroid Build Coastguard Worker uvec2 a = unpackUint2x32(__a); 230*61046927SAndroid Build Coastguard Worker uvec2 b = unpackUint2x32(__b); 231*61046927SAndroid Build Coastguard Worker 232*61046927SAndroid Build Coastguard Worker /* See __flt64_nonnan. For implementing fmin/fmax, we compare -0 < 0, so the 233*61046927SAndroid Build Coastguard Worker * implied logic is a bit simpler: 234*61046927SAndroid Build Coastguard Worker * 235*61046927SAndroid Build Coastguard Worker * both_negative(a, b) ? a > b : a < b 236*61046927SAndroid Build Coastguard Worker * 237*61046927SAndroid Build Coastguard Worker * If a == b, it doesn't matter what we return, so that's equivalent to: 238*61046927SAndroid Build Coastguard Worker * 239*61046927SAndroid Build Coastguard Worker * both_negative(a, b) ? a >= b : a < b 240*61046927SAndroid Build Coastguard Worker * both_negative(a, b) ? !(a < b) : a < b 241*61046927SAndroid Build Coastguard Worker * both_negative(a, b) ^ (a < b) 242*61046927SAndroid Build Coastguard Worker * 243*61046927SAndroid Build Coastguard Worker * XOR is again implemented using !=. 244*61046927SAndroid Build Coastguard Worker */ 245*61046927SAndroid Build Coastguard Worker bool lt = ilt64(a.y, a.x, b.y, b.x); 246*61046927SAndroid Build Coastguard Worker bool both_negative = (a.y & b.y & 0x80000000u) != 0; 247*61046927SAndroid Build Coastguard Worker 248*61046927SAndroid Build Coastguard Worker return (lt != both_negative); 249*61046927SAndroid Build Coastguard Worker} 250*61046927SAndroid Build Coastguard Worker 251*61046927SAndroid Build Coastguard Worker/* Returns true if the double-precision floating-point value `a' is less than 252*61046927SAndroid Build Coastguard Worker * the corresponding value `b', and false otherwise. The comparison is performed 253*61046927SAndroid Build Coastguard Worker * according to the IEEE Standard for Floating-Point Arithmetic. 254*61046927SAndroid Build Coastguard Worker */ 255*61046927SAndroid Build Coastguard Workerbool 256*61046927SAndroid Build Coastguard Worker__flt64(uint64_t a, uint64_t b) 257*61046927SAndroid Build Coastguard Worker{ 258*61046927SAndroid Build Coastguard Worker /* This weird layout matters. Doing the "obvious" thing results in extra 259*61046927SAndroid Build Coastguard Worker * flow control being inserted to implement the short-circuit evaluation 260*61046927SAndroid Build Coastguard Worker * rules. Flow control is bad! 261*61046927SAndroid Build Coastguard Worker */ 262*61046927SAndroid Build Coastguard Worker bool x = !__is_nan(a); 263*61046927SAndroid Build Coastguard Worker bool y = !__is_nan(b); 264*61046927SAndroid Build Coastguard Worker bool z = __flt64_nonnan(a, b); 265*61046927SAndroid Build Coastguard Worker 266*61046927SAndroid Build Coastguard Worker return (x && y && z); 267*61046927SAndroid Build Coastguard Worker} 268*61046927SAndroid Build Coastguard Worker 269*61046927SAndroid Build Coastguard Worker/* Returns true if the double-precision floating-point value `a' is greater 270*61046927SAndroid Build Coastguard Worker * than or equal to * the corresponding value `b', and false otherwise. The 271*61046927SAndroid Build Coastguard Worker * comparison is performed * according to the IEEE Standard for Floating-Point 272*61046927SAndroid Build Coastguard Worker * Arithmetic. 273*61046927SAndroid Build Coastguard Worker */ 274*61046927SAndroid Build Coastguard Workerbool 275*61046927SAndroid Build Coastguard Worker__fge64(uint64_t a, uint64_t b) 276*61046927SAndroid Build Coastguard Worker{ 277*61046927SAndroid Build Coastguard Worker /* This weird layout matters. Doing the "obvious" thing results in extra 278*61046927SAndroid Build Coastguard Worker * flow control being inserted to implement the short-circuit evaluation 279*61046927SAndroid Build Coastguard Worker * rules. Flow control is bad! 280*61046927SAndroid Build Coastguard Worker */ 281*61046927SAndroid Build Coastguard Worker bool x = !__is_nan(a); 282*61046927SAndroid Build Coastguard Worker bool y = !__is_nan(b); 283*61046927SAndroid Build Coastguard Worker bool z = !__flt64_nonnan(a, b); 284*61046927SAndroid Build Coastguard Worker 285*61046927SAndroid Build Coastguard Worker return (x && y && z); 286*61046927SAndroid Build Coastguard Worker} 287*61046927SAndroid Build Coastguard Worker 288*61046927SAndroid Build Coastguard Workeruint64_t 289*61046927SAndroid Build Coastguard Worker__fsat64(uint64_t __a) 290*61046927SAndroid Build Coastguard Worker{ 291*61046927SAndroid Build Coastguard Worker uvec2 a = unpackUint2x32(__a); 292*61046927SAndroid Build Coastguard Worker 293*61046927SAndroid Build Coastguard Worker /* fsat(NaN) should be zero. */ 294*61046927SAndroid Build Coastguard Worker if (__is_nan(__a) || int(a.y) < 0) 295*61046927SAndroid Build Coastguard Worker return 0ul; 296*61046927SAndroid Build Coastguard Worker 297*61046927SAndroid Build Coastguard Worker /* IEEE 754 floating point numbers are specifically designed so that, with 298*61046927SAndroid Build Coastguard Worker * two exceptions, values can be compared by bit-casting to signed integers 299*61046927SAndroid Build Coastguard Worker * with the same number of bits. 300*61046927SAndroid Build Coastguard Worker * 301*61046927SAndroid Build Coastguard Worker * From https://en.wikipedia.org/wiki/IEEE_754-1985#Comparing_floating-point_numbers: 302*61046927SAndroid Build Coastguard Worker * 303*61046927SAndroid Build Coastguard Worker * When comparing as 2's-complement integers: If the sign bits differ, 304*61046927SAndroid Build Coastguard Worker * the negative number precedes the positive number, so 2's complement 305*61046927SAndroid Build Coastguard Worker * gives the correct result (except that negative zero and positive zero 306*61046927SAndroid Build Coastguard Worker * should be considered equal). If both values are positive, the 2's 307*61046927SAndroid Build Coastguard Worker * complement comparison again gives the correct result. Otherwise (two 308*61046927SAndroid Build Coastguard Worker * negative numbers), the correct FP ordering is the opposite of the 2's 309*61046927SAndroid Build Coastguard Worker * complement ordering. 310*61046927SAndroid Build Coastguard Worker * 311*61046927SAndroid Build Coastguard Worker * We know that both values are not negative, and we know that at least one 312*61046927SAndroid Build Coastguard Worker * value is not zero. Therefore, we can just use the 2's complement 313*61046927SAndroid Build Coastguard Worker * comparison ordering. 314*61046927SAndroid Build Coastguard Worker */ 315*61046927SAndroid Build Coastguard Worker if (ilt64(0x3FF00000, 0x00000000, a.y, a.x)) 316*61046927SAndroid Build Coastguard Worker return 0x3FF0000000000000ul; 317*61046927SAndroid Build Coastguard Worker 318*61046927SAndroid Build Coastguard Worker return __a; 319*61046927SAndroid Build Coastguard Worker} 320*61046927SAndroid Build Coastguard Worker 321*61046927SAndroid Build Coastguard Worker/* Adds the 64-bit value formed by concatenating `a0' and `a1' to the 64-bit 322*61046927SAndroid Build Coastguard Worker * value formed by concatenating `b0' and `b1'. Addition is modulo 2^64, so 323*61046927SAndroid Build Coastguard Worker * any carry out is lost. The result is broken into two 32-bit pieces which 324*61046927SAndroid Build Coastguard Worker * are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. 325*61046927SAndroid Build Coastguard Worker */ 326*61046927SAndroid Build Coastguard Workervoid 327*61046927SAndroid Build Coastguard Worker__add64(uint a0, uint a1, uint b0, uint b1, 328*61046927SAndroid Build Coastguard Worker out uint z0Ptr, 329*61046927SAndroid Build Coastguard Worker out uint z1Ptr) 330*61046927SAndroid Build Coastguard Worker{ 331*61046927SAndroid Build Coastguard Worker uint z1 = a1 + b1; 332*61046927SAndroid Build Coastguard Worker z1Ptr = z1; 333*61046927SAndroid Build Coastguard Worker z0Ptr = a0 + b0 + uint(z1 < a1); 334*61046927SAndroid Build Coastguard Worker} 335*61046927SAndroid Build Coastguard Worker 336*61046927SAndroid Build Coastguard Worker 337*61046927SAndroid Build Coastguard Worker/* Subtracts the 64-bit value formed by concatenating `b0' and `b1' from the 338*61046927SAndroid Build Coastguard Worker * 64-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo 339*61046927SAndroid Build Coastguard Worker * 2^64, so any borrow out (carry out) is lost. The result is broken into two 340*61046927SAndroid Build Coastguard Worker * 32-bit pieces which are stored at the locations pointed to by `z0Ptr' and 341*61046927SAndroid Build Coastguard Worker * `z1Ptr'. 342*61046927SAndroid Build Coastguard Worker */ 343*61046927SAndroid Build Coastguard Workervoid 344*61046927SAndroid Build Coastguard Worker__sub64(uint a0, uint a1, uint b0, uint b1, 345*61046927SAndroid Build Coastguard Worker out uint z0Ptr, 346*61046927SAndroid Build Coastguard Worker out uint z1Ptr) 347*61046927SAndroid Build Coastguard Worker{ 348*61046927SAndroid Build Coastguard Worker z1Ptr = a1 - b1; 349*61046927SAndroid Build Coastguard Worker z0Ptr = a0 - b0 - uint(a1 < b1); 350*61046927SAndroid Build Coastguard Worker} 351*61046927SAndroid Build Coastguard Worker 352*61046927SAndroid Build Coastguard Worker/* Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the 353*61046927SAndroid Build Coastguard Worker * number of bits given in `count'. If any nonzero bits are shifted off, they 354*61046927SAndroid Build Coastguard Worker * are "jammed" into the least significant bit of the result by setting the 355*61046927SAndroid Build Coastguard Worker * least significant bit to 1. The value of `count' can be arbitrarily large; 356*61046927SAndroid Build Coastguard Worker * in particular, if `count' is greater than 64, the result will be either 0 357*61046927SAndroid Build Coastguard Worker * or 1, depending on whether the concatenation of `a0' and `a1' is zero or 358*61046927SAndroid Build Coastguard Worker * nonzero. The result is broken into two 32-bit pieces which are stored at 359*61046927SAndroid Build Coastguard Worker * the locations pointed to by `z0Ptr' and `z1Ptr'. 360*61046927SAndroid Build Coastguard Worker */ 361*61046927SAndroid Build Coastguard Workervoid 362*61046927SAndroid Build Coastguard Worker__shift64RightJamming(uint a0, 363*61046927SAndroid Build Coastguard Worker uint a1, 364*61046927SAndroid Build Coastguard Worker int count, 365*61046927SAndroid Build Coastguard Worker out uint z0Ptr, 366*61046927SAndroid Build Coastguard Worker out uint z1Ptr) 367*61046927SAndroid Build Coastguard Worker{ 368*61046927SAndroid Build Coastguard Worker uint z0; 369*61046927SAndroid Build Coastguard Worker uint z1; 370*61046927SAndroid Build Coastguard Worker int negCount = (-count) & 31; 371*61046927SAndroid Build Coastguard Worker 372*61046927SAndroid Build Coastguard Worker z0 = mix(0u, a0, count == 0); 373*61046927SAndroid Build Coastguard Worker z0 = mix(z0, (a0 >> count), count < 32); 374*61046927SAndroid Build Coastguard Worker 375*61046927SAndroid Build Coastguard Worker z1 = uint((a0 | a1) != 0u); /* count >= 64 */ 376*61046927SAndroid Build Coastguard Worker uint z1_lt64 = (a0>>(count & 31)) | uint(((a0<<negCount) | a1) != 0u); 377*61046927SAndroid Build Coastguard Worker z1 = mix(z1, z1_lt64, count < 64); 378*61046927SAndroid Build Coastguard Worker z1 = mix(z1, (a0 | uint(a1 != 0u)), count == 32); 379*61046927SAndroid Build Coastguard Worker uint z1_lt32 = (a0<<negCount) | (a1>>count) | uint ((a1<<negCount) != 0u); 380*61046927SAndroid Build Coastguard Worker z1 = mix(z1, z1_lt32, count < 32); 381*61046927SAndroid Build Coastguard Worker z1 = mix(z1, a1, count == 0); 382*61046927SAndroid Build Coastguard Worker z1Ptr = z1; 383*61046927SAndroid Build Coastguard Worker z0Ptr = z0; 384*61046927SAndroid Build Coastguard Worker} 385*61046927SAndroid Build Coastguard Worker 386*61046927SAndroid Build Coastguard Worker/* Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' right 387*61046927SAndroid Build Coastguard Worker * by 32 _plus_ the number of bits given in `count'. The shifted result is 388*61046927SAndroid Build Coastguard Worker * at most 64 nonzero bits; these are broken into two 32-bit pieces which are 389*61046927SAndroid Build Coastguard Worker * stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted 390*61046927SAndroid Build Coastguard Worker * off form a third 32-bit result as follows: The _last_ bit shifted off is 391*61046927SAndroid Build Coastguard Worker * the most-significant bit of the extra result, and the other 31 bits of the 392*61046927SAndroid Build Coastguard Worker * extra result are all zero if and only if _all_but_the_last_ bits shifted off 393*61046927SAndroid Build Coastguard Worker * were all zero. This extra result is stored in the location pointed to by 394*61046927SAndroid Build Coastguard Worker * `z2Ptr'. The value of `count' can be arbitrarily large. 395*61046927SAndroid Build Coastguard Worker * (This routine makes more sense if `a0', `a1', and `a2' are considered 396*61046927SAndroid Build Coastguard Worker * to form a fixed-point value with binary point between `a1' and `a2'. This 397*61046927SAndroid Build Coastguard Worker * fixed-point value is shifted right by the number of bits given in `count', 398*61046927SAndroid Build Coastguard Worker * and the integer part of the result is returned at the locations pointed to 399*61046927SAndroid Build Coastguard Worker * by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly 400*61046927SAndroid Build Coastguard Worker * corrupted as described above, and is returned at the location pointed to by 401*61046927SAndroid Build Coastguard Worker * `z2Ptr'.) 402*61046927SAndroid Build Coastguard Worker */ 403*61046927SAndroid Build Coastguard Workervoid 404*61046927SAndroid Build Coastguard Worker__shift64ExtraRightJamming(uint a0, uint a1, uint a2, 405*61046927SAndroid Build Coastguard Worker int count, 406*61046927SAndroid Build Coastguard Worker out uint z0Ptr, 407*61046927SAndroid Build Coastguard Worker out uint z1Ptr, 408*61046927SAndroid Build Coastguard Worker out uint z2Ptr) 409*61046927SAndroid Build Coastguard Worker{ 410*61046927SAndroid Build Coastguard Worker uint z0 = 0u; 411*61046927SAndroid Build Coastguard Worker uint z1; 412*61046927SAndroid Build Coastguard Worker uint z2; 413*61046927SAndroid Build Coastguard Worker int negCount = (-count) & 31; 414*61046927SAndroid Build Coastguard Worker 415*61046927SAndroid Build Coastguard Worker z2 = mix(uint(a0 != 0u), a0, count == 64); 416*61046927SAndroid Build Coastguard Worker z2 = mix(z2, a0 << negCount, count < 64); 417*61046927SAndroid Build Coastguard Worker z2 = mix(z2, a1 << negCount, count < 32); 418*61046927SAndroid Build Coastguard Worker 419*61046927SAndroid Build Coastguard Worker z1 = mix(0u, (a0 >> (count & 31)), count < 64); 420*61046927SAndroid Build Coastguard Worker z1 = mix(z1, (a0<<negCount) | (a1>>count), count < 32); 421*61046927SAndroid Build Coastguard Worker 422*61046927SAndroid Build Coastguard Worker a2 = mix(a2 | a1, a2, count < 32); 423*61046927SAndroid Build Coastguard Worker z0 = mix(z0, a0 >> count, count < 32); 424*61046927SAndroid Build Coastguard Worker z2 |= uint(a2 != 0u); 425*61046927SAndroid Build Coastguard Worker 426*61046927SAndroid Build Coastguard Worker z0 = mix(z0, 0u, (count == 32)); 427*61046927SAndroid Build Coastguard Worker z1 = mix(z1, a0, (count == 32)); 428*61046927SAndroid Build Coastguard Worker z2 = mix(z2, a1, (count == 32)); 429*61046927SAndroid Build Coastguard Worker z0 = mix(z0, a0, (count == 0)); 430*61046927SAndroid Build Coastguard Worker z1 = mix(z1, a1, (count == 0)); 431*61046927SAndroid Build Coastguard Worker z2 = mix(z2, a2, (count == 0)); 432*61046927SAndroid Build Coastguard Worker z2Ptr = z2; 433*61046927SAndroid Build Coastguard Worker z1Ptr = z1; 434*61046927SAndroid Build Coastguard Worker z0Ptr = z0; 435*61046927SAndroid Build Coastguard Worker} 436*61046927SAndroid Build Coastguard Worker 437*61046927SAndroid Build Coastguard Worker/* Shifts the 64-bit value formed by concatenating `a0' and `a1' left by the 438*61046927SAndroid Build Coastguard Worker * number of bits given in `count'. Any bits shifted off are lost. The value 439*61046927SAndroid Build Coastguard Worker * of `count' must be less than 32. The result is broken into two 32-bit 440*61046927SAndroid Build Coastguard Worker * pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. 441*61046927SAndroid Build Coastguard Worker */ 442*61046927SAndroid Build Coastguard Workervoid 443*61046927SAndroid Build Coastguard Worker__shortShift64Left(uint a0, uint a1, 444*61046927SAndroid Build Coastguard Worker int count, 445*61046927SAndroid Build Coastguard Worker out uint z0Ptr, 446*61046927SAndroid Build Coastguard Worker out uint z1Ptr) 447*61046927SAndroid Build Coastguard Worker{ 448*61046927SAndroid Build Coastguard Worker z1Ptr = a1<<count; 449*61046927SAndroid Build Coastguard Worker z0Ptr = mix((a0 << count | (a1 >> ((-count) & 31))), a0, count == 0); 450*61046927SAndroid Build Coastguard Worker} 451*61046927SAndroid Build Coastguard Worker 452*61046927SAndroid Build Coastguard Worker/* Packs the sign `zSign', the exponent `zExp', and the significand formed by 453*61046927SAndroid Build Coastguard Worker * the concatenation of `zFrac0' and `zFrac1' into a double-precision floating- 454*61046927SAndroid Build Coastguard Worker * point value, returning the result. After being shifted into the proper 455*61046927SAndroid Build Coastguard Worker * positions, the three fields `zSign', `zExp', and `zFrac0' are simply added 456*61046927SAndroid Build Coastguard Worker * together to form the most significant 32 bits of the result. This means 457*61046927SAndroid Build Coastguard Worker * that any integer portion of `zFrac0' will be added into the exponent. Since 458*61046927SAndroid Build Coastguard Worker * a properly normalized significand will have an integer portion equal to 1, 459*61046927SAndroid Build Coastguard Worker * the `zExp' input should be 1 less than the desired result exponent whenever 460*61046927SAndroid Build Coastguard Worker * `zFrac0' and `zFrac1' concatenated form a complete, normalized significand. 461*61046927SAndroid Build Coastguard Worker */ 462*61046927SAndroid Build Coastguard Workeruint64_t 463*61046927SAndroid Build Coastguard Worker__packFloat64(uint zSign, int zExp, uint zFrac0, uint zFrac1) 464*61046927SAndroid Build Coastguard Worker{ 465*61046927SAndroid Build Coastguard Worker uvec2 z; 466*61046927SAndroid Build Coastguard Worker 467*61046927SAndroid Build Coastguard Worker z.y = zSign + (uint(zExp) << 20) + zFrac0; 468*61046927SAndroid Build Coastguard Worker z.x = zFrac1; 469*61046927SAndroid Build Coastguard Worker return packUint2x32(z); 470*61046927SAndroid Build Coastguard Worker} 471*61046927SAndroid Build Coastguard Worker 472*61046927SAndroid Build Coastguard Worker/* Takes an abstract floating-point value having sign `zSign', exponent `zExp', 473*61046927SAndroid Build Coastguard Worker * and extended significand formed by the concatenation of `zFrac0', `zFrac1', 474*61046927SAndroid Build Coastguard Worker * and `zFrac2', and returns the proper double-precision floating-point value 475*61046927SAndroid Build Coastguard Worker * corresponding to the abstract input. Ordinarily, the abstract value is 476*61046927SAndroid Build Coastguard Worker * simply rounded and packed into the double-precision format, with the inexact 477*61046927SAndroid Build Coastguard Worker * exception raised if the abstract input cannot be represented exactly. 478*61046927SAndroid Build Coastguard Worker * However, if the abstract value is too large, the overflow and inexact 479*61046927SAndroid Build Coastguard Worker * exceptions are raised and an infinity or maximal finite value is returned. 480*61046927SAndroid Build Coastguard Worker * If the abstract value is too small, the input value is rounded to a 481*61046927SAndroid Build Coastguard Worker * subnormal number, and the underflow and inexact exceptions are raised if the 482*61046927SAndroid Build Coastguard Worker * abstract input cannot be represented exactly as a subnormal double-precision 483*61046927SAndroid Build Coastguard Worker * floating-point number. 484*61046927SAndroid Build Coastguard Worker * The input significand must be normalized or smaller. If the input 485*61046927SAndroid Build Coastguard Worker * significand is not normalized, `zExp' must be 0; in that case, the result 486*61046927SAndroid Build Coastguard Worker * returned is a subnormal number, and it must not require rounding. In the 487*61046927SAndroid Build Coastguard Worker * usual case that the input significand is normalized, `zExp' must be 1 less 488*61046927SAndroid Build Coastguard Worker * than the "true" floating-point exponent. The handling of underflow and 489*61046927SAndroid Build Coastguard Worker * overflow follows the IEEE Standard for Floating-Point Arithmetic. 490*61046927SAndroid Build Coastguard Worker */ 491*61046927SAndroid Build Coastguard Workeruint64_t 492*61046927SAndroid Build Coastguard Worker__roundAndPackFloat64(uint zSign, 493*61046927SAndroid Build Coastguard Worker int zExp, 494*61046927SAndroid Build Coastguard Worker uint zFrac0, 495*61046927SAndroid Build Coastguard Worker uint zFrac1, 496*61046927SAndroid Build Coastguard Worker uint zFrac2) 497*61046927SAndroid Build Coastguard Worker{ 498*61046927SAndroid Build Coastguard Worker bool roundNearestEven; 499*61046927SAndroid Build Coastguard Worker bool increment; 500*61046927SAndroid Build Coastguard Worker 501*61046927SAndroid Build Coastguard Worker roundNearestEven = FLOAT_ROUNDING_MODE == FLOAT_ROUND_NEAREST_EVEN; 502*61046927SAndroid Build Coastguard Worker increment = int(zFrac2) < 0; 503*61046927SAndroid Build Coastguard Worker if (!roundNearestEven) { 504*61046927SAndroid Build Coastguard Worker if (FLOAT_ROUNDING_MODE == FLOAT_ROUND_TO_ZERO) { 505*61046927SAndroid Build Coastguard Worker increment = false; 506*61046927SAndroid Build Coastguard Worker } else { 507*61046927SAndroid Build Coastguard Worker if (zSign != 0u) { 508*61046927SAndroid Build Coastguard Worker increment = (FLOAT_ROUNDING_MODE == FLOAT_ROUND_DOWN) && 509*61046927SAndroid Build Coastguard Worker (zFrac2 != 0u); 510*61046927SAndroid Build Coastguard Worker } else { 511*61046927SAndroid Build Coastguard Worker increment = (FLOAT_ROUNDING_MODE == FLOAT_ROUND_UP) && 512*61046927SAndroid Build Coastguard Worker (zFrac2 != 0u); 513*61046927SAndroid Build Coastguard Worker } 514*61046927SAndroid Build Coastguard Worker } 515*61046927SAndroid Build Coastguard Worker } 516*61046927SAndroid Build Coastguard Worker if (0x7FD <= zExp) { 517*61046927SAndroid Build Coastguard Worker if ((0x7FD < zExp) || 518*61046927SAndroid Build Coastguard Worker ((zExp == 0x7FD) && 519*61046927SAndroid Build Coastguard Worker (0x001FFFFFu == zFrac0 && 0xFFFFFFFFu == zFrac1) && 520*61046927SAndroid Build Coastguard Worker increment)) { 521*61046927SAndroid Build Coastguard Worker if ((FLOAT_ROUNDING_MODE == FLOAT_ROUND_TO_ZERO) || 522*61046927SAndroid Build Coastguard Worker ((zSign != 0u) && (FLOAT_ROUNDING_MODE == FLOAT_ROUND_UP)) || 523*61046927SAndroid Build Coastguard Worker ((zSign == 0u) && (FLOAT_ROUNDING_MODE == FLOAT_ROUND_DOWN))) { 524*61046927SAndroid Build Coastguard Worker return __packFloat64(zSign, 0x7FE, 0x000FFFFFu, 0xFFFFFFFFu); 525*61046927SAndroid Build Coastguard Worker } 526*61046927SAndroid Build Coastguard Worker return __packFloat64(zSign, 0x7FF, 0u, 0u); 527*61046927SAndroid Build Coastguard Worker } 528*61046927SAndroid Build Coastguard Worker } 529*61046927SAndroid Build Coastguard Worker 530*61046927SAndroid Build Coastguard Worker if (zExp < 0) { 531*61046927SAndroid Build Coastguard Worker __shift64ExtraRightJamming( 532*61046927SAndroid Build Coastguard Worker zFrac0, zFrac1, zFrac2, -zExp, zFrac0, zFrac1, zFrac2); 533*61046927SAndroid Build Coastguard Worker zExp = 0; 534*61046927SAndroid Build Coastguard Worker if (roundNearestEven) { 535*61046927SAndroid Build Coastguard Worker increment = zFrac2 < 0u; 536*61046927SAndroid Build Coastguard Worker } else { 537*61046927SAndroid Build Coastguard Worker if (zSign != 0u) { 538*61046927SAndroid Build Coastguard Worker increment = (FLOAT_ROUNDING_MODE == FLOAT_ROUND_DOWN) && 539*61046927SAndroid Build Coastguard Worker (zFrac2 != 0u); 540*61046927SAndroid Build Coastguard Worker } else { 541*61046927SAndroid Build Coastguard Worker increment = (FLOAT_ROUNDING_MODE == FLOAT_ROUND_UP) && 542*61046927SAndroid Build Coastguard Worker (zFrac2 != 0u); 543*61046927SAndroid Build Coastguard Worker } 544*61046927SAndroid Build Coastguard Worker } 545*61046927SAndroid Build Coastguard Worker } 546*61046927SAndroid Build Coastguard Worker 547*61046927SAndroid Build Coastguard Worker if (increment) { 548*61046927SAndroid Build Coastguard Worker __add64(zFrac0, zFrac1, 0u, 1u, zFrac0, zFrac1); 549*61046927SAndroid Build Coastguard Worker zFrac1 &= ~((zFrac2 + uint(zFrac2 == 0u)) & uint(roundNearestEven)); 550*61046927SAndroid Build Coastguard Worker } else { 551*61046927SAndroid Build Coastguard Worker zExp = mix(zExp, 0, (zFrac0 | zFrac1) == 0u); 552*61046927SAndroid Build Coastguard Worker } 553*61046927SAndroid Build Coastguard Worker return __packFloat64(zSign, zExp, zFrac0, zFrac1); 554*61046927SAndroid Build Coastguard Worker} 555*61046927SAndroid Build Coastguard Worker 556*61046927SAndroid Build Coastguard Workeruint64_t 557*61046927SAndroid Build Coastguard Worker__roundAndPackUInt64(uint zSign, uint zFrac0, uint zFrac1, uint zFrac2) 558*61046927SAndroid Build Coastguard Worker{ 559*61046927SAndroid Build Coastguard Worker bool roundNearestEven; 560*61046927SAndroid Build Coastguard Worker bool increment; 561*61046927SAndroid Build Coastguard Worker uint64_t default_nan = 0xFFFFFFFFFFFFFFFFUL; 562*61046927SAndroid Build Coastguard Worker 563*61046927SAndroid Build Coastguard Worker roundNearestEven = FLOAT_ROUNDING_MODE == FLOAT_ROUND_NEAREST_EVEN; 564*61046927SAndroid Build Coastguard Worker 565*61046927SAndroid Build Coastguard Worker if (zFrac2 >= 0x80000000u) 566*61046927SAndroid Build Coastguard Worker increment = false; 567*61046927SAndroid Build Coastguard Worker 568*61046927SAndroid Build Coastguard Worker if (!roundNearestEven) { 569*61046927SAndroid Build Coastguard Worker if (zSign != 0u) { 570*61046927SAndroid Build Coastguard Worker if ((FLOAT_ROUNDING_MODE == FLOAT_ROUND_DOWN) && (zFrac2 != 0u)) { 571*61046927SAndroid Build Coastguard Worker increment = false; 572*61046927SAndroid Build Coastguard Worker } 573*61046927SAndroid Build Coastguard Worker } else { 574*61046927SAndroid Build Coastguard Worker increment = (FLOAT_ROUNDING_MODE == FLOAT_ROUND_UP) && 575*61046927SAndroid Build Coastguard Worker (zFrac2 != 0u); 576*61046927SAndroid Build Coastguard Worker } 577*61046927SAndroid Build Coastguard Worker } 578*61046927SAndroid Build Coastguard Worker 579*61046927SAndroid Build Coastguard Worker if (increment) { 580*61046927SAndroid Build Coastguard Worker __add64(zFrac0, zFrac1, 0u, 1u, zFrac0, zFrac1); 581*61046927SAndroid Build Coastguard Worker if ((zFrac0 | zFrac1) != 0u) 582*61046927SAndroid Build Coastguard Worker zFrac1 &= ~(1u) + uint(zFrac2 == 0u) & uint(roundNearestEven); 583*61046927SAndroid Build Coastguard Worker } 584*61046927SAndroid Build Coastguard Worker return mix(packUint2x32(uvec2(zFrac1, zFrac0)), default_nan, 585*61046927SAndroid Build Coastguard Worker (zSign != 0u && (zFrac0 | zFrac1) != 0u)); 586*61046927SAndroid Build Coastguard Worker} 587*61046927SAndroid Build Coastguard Worker 588*61046927SAndroid Build Coastguard Workerint64_t 589*61046927SAndroid Build Coastguard Worker__roundAndPackInt64(uint zSign, uint zFrac0, uint zFrac1, uint zFrac2) 590*61046927SAndroid Build Coastguard Worker{ 591*61046927SAndroid Build Coastguard Worker bool roundNearestEven; 592*61046927SAndroid Build Coastguard Worker bool increment; 593*61046927SAndroid Build Coastguard Worker int64_t default_NegNaN = -0x7FFFFFFFFFFFFFFEL; 594*61046927SAndroid Build Coastguard Worker int64_t default_PosNaN = 0xFFFFFFFFFFFFFFFFL; 595*61046927SAndroid Build Coastguard Worker 596*61046927SAndroid Build Coastguard Worker roundNearestEven = FLOAT_ROUNDING_MODE == FLOAT_ROUND_NEAREST_EVEN; 597*61046927SAndroid Build Coastguard Worker 598*61046927SAndroid Build Coastguard Worker if (zFrac2 >= 0x80000000u) 599*61046927SAndroid Build Coastguard Worker increment = false; 600*61046927SAndroid Build Coastguard Worker 601*61046927SAndroid Build Coastguard Worker if (!roundNearestEven) { 602*61046927SAndroid Build Coastguard Worker if (zSign != 0u) { 603*61046927SAndroid Build Coastguard Worker increment = ((FLOAT_ROUNDING_MODE == FLOAT_ROUND_DOWN) && 604*61046927SAndroid Build Coastguard Worker (zFrac2 != 0u)); 605*61046927SAndroid Build Coastguard Worker } else { 606*61046927SAndroid Build Coastguard Worker increment = (FLOAT_ROUNDING_MODE == FLOAT_ROUND_UP) && 607*61046927SAndroid Build Coastguard Worker (zFrac2 != 0u); 608*61046927SAndroid Build Coastguard Worker } 609*61046927SAndroid Build Coastguard Worker } 610*61046927SAndroid Build Coastguard Worker 611*61046927SAndroid Build Coastguard Worker if (increment) { 612*61046927SAndroid Build Coastguard Worker __add64(zFrac0, zFrac1, 0u, 1u, zFrac0, zFrac1); 613*61046927SAndroid Build Coastguard Worker if ((zFrac0 | zFrac1) != 0u) 614*61046927SAndroid Build Coastguard Worker zFrac1 &= ~(1u) + uint(zFrac2 == 0u) & uint(roundNearestEven); 615*61046927SAndroid Build Coastguard Worker } 616*61046927SAndroid Build Coastguard Worker 617*61046927SAndroid Build Coastguard Worker int64_t absZ = mix(int64_t(packUint2x32(uvec2(zFrac1, zFrac0))), 618*61046927SAndroid Build Coastguard Worker -int64_t(packUint2x32(uvec2(zFrac1, zFrac0))), 619*61046927SAndroid Build Coastguard Worker zSign != 0u); 620*61046927SAndroid Build Coastguard Worker int64_t nan = mix(default_PosNaN, default_NegNaN, zSign != 0u); 621*61046927SAndroid Build Coastguard Worker return mix(absZ, nan, ((zSign != 0u) != (absZ < 0)) && bool(absZ)); 622*61046927SAndroid Build Coastguard Worker} 623*61046927SAndroid Build Coastguard Worker 624*61046927SAndroid Build Coastguard Worker/* Returns the number of leading 0 bits before the most-significant 1 bit of 625*61046927SAndroid Build Coastguard Worker * `a'. If `a' is zero, 32 is returned. 626*61046927SAndroid Build Coastguard Worker */ 627*61046927SAndroid Build Coastguard Workerint 628*61046927SAndroid Build Coastguard Worker__countLeadingZeros32(uint a) 629*61046927SAndroid Build Coastguard Worker{ 630*61046927SAndroid Build Coastguard Worker return 31 - findMSB(a); 631*61046927SAndroid Build Coastguard Worker} 632*61046927SAndroid Build Coastguard Worker 633*61046927SAndroid Build Coastguard Worker/* Takes an abstract floating-point value having sign `zSign', exponent `zExp', 634*61046927SAndroid Build Coastguard Worker * and significand formed by the concatenation of `zSig0' and `zSig1', and 635*61046927SAndroid Build Coastguard Worker * returns the proper double-precision floating-point value corresponding 636*61046927SAndroid Build Coastguard Worker * to the abstract input. This routine is just like `__roundAndPackFloat64' 637*61046927SAndroid Build Coastguard Worker * except that the input significand has fewer bits and does not have to be 638*61046927SAndroid Build Coastguard Worker * normalized. In all cases, `zExp' must be 1 less than the "true" floating- 639*61046927SAndroid Build Coastguard Worker * point exponent. 640*61046927SAndroid Build Coastguard Worker */ 641*61046927SAndroid Build Coastguard Workeruint64_t 642*61046927SAndroid Build Coastguard Worker__normalizeRoundAndPackFloat64(uint zSign, 643*61046927SAndroid Build Coastguard Worker int zExp, 644*61046927SAndroid Build Coastguard Worker uint zFrac0, 645*61046927SAndroid Build Coastguard Worker uint zFrac1) 646*61046927SAndroid Build Coastguard Worker{ 647*61046927SAndroid Build Coastguard Worker int shiftCount; 648*61046927SAndroid Build Coastguard Worker uint zFrac2; 649*61046927SAndroid Build Coastguard Worker 650*61046927SAndroid Build Coastguard Worker if (zFrac0 == 0u) { 651*61046927SAndroid Build Coastguard Worker zExp -= 32; 652*61046927SAndroid Build Coastguard Worker zFrac0 = zFrac1; 653*61046927SAndroid Build Coastguard Worker zFrac1 = 0u; 654*61046927SAndroid Build Coastguard Worker } 655*61046927SAndroid Build Coastguard Worker 656*61046927SAndroid Build Coastguard Worker shiftCount = __countLeadingZeros32(zFrac0) - 11; 657*61046927SAndroid Build Coastguard Worker if (0 <= shiftCount) { 658*61046927SAndroid Build Coastguard Worker zFrac2 = 0u; 659*61046927SAndroid Build Coastguard Worker __shortShift64Left(zFrac0, zFrac1, shiftCount, zFrac0, zFrac1); 660*61046927SAndroid Build Coastguard Worker } else { 661*61046927SAndroid Build Coastguard Worker __shift64ExtraRightJamming( 662*61046927SAndroid Build Coastguard Worker zFrac0, zFrac1, 0u, -shiftCount, zFrac0, zFrac1, zFrac2); 663*61046927SAndroid Build Coastguard Worker } 664*61046927SAndroid Build Coastguard Worker zExp -= shiftCount; 665*61046927SAndroid Build Coastguard Worker return __roundAndPackFloat64(zSign, zExp, zFrac0, zFrac1, zFrac2); 666*61046927SAndroid Build Coastguard Worker} 667*61046927SAndroid Build Coastguard Worker 668*61046927SAndroid Build Coastguard Worker/* Takes two double-precision floating-point values `a' and `b', one of which 669*61046927SAndroid Build Coastguard Worker * is a NaN, and returns the appropriate NaN result. 670*61046927SAndroid Build Coastguard Worker */ 671*61046927SAndroid Build Coastguard Workeruint64_t 672*61046927SAndroid Build Coastguard Worker__propagateFloat64NaN(uint64_t __a, uint64_t __b) 673*61046927SAndroid Build Coastguard Worker{ 674*61046927SAndroid Build Coastguard Worker#if defined RELAXED_NAN_PROPAGATION 675*61046927SAndroid Build Coastguard Worker uvec2 a = unpackUint2x32(__a); 676*61046927SAndroid Build Coastguard Worker uvec2 b = unpackUint2x32(__b); 677*61046927SAndroid Build Coastguard Worker 678*61046927SAndroid Build Coastguard Worker return packUint2x32(uvec2(a.x | b.x, a.y | b.y)); 679*61046927SAndroid Build Coastguard Worker#else 680*61046927SAndroid Build Coastguard Worker bool aIsNaN = __is_nan(__a); 681*61046927SAndroid Build Coastguard Worker bool bIsNaN = __is_nan(__b); 682*61046927SAndroid Build Coastguard Worker uvec2 a = unpackUint2x32(__a); 683*61046927SAndroid Build Coastguard Worker uvec2 b = unpackUint2x32(__b); 684*61046927SAndroid Build Coastguard Worker a.y |= 0x00080000u; 685*61046927SAndroid Build Coastguard Worker b.y |= 0x00080000u; 686*61046927SAndroid Build Coastguard Worker 687*61046927SAndroid Build Coastguard Worker return packUint2x32(mix(b, mix(a, b, bvec2(bIsNaN, bIsNaN)), bvec2(aIsNaN, aIsNaN))); 688*61046927SAndroid Build Coastguard Worker#endif 689*61046927SAndroid Build Coastguard Worker} 690*61046927SAndroid Build Coastguard Worker 691*61046927SAndroid Build Coastguard Worker/* If a shader is in the soft-fp64 path, it almost certainly has register 692*61046927SAndroid Build Coastguard Worker * pressure problems. Choose a method to exchange two values that does not 693*61046927SAndroid Build Coastguard Worker * require a temporary. 694*61046927SAndroid Build Coastguard Worker */ 695*61046927SAndroid Build Coastguard Worker#define EXCHANGE(a, b) \ 696*61046927SAndroid Build Coastguard Worker do { \ 697*61046927SAndroid Build Coastguard Worker a ^= b; \ 698*61046927SAndroid Build Coastguard Worker b ^= a; \ 699*61046927SAndroid Build Coastguard Worker a ^= b; \ 700*61046927SAndroid Build Coastguard Worker } while (false) 701*61046927SAndroid Build Coastguard Worker 702*61046927SAndroid Build Coastguard Worker/* Returns the result of adding the double-precision floating-point values 703*61046927SAndroid Build Coastguard Worker * `a' and `b'. The operation is performed according to the IEEE Standard for 704*61046927SAndroid Build Coastguard Worker * Floating-Point Arithmetic. 705*61046927SAndroid Build Coastguard Worker */ 706*61046927SAndroid Build Coastguard Workeruint64_t 707*61046927SAndroid Build Coastguard Worker__fadd64(uint64_t a, uint64_t b) 708*61046927SAndroid Build Coastguard Worker{ 709*61046927SAndroid Build Coastguard Worker uint aSign = __extractFloat64Sign(a); 710*61046927SAndroid Build Coastguard Worker uint bSign = __extractFloat64Sign(b); 711*61046927SAndroid Build Coastguard Worker uint aFracLo = __extractFloat64FracLo(a); 712*61046927SAndroid Build Coastguard Worker uint aFracHi = __extractFloat64FracHi(a); 713*61046927SAndroid Build Coastguard Worker uint bFracLo = __extractFloat64FracLo(b); 714*61046927SAndroid Build Coastguard Worker uint bFracHi = __extractFloat64FracHi(b); 715*61046927SAndroid Build Coastguard Worker int aExp = __extractFloat64Exp(a); 716*61046927SAndroid Build Coastguard Worker int bExp = __extractFloat64Exp(b); 717*61046927SAndroid Build Coastguard Worker int expDiff = aExp - bExp; 718*61046927SAndroid Build Coastguard Worker if (aSign == bSign) { 719*61046927SAndroid Build Coastguard Worker uint zFrac0; 720*61046927SAndroid Build Coastguard Worker uint zFrac1; 721*61046927SAndroid Build Coastguard Worker uint zFrac2; 722*61046927SAndroid Build Coastguard Worker int zExp; 723*61046927SAndroid Build Coastguard Worker 724*61046927SAndroid Build Coastguard Worker if (expDiff == 0) { 725*61046927SAndroid Build Coastguard Worker if (aExp == 0x7FF) { 726*61046927SAndroid Build Coastguard Worker bool propagate = ((aFracHi | bFracHi) | (aFracLo| bFracLo)) != 0u; 727*61046927SAndroid Build Coastguard Worker return mix(a, __propagateFloat64NaN(a, b), propagate); 728*61046927SAndroid Build Coastguard Worker } 729*61046927SAndroid Build Coastguard Worker __add64(aFracHi, aFracLo, bFracHi, bFracLo, zFrac0, zFrac1); 730*61046927SAndroid Build Coastguard Worker if (aExp == 0) 731*61046927SAndroid Build Coastguard Worker return __packFloat64(aSign, 0, zFrac0, zFrac1); 732*61046927SAndroid Build Coastguard Worker zFrac2 = 0u; 733*61046927SAndroid Build Coastguard Worker zFrac0 |= 0x00200000u; 734*61046927SAndroid Build Coastguard Worker zExp = aExp; 735*61046927SAndroid Build Coastguard Worker __shift64ExtraRightJamming( 736*61046927SAndroid Build Coastguard Worker zFrac0, zFrac1, zFrac2, 1, zFrac0, zFrac1, zFrac2); 737*61046927SAndroid Build Coastguard Worker } else { 738*61046927SAndroid Build Coastguard Worker if (expDiff < 0) { 739*61046927SAndroid Build Coastguard Worker EXCHANGE(aFracHi, bFracHi); 740*61046927SAndroid Build Coastguard Worker EXCHANGE(aFracLo, bFracLo); 741*61046927SAndroid Build Coastguard Worker EXCHANGE(aExp, bExp); 742*61046927SAndroid Build Coastguard Worker } 743*61046927SAndroid Build Coastguard Worker 744*61046927SAndroid Build Coastguard Worker if (aExp == 0x7FF) { 745*61046927SAndroid Build Coastguard Worker bool propagate = (aFracHi | aFracLo) != 0u; 746*61046927SAndroid Build Coastguard Worker return mix(__packFloat64(aSign, 0x7ff, 0u, 0u), __propagateFloat64NaN(a, b), propagate); 747*61046927SAndroid Build Coastguard Worker } 748*61046927SAndroid Build Coastguard Worker 749*61046927SAndroid Build Coastguard Worker expDiff = mix(abs(expDiff), abs(expDiff) - 1, bExp == 0); 750*61046927SAndroid Build Coastguard Worker bFracHi = mix(bFracHi | 0x00100000u, bFracHi, bExp == 0); 751*61046927SAndroid Build Coastguard Worker __shift64ExtraRightJamming( 752*61046927SAndroid Build Coastguard Worker bFracHi, bFracLo, 0u, expDiff, bFracHi, bFracLo, zFrac2); 753*61046927SAndroid Build Coastguard Worker zExp = aExp; 754*61046927SAndroid Build Coastguard Worker 755*61046927SAndroid Build Coastguard Worker aFracHi |= 0x00100000u; 756*61046927SAndroid Build Coastguard Worker __add64(aFracHi, aFracLo, bFracHi, bFracLo, zFrac0, zFrac1); 757*61046927SAndroid Build Coastguard Worker --zExp; 758*61046927SAndroid Build Coastguard Worker if (!(zFrac0 < 0x00200000u)) { 759*61046927SAndroid Build Coastguard Worker __shift64ExtraRightJamming(zFrac0, zFrac1, zFrac2, 1, zFrac0, zFrac1, zFrac2); 760*61046927SAndroid Build Coastguard Worker ++zExp; 761*61046927SAndroid Build Coastguard Worker } 762*61046927SAndroid Build Coastguard Worker } 763*61046927SAndroid Build Coastguard Worker return __roundAndPackFloat64(aSign, zExp, zFrac0, zFrac1, zFrac2); 764*61046927SAndroid Build Coastguard Worker 765*61046927SAndroid Build Coastguard Worker } else { 766*61046927SAndroid Build Coastguard Worker int zExp; 767*61046927SAndroid Build Coastguard Worker 768*61046927SAndroid Build Coastguard Worker __shortShift64Left(aFracHi, aFracLo, 10, aFracHi, aFracLo); 769*61046927SAndroid Build Coastguard Worker __shortShift64Left(bFracHi, bFracLo, 10, bFracHi, bFracLo); 770*61046927SAndroid Build Coastguard Worker if (expDiff != 0) { 771*61046927SAndroid Build Coastguard Worker uint zFrac0; 772*61046927SAndroid Build Coastguard Worker uint zFrac1; 773*61046927SAndroid Build Coastguard Worker 774*61046927SAndroid Build Coastguard Worker if (expDiff < 0) { 775*61046927SAndroid Build Coastguard Worker EXCHANGE(aFracHi, bFracHi); 776*61046927SAndroid Build Coastguard Worker EXCHANGE(aFracLo, bFracLo); 777*61046927SAndroid Build Coastguard Worker EXCHANGE(aExp, bExp); 778*61046927SAndroid Build Coastguard Worker aSign ^= 0x80000000u; 779*61046927SAndroid Build Coastguard Worker } 780*61046927SAndroid Build Coastguard Worker 781*61046927SAndroid Build Coastguard Worker if (aExp == 0x7FF) { 782*61046927SAndroid Build Coastguard Worker bool propagate = (aFracHi | aFracLo) != 0u; 783*61046927SAndroid Build Coastguard Worker return mix(__packFloat64(aSign, 0x7ff, 0u, 0u), __propagateFloat64NaN(a, b), propagate); 784*61046927SAndroid Build Coastguard Worker } 785*61046927SAndroid Build Coastguard Worker 786*61046927SAndroid Build Coastguard Worker expDiff = mix(abs(expDiff), abs(expDiff) - 1, bExp == 0); 787*61046927SAndroid Build Coastguard Worker bFracHi = mix(bFracHi | 0x40000000u, bFracHi, bExp == 0); 788*61046927SAndroid Build Coastguard Worker __shift64RightJamming(bFracHi, bFracLo, expDiff, bFracHi, bFracLo); 789*61046927SAndroid Build Coastguard Worker aFracHi |= 0x40000000u; 790*61046927SAndroid Build Coastguard Worker __sub64(aFracHi, aFracLo, bFracHi, bFracLo, zFrac0, zFrac1); 791*61046927SAndroid Build Coastguard Worker zExp = aExp; 792*61046927SAndroid Build Coastguard Worker --zExp; 793*61046927SAndroid Build Coastguard Worker return __normalizeRoundAndPackFloat64(aSign, zExp - 10, zFrac0, zFrac1); 794*61046927SAndroid Build Coastguard Worker } 795*61046927SAndroid Build Coastguard Worker if (aExp == 0x7FF) { 796*61046927SAndroid Build Coastguard Worker bool propagate = ((aFracHi | bFracHi) | (aFracLo | bFracLo)) != 0u; 797*61046927SAndroid Build Coastguard Worker return mix(0xFFFFFFFFFFFFFFFFUL, __propagateFloat64NaN(a, b), propagate); 798*61046927SAndroid Build Coastguard Worker } 799*61046927SAndroid Build Coastguard Worker bExp = mix(bExp, 1, aExp == 0); 800*61046927SAndroid Build Coastguard Worker aExp = mix(aExp, 1, aExp == 0); 801*61046927SAndroid Build Coastguard Worker 802*61046927SAndroid Build Coastguard Worker uint zFrac0; 803*61046927SAndroid Build Coastguard Worker uint zFrac1; 804*61046927SAndroid Build Coastguard Worker uint sign_of_difference = 0; 805*61046927SAndroid Build Coastguard Worker if (bFracHi < aFracHi) { 806*61046927SAndroid Build Coastguard Worker __sub64(aFracHi, aFracLo, bFracHi, bFracLo, zFrac0, zFrac1); 807*61046927SAndroid Build Coastguard Worker } 808*61046927SAndroid Build Coastguard Worker else if (aFracHi < bFracHi) { 809*61046927SAndroid Build Coastguard Worker __sub64(bFracHi, bFracLo, aFracHi, aFracLo, zFrac0, zFrac1); 810*61046927SAndroid Build Coastguard Worker sign_of_difference = 0x80000000; 811*61046927SAndroid Build Coastguard Worker } 812*61046927SAndroid Build Coastguard Worker else if (bFracLo <= aFracLo) { 813*61046927SAndroid Build Coastguard Worker /* It is possible that zFrac0 and zFrac1 may be zero after this. */ 814*61046927SAndroid Build Coastguard Worker __sub64(aFracHi, aFracLo, bFracHi, bFracLo, zFrac0, zFrac1); 815*61046927SAndroid Build Coastguard Worker } 816*61046927SAndroid Build Coastguard Worker else { 817*61046927SAndroid Build Coastguard Worker __sub64(bFracHi, bFracLo, aFracHi, aFracLo, zFrac0, zFrac1); 818*61046927SAndroid Build Coastguard Worker sign_of_difference = 0x80000000; 819*61046927SAndroid Build Coastguard Worker } 820*61046927SAndroid Build Coastguard Worker zExp = mix(bExp, aExp, sign_of_difference == 0u); 821*61046927SAndroid Build Coastguard Worker aSign ^= sign_of_difference; 822*61046927SAndroid Build Coastguard Worker uint64_t retval_0 = __packFloat64(uint(FLOAT_ROUNDING_MODE == FLOAT_ROUND_DOWN) << 31, 0, 0u, 0u); 823*61046927SAndroid Build Coastguard Worker uint64_t retval_1 = __normalizeRoundAndPackFloat64(aSign, zExp - 11, zFrac0, zFrac1); 824*61046927SAndroid Build Coastguard Worker return mix(retval_0, retval_1, zFrac0 != 0u || zFrac1 != 0u); 825*61046927SAndroid Build Coastguard Worker } 826*61046927SAndroid Build Coastguard Worker} 827*61046927SAndroid Build Coastguard Worker 828*61046927SAndroid Build Coastguard Worker/* Multiplies the 64-bit value formed by concatenating `a0' and `a1' to the 829*61046927SAndroid Build Coastguard Worker * 64-bit value formed by concatenating `b0' and `b1' to obtain a 128-bit 830*61046927SAndroid Build Coastguard Worker * product. The product is broken into four 32-bit pieces which are stored at 831*61046927SAndroid Build Coastguard Worker * the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. 832*61046927SAndroid Build Coastguard Worker */ 833*61046927SAndroid Build Coastguard Workervoid 834*61046927SAndroid Build Coastguard Worker__mul64To128(uint a0, uint a1, uint b0, uint b1, 835*61046927SAndroid Build Coastguard Worker out uint z0Ptr, 836*61046927SAndroid Build Coastguard Worker out uint z1Ptr, 837*61046927SAndroid Build Coastguard Worker out uint z2Ptr, 838*61046927SAndroid Build Coastguard Worker out uint z3Ptr) 839*61046927SAndroid Build Coastguard Worker{ 840*61046927SAndroid Build Coastguard Worker uint z0 = 0u; 841*61046927SAndroid Build Coastguard Worker uint z1 = 0u; 842*61046927SAndroid Build Coastguard Worker uint z2 = 0u; 843*61046927SAndroid Build Coastguard Worker uint z3 = 0u; 844*61046927SAndroid Build Coastguard Worker uint more1 = 0u; 845*61046927SAndroid Build Coastguard Worker uint more2 = 0u; 846*61046927SAndroid Build Coastguard Worker 847*61046927SAndroid Build Coastguard Worker umulExtended(a1, b1, z2, z3); 848*61046927SAndroid Build Coastguard Worker umulExtended(a1, b0, z1, more2); 849*61046927SAndroid Build Coastguard Worker __add64(z1, more2, 0u, z2, z1, z2); 850*61046927SAndroid Build Coastguard Worker umulExtended(a0, b0, z0, more1); 851*61046927SAndroid Build Coastguard Worker __add64(z0, more1, 0u, z1, z0, z1); 852*61046927SAndroid Build Coastguard Worker umulExtended(a0, b1, more1, more2); 853*61046927SAndroid Build Coastguard Worker __add64(more1, more2, 0u, z2, more1, z2); 854*61046927SAndroid Build Coastguard Worker __add64(z0, z1, 0u, more1, z0, z1); 855*61046927SAndroid Build Coastguard Worker z3Ptr = z3; 856*61046927SAndroid Build Coastguard Worker z2Ptr = z2; 857*61046927SAndroid Build Coastguard Worker z1Ptr = z1; 858*61046927SAndroid Build Coastguard Worker z0Ptr = z0; 859*61046927SAndroid Build Coastguard Worker} 860*61046927SAndroid Build Coastguard Worker 861*61046927SAndroid Build Coastguard Worker/* Normalizes the subnormal double-precision floating-point value represented 862*61046927SAndroid Build Coastguard Worker * by the denormalized significand formed by the concatenation of `aFrac0' and 863*61046927SAndroid Build Coastguard Worker * `aFrac1'. The normalized exponent is stored at the location pointed to by 864*61046927SAndroid Build Coastguard Worker * `zExpPtr'. The most significant 21 bits of the normalized significand are 865*61046927SAndroid Build Coastguard Worker * stored at the location pointed to by `zFrac0Ptr', and the least significant 866*61046927SAndroid Build Coastguard Worker * 32 bits of the normalized significand are stored at the location pointed to 867*61046927SAndroid Build Coastguard Worker * by `zFrac1Ptr'. 868*61046927SAndroid Build Coastguard Worker */ 869*61046927SAndroid Build Coastguard Workervoid 870*61046927SAndroid Build Coastguard Worker__normalizeFloat64Subnormal(uint aFrac0, uint aFrac1, 871*61046927SAndroid Build Coastguard Worker out int zExpPtr, 872*61046927SAndroid Build Coastguard Worker out uint zFrac0Ptr, 873*61046927SAndroid Build Coastguard Worker out uint zFrac1Ptr) 874*61046927SAndroid Build Coastguard Worker{ 875*61046927SAndroid Build Coastguard Worker int shiftCount; 876*61046927SAndroid Build Coastguard Worker uint temp_zfrac0, temp_zfrac1; 877*61046927SAndroid Build Coastguard Worker shiftCount = __countLeadingZeros32(mix(aFrac0, aFrac1, aFrac0 == 0u)) - 11; 878*61046927SAndroid Build Coastguard Worker zExpPtr = mix(1 - shiftCount, -shiftCount - 31, aFrac0 == 0u); 879*61046927SAndroid Build Coastguard Worker 880*61046927SAndroid Build Coastguard Worker temp_zfrac0 = mix(aFrac1<<shiftCount, aFrac1>>(-shiftCount), shiftCount < 0); 881*61046927SAndroid Build Coastguard Worker temp_zfrac1 = mix(0u, aFrac1<<(shiftCount & 31), shiftCount < 0); 882*61046927SAndroid Build Coastguard Worker 883*61046927SAndroid Build Coastguard Worker __shortShift64Left(aFrac0, aFrac1, shiftCount, zFrac0Ptr, zFrac1Ptr); 884*61046927SAndroid Build Coastguard Worker 885*61046927SAndroid Build Coastguard Worker zFrac0Ptr = mix(zFrac0Ptr, temp_zfrac0, aFrac0 == 0); 886*61046927SAndroid Build Coastguard Worker zFrac1Ptr = mix(zFrac1Ptr, temp_zfrac1, aFrac0 == 0); 887*61046927SAndroid Build Coastguard Worker} 888*61046927SAndroid Build Coastguard Worker 889*61046927SAndroid Build Coastguard Worker/* Returns the result of multiplying the double-precision floating-point values 890*61046927SAndroid Build Coastguard Worker * `a' and `b'. The operation is performed according to the IEEE Standard for 891*61046927SAndroid Build Coastguard Worker * Floating-Point Arithmetic. 892*61046927SAndroid Build Coastguard Worker */ 893*61046927SAndroid Build Coastguard Workeruint64_t 894*61046927SAndroid Build Coastguard Worker__fmul64(uint64_t a, uint64_t b) 895*61046927SAndroid Build Coastguard Worker{ 896*61046927SAndroid Build Coastguard Worker uint zFrac0 = 0u; 897*61046927SAndroid Build Coastguard Worker uint zFrac1 = 0u; 898*61046927SAndroid Build Coastguard Worker uint zFrac2 = 0u; 899*61046927SAndroid Build Coastguard Worker uint zFrac3 = 0u; 900*61046927SAndroid Build Coastguard Worker int zExp; 901*61046927SAndroid Build Coastguard Worker 902*61046927SAndroid Build Coastguard Worker uint aFracLo = __extractFloat64FracLo(a); 903*61046927SAndroid Build Coastguard Worker uint aFracHi = __extractFloat64FracHi(a); 904*61046927SAndroid Build Coastguard Worker uint bFracLo = __extractFloat64FracLo(b); 905*61046927SAndroid Build Coastguard Worker uint bFracHi = __extractFloat64FracHi(b); 906*61046927SAndroid Build Coastguard Worker int aExp = __extractFloat64Exp(a); 907*61046927SAndroid Build Coastguard Worker uint aSign = __extractFloat64Sign(a); 908*61046927SAndroid Build Coastguard Worker int bExp = __extractFloat64Exp(b); 909*61046927SAndroid Build Coastguard Worker uint bSign = __extractFloat64Sign(b); 910*61046927SAndroid Build Coastguard Worker uint zSign = aSign ^ bSign; 911*61046927SAndroid Build Coastguard Worker if (aExp == 0x7FF) { 912*61046927SAndroid Build Coastguard Worker if (((aFracHi | aFracLo) != 0u) || 913*61046927SAndroid Build Coastguard Worker ((bExp == 0x7FF) && ((bFracHi | bFracLo) != 0u))) { 914*61046927SAndroid Build Coastguard Worker return __propagateFloat64NaN(a, b); 915*61046927SAndroid Build Coastguard Worker } 916*61046927SAndroid Build Coastguard Worker if ((uint(bExp) | bFracHi | bFracLo) == 0u) 917*61046927SAndroid Build Coastguard Worker return 0xFFFFFFFFFFFFFFFFUL; 918*61046927SAndroid Build Coastguard Worker return __packFloat64(zSign, 0x7FF, 0u, 0u); 919*61046927SAndroid Build Coastguard Worker } 920*61046927SAndroid Build Coastguard Worker if (bExp == 0x7FF) { 921*61046927SAndroid Build Coastguard Worker /* a cannot be NaN, but is b NaN? */ 922*61046927SAndroid Build Coastguard Worker if ((bFracHi | bFracLo) != 0u) 923*61046927SAndroid Build Coastguard Worker#if defined RELAXED_NAN_PROPAGATION 924*61046927SAndroid Build Coastguard Worker return b; 925*61046927SAndroid Build Coastguard Worker#else 926*61046927SAndroid Build Coastguard Worker return __propagateFloat64NaN(a, b); 927*61046927SAndroid Build Coastguard Worker#endif 928*61046927SAndroid Build Coastguard Worker if ((uint(aExp) | aFracHi | aFracLo) == 0u) 929*61046927SAndroid Build Coastguard Worker return 0xFFFFFFFFFFFFFFFFUL; 930*61046927SAndroid Build Coastguard Worker return __packFloat64(zSign, 0x7FF, 0u, 0u); 931*61046927SAndroid Build Coastguard Worker } 932*61046927SAndroid Build Coastguard Worker if (aExp == 0) { 933*61046927SAndroid Build Coastguard Worker if ((aFracHi | aFracLo) == 0u) 934*61046927SAndroid Build Coastguard Worker return __packFloat64(zSign, 0, 0u, 0u); 935*61046927SAndroid Build Coastguard Worker __normalizeFloat64Subnormal(aFracHi, aFracLo, aExp, aFracHi, aFracLo); 936*61046927SAndroid Build Coastguard Worker } 937*61046927SAndroid Build Coastguard Worker if (bExp == 0) { 938*61046927SAndroid Build Coastguard Worker if ((bFracHi | bFracLo) == 0u) 939*61046927SAndroid Build Coastguard Worker return __packFloat64(zSign, 0, 0u, 0u); 940*61046927SAndroid Build Coastguard Worker __normalizeFloat64Subnormal(bFracHi, bFracLo, bExp, bFracHi, bFracLo); 941*61046927SAndroid Build Coastguard Worker } 942*61046927SAndroid Build Coastguard Worker zExp = aExp + bExp - 0x400; 943*61046927SAndroid Build Coastguard Worker aFracHi |= 0x00100000u; 944*61046927SAndroid Build Coastguard Worker __shortShift64Left(bFracHi, bFracLo, 12, bFracHi, bFracLo); 945*61046927SAndroid Build Coastguard Worker __mul64To128( 946*61046927SAndroid Build Coastguard Worker aFracHi, aFracLo, bFracHi, bFracLo, zFrac0, zFrac1, zFrac2, zFrac3); 947*61046927SAndroid Build Coastguard Worker __add64(zFrac0, zFrac1, aFracHi, aFracLo, zFrac0, zFrac1); 948*61046927SAndroid Build Coastguard Worker zFrac2 |= uint(zFrac3 != 0u); 949*61046927SAndroid Build Coastguard Worker if (0x00200000u <= zFrac0) { 950*61046927SAndroid Build Coastguard Worker __shift64ExtraRightJamming( 951*61046927SAndroid Build Coastguard Worker zFrac0, zFrac1, zFrac2, 1, zFrac0, zFrac1, zFrac2); 952*61046927SAndroid Build Coastguard Worker ++zExp; 953*61046927SAndroid Build Coastguard Worker } 954*61046927SAndroid Build Coastguard Worker return __roundAndPackFloat64(zSign, zExp, zFrac0, zFrac1, zFrac2); 955*61046927SAndroid Build Coastguard Worker} 956*61046927SAndroid Build Coastguard Worker 957*61046927SAndroid Build Coastguard Workeruint64_t 958*61046927SAndroid Build Coastguard Worker__ffma64(uint64_t a, uint64_t b, uint64_t c) 959*61046927SAndroid Build Coastguard Worker{ 960*61046927SAndroid Build Coastguard Worker return __fadd64(__fmul64(a, b), c); 961*61046927SAndroid Build Coastguard Worker} 962*61046927SAndroid Build Coastguard Worker 963*61046927SAndroid Build Coastguard Worker/* Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the 964*61046927SAndroid Build Coastguard Worker * number of bits given in `count'. Any bits shifted off are lost. The value 965*61046927SAndroid Build Coastguard Worker * of `count' can be arbitrarily large; in particular, if `count' is greater 966*61046927SAndroid Build Coastguard Worker * than 64, the result will be 0. The result is broken into two 32-bit pieces 967*61046927SAndroid Build Coastguard Worker * which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. 968*61046927SAndroid Build Coastguard Worker */ 969*61046927SAndroid Build Coastguard Workervoid 970*61046927SAndroid Build Coastguard Worker__shift64Right(uint a0, uint a1, 971*61046927SAndroid Build Coastguard Worker int count, 972*61046927SAndroid Build Coastguard Worker out uint z0Ptr, 973*61046927SAndroid Build Coastguard Worker out uint z1Ptr) 974*61046927SAndroid Build Coastguard Worker{ 975*61046927SAndroid Build Coastguard Worker uint z0; 976*61046927SAndroid Build Coastguard Worker uint z1; 977*61046927SAndroid Build Coastguard Worker int negCount = (-count) & 31; 978*61046927SAndroid Build Coastguard Worker 979*61046927SAndroid Build Coastguard Worker z0 = 0u; 980*61046927SAndroid Build Coastguard Worker z0 = mix(z0, (a0 >> count), count < 32); 981*61046927SAndroid Build Coastguard Worker z0 = mix(z0, a0, count == 0); 982*61046927SAndroid Build Coastguard Worker 983*61046927SAndroid Build Coastguard Worker z1 = mix(0u, (a0 >> (count & 31)), count < 64); 984*61046927SAndroid Build Coastguard Worker z1 = mix(z1, (a0<<negCount) | (a1>>count), count < 32); 985*61046927SAndroid Build Coastguard Worker z1 = mix(z1, a0, count == 0); 986*61046927SAndroid Build Coastguard Worker 987*61046927SAndroid Build Coastguard Worker z1Ptr = z1; 988*61046927SAndroid Build Coastguard Worker z0Ptr = z0; 989*61046927SAndroid Build Coastguard Worker} 990*61046927SAndroid Build Coastguard Worker 991*61046927SAndroid Build Coastguard Worker/* Returns the result of converting the double-precision floating-point value 992*61046927SAndroid Build Coastguard Worker * `a' to the unsigned integer format. The conversion is performed according 993*61046927SAndroid Build Coastguard Worker * to the IEEE Standard for Floating-Point Arithmetic. 994*61046927SAndroid Build Coastguard Worker */ 995*61046927SAndroid Build Coastguard Workeruint 996*61046927SAndroid Build Coastguard Worker__fp64_to_uint(uint64_t a) 997*61046927SAndroid Build Coastguard Worker{ 998*61046927SAndroid Build Coastguard Worker uint aFracLo = __extractFloat64FracLo(a); 999*61046927SAndroid Build Coastguard Worker uint aFracHi = __extractFloat64FracHi(a); 1000*61046927SAndroid Build Coastguard Worker int aExp = __extractFloat64Exp(a); 1001*61046927SAndroid Build Coastguard Worker uint aSign = __extractFloat64Sign(a); 1002*61046927SAndroid Build Coastguard Worker 1003*61046927SAndroid Build Coastguard Worker if ((aExp == 0x7FF) && ((aFracHi | aFracLo) != 0u)) 1004*61046927SAndroid Build Coastguard Worker return 0xFFFFFFFFu; 1005*61046927SAndroid Build Coastguard Worker 1006*61046927SAndroid Build Coastguard Worker aFracHi |= mix(0u, 0x00100000u, aExp != 0); 1007*61046927SAndroid Build Coastguard Worker 1008*61046927SAndroid Build Coastguard Worker int shiftDist = 0x427 - aExp; 1009*61046927SAndroid Build Coastguard Worker if (0 < shiftDist) 1010*61046927SAndroid Build Coastguard Worker __shift64RightJamming(aFracHi, aFracLo, shiftDist, aFracHi, aFracLo); 1011*61046927SAndroid Build Coastguard Worker 1012*61046927SAndroid Build Coastguard Worker if ((aFracHi & 0xFFFFF000u) != 0u) 1013*61046927SAndroid Build Coastguard Worker return mix(~0u, 0u, aSign != 0u); 1014*61046927SAndroid Build Coastguard Worker 1015*61046927SAndroid Build Coastguard Worker uint z = 0u; 1016*61046927SAndroid Build Coastguard Worker uint zero = 0u; 1017*61046927SAndroid Build Coastguard Worker __shift64Right(aFracHi, aFracLo, 12, zero, z); 1018*61046927SAndroid Build Coastguard Worker 1019*61046927SAndroid Build Coastguard Worker uint expt = mix(~0u, 0u, aSign != 0u); 1020*61046927SAndroid Build Coastguard Worker 1021*61046927SAndroid Build Coastguard Worker return mix(z, expt, (aSign != 0u) && (z != 0u)); 1022*61046927SAndroid Build Coastguard Worker} 1023*61046927SAndroid Build Coastguard Worker 1024*61046927SAndroid Build Coastguard Workeruint64_t 1025*61046927SAndroid Build Coastguard Worker__uint_to_fp64(uint a) 1026*61046927SAndroid Build Coastguard Worker{ 1027*61046927SAndroid Build Coastguard Worker if (a == 0u) 1028*61046927SAndroid Build Coastguard Worker return 0ul; 1029*61046927SAndroid Build Coastguard Worker 1030*61046927SAndroid Build Coastguard Worker int shiftDist = __countLeadingZeros32(a) + 21; 1031*61046927SAndroid Build Coastguard Worker 1032*61046927SAndroid Build Coastguard Worker uint aHigh = 0u; 1033*61046927SAndroid Build Coastguard Worker uint aLow = 0u; 1034*61046927SAndroid Build Coastguard Worker int negCount = (- shiftDist) & 31; 1035*61046927SAndroid Build Coastguard Worker 1036*61046927SAndroid Build Coastguard Worker aHigh = mix(0u, a<< shiftDist - 32, shiftDist < 64); 1037*61046927SAndroid Build Coastguard Worker aLow = 0u; 1038*61046927SAndroid Build Coastguard Worker aHigh = mix(aHigh, 0u, shiftDist == 0); 1039*61046927SAndroid Build Coastguard Worker aLow = mix(aLow, a, shiftDist ==0); 1040*61046927SAndroid Build Coastguard Worker aHigh = mix(aHigh, a >> negCount, shiftDist < 32); 1041*61046927SAndroid Build Coastguard Worker aLow = mix(aLow, a << shiftDist, shiftDist < 32); 1042*61046927SAndroid Build Coastguard Worker 1043*61046927SAndroid Build Coastguard Worker return __packFloat64(0u, 0x432 - shiftDist, aHigh, aLow); 1044*61046927SAndroid Build Coastguard Worker} 1045*61046927SAndroid Build Coastguard Worker 1046*61046927SAndroid Build Coastguard Workeruint64_t 1047*61046927SAndroid Build Coastguard Worker__uint64_to_fp64(uint64_t a) 1048*61046927SAndroid Build Coastguard Worker{ 1049*61046927SAndroid Build Coastguard Worker if (a == 0u) 1050*61046927SAndroid Build Coastguard Worker return 0ul; 1051*61046927SAndroid Build Coastguard Worker 1052*61046927SAndroid Build Coastguard Worker uvec2 aFrac = unpackUint2x32(a); 1053*61046927SAndroid Build Coastguard Worker uint aFracLo = __extractFloat64FracLo(a); 1054*61046927SAndroid Build Coastguard Worker uint aFracHi = __extractFloat64FracHi(a); 1055*61046927SAndroid Build Coastguard Worker 1056*61046927SAndroid Build Coastguard Worker if ((aFracHi & 0x80000000u) != 0u) { 1057*61046927SAndroid Build Coastguard Worker __shift64RightJamming(aFracHi, aFracLo, 1, aFracHi, aFracLo); 1058*61046927SAndroid Build Coastguard Worker return __roundAndPackFloat64(0, 0x433, aFracHi, aFracLo, 0u); 1059*61046927SAndroid Build Coastguard Worker } else { 1060*61046927SAndroid Build Coastguard Worker return __normalizeRoundAndPackFloat64(0, 0x432, aFrac.y, aFrac.x); 1061*61046927SAndroid Build Coastguard Worker } 1062*61046927SAndroid Build Coastguard Worker} 1063*61046927SAndroid Build Coastguard Worker 1064*61046927SAndroid Build Coastguard Workeruint64_t 1065*61046927SAndroid Build Coastguard Worker__fp64_to_uint64(uint64_t a) 1066*61046927SAndroid Build Coastguard Worker{ 1067*61046927SAndroid Build Coastguard Worker uint aFracLo = __extractFloat64FracLo(a); 1068*61046927SAndroid Build Coastguard Worker uint aFracHi = __extractFloat64FracHi(a); 1069*61046927SAndroid Build Coastguard Worker int aExp = __extractFloat64Exp(a); 1070*61046927SAndroid Build Coastguard Worker uint aSign = __extractFloat64Sign(a); 1071*61046927SAndroid Build Coastguard Worker uint zFrac2 = 0u; 1072*61046927SAndroid Build Coastguard Worker uint64_t default_nan = 0xFFFFFFFFFFFFFFFFUL; 1073*61046927SAndroid Build Coastguard Worker 1074*61046927SAndroid Build Coastguard Worker aFracHi = mix(aFracHi, aFracHi | 0x00100000u, aExp != 0); 1075*61046927SAndroid Build Coastguard Worker int shiftCount = 0x433 - aExp; 1076*61046927SAndroid Build Coastguard Worker 1077*61046927SAndroid Build Coastguard Worker if ( shiftCount <= 0 ) { 1078*61046927SAndroid Build Coastguard Worker if (shiftCount < -11 && aExp == 0x7FF) { 1079*61046927SAndroid Build Coastguard Worker if ((aFracHi | aFracLo) != 0u) 1080*61046927SAndroid Build Coastguard Worker return __propagateFloat64NaN(a, a); 1081*61046927SAndroid Build Coastguard Worker return mix(default_nan, a, aSign == 0u); 1082*61046927SAndroid Build Coastguard Worker } 1083*61046927SAndroid Build Coastguard Worker __shortShift64Left(aFracHi, aFracLo, -shiftCount, aFracHi, aFracLo); 1084*61046927SAndroid Build Coastguard Worker } else { 1085*61046927SAndroid Build Coastguard Worker __shift64ExtraRightJamming(aFracHi, aFracLo, zFrac2, shiftCount, 1086*61046927SAndroid Build Coastguard Worker aFracHi, aFracLo, zFrac2); 1087*61046927SAndroid Build Coastguard Worker } 1088*61046927SAndroid Build Coastguard Worker return __roundAndPackUInt64(aSign, aFracHi, aFracLo, zFrac2); 1089*61046927SAndroid Build Coastguard Worker} 1090*61046927SAndroid Build Coastguard Worker 1091*61046927SAndroid Build Coastguard Workerint64_t 1092*61046927SAndroid Build Coastguard Worker__fp64_to_int64(uint64_t a) 1093*61046927SAndroid Build Coastguard Worker{ 1094*61046927SAndroid Build Coastguard Worker uint zFrac2 = 0u; 1095*61046927SAndroid Build Coastguard Worker uint aFracLo = __extractFloat64FracLo(a); 1096*61046927SAndroid Build Coastguard Worker uint aFracHi = __extractFloat64FracHi(a); 1097*61046927SAndroid Build Coastguard Worker int aExp = __extractFloat64Exp(a); 1098*61046927SAndroid Build Coastguard Worker uint aSign = __extractFloat64Sign(a); 1099*61046927SAndroid Build Coastguard Worker int64_t default_NegNaN = -0x7FFFFFFFFFFFFFFEL; 1100*61046927SAndroid Build Coastguard Worker int64_t default_PosNaN = 0xFFFFFFFFFFFFFFFFL; 1101*61046927SAndroid Build Coastguard Worker 1102*61046927SAndroid Build Coastguard Worker aFracHi = mix(aFracHi, aFracHi | 0x00100000u, aExp != 0); 1103*61046927SAndroid Build Coastguard Worker int shiftCount = 0x433 - aExp; 1104*61046927SAndroid Build Coastguard Worker 1105*61046927SAndroid Build Coastguard Worker if (shiftCount <= 0) { 1106*61046927SAndroid Build Coastguard Worker if (shiftCount < -11 && aExp == 0x7FF) { 1107*61046927SAndroid Build Coastguard Worker if ((aFracHi | aFracLo) != 0u) 1108*61046927SAndroid Build Coastguard Worker return default_NegNaN; 1109*61046927SAndroid Build Coastguard Worker return mix(default_NegNaN, default_PosNaN, aSign == 0u); 1110*61046927SAndroid Build Coastguard Worker } 1111*61046927SAndroid Build Coastguard Worker __shortShift64Left(aFracHi, aFracLo, -shiftCount, aFracHi, aFracLo); 1112*61046927SAndroid Build Coastguard Worker } else { 1113*61046927SAndroid Build Coastguard Worker __shift64ExtraRightJamming(aFracHi, aFracLo, zFrac2, shiftCount, 1114*61046927SAndroid Build Coastguard Worker aFracHi, aFracLo, zFrac2); 1115*61046927SAndroid Build Coastguard Worker } 1116*61046927SAndroid Build Coastguard Worker 1117*61046927SAndroid Build Coastguard Worker return __roundAndPackInt64(aSign, aFracHi, aFracLo, zFrac2); 1118*61046927SAndroid Build Coastguard Worker} 1119*61046927SAndroid Build Coastguard Worker 1120*61046927SAndroid Build Coastguard Workeruint64_t 1121*61046927SAndroid Build Coastguard Worker__int64_to_fp64(int64_t a) 1122*61046927SAndroid Build Coastguard Worker{ 1123*61046927SAndroid Build Coastguard Worker if (a==0) 1124*61046927SAndroid Build Coastguard Worker return 0ul; 1125*61046927SAndroid Build Coastguard Worker 1126*61046927SAndroid Build Coastguard Worker uint64_t absA = mix(uint64_t(a), uint64_t(-a), a < 0); 1127*61046927SAndroid Build Coastguard Worker uint aFracHi = __extractFloat64FracHi(absA); 1128*61046927SAndroid Build Coastguard Worker uvec2 aFrac = unpackUint2x32(absA); 1129*61046927SAndroid Build Coastguard Worker uint zSign = uint(unpackInt2x32(a).y) & 0x80000000u; 1130*61046927SAndroid Build Coastguard Worker 1131*61046927SAndroid Build Coastguard Worker if ((aFracHi & 0x80000000u) != 0u) { 1132*61046927SAndroid Build Coastguard Worker return mix(0ul, __packFloat64(0x80000000u, 0x434, 0u, 0u), a < 0); 1133*61046927SAndroid Build Coastguard Worker } 1134*61046927SAndroid Build Coastguard Worker 1135*61046927SAndroid Build Coastguard Worker return __normalizeRoundAndPackFloat64(zSign, 0x432, aFrac.y, aFrac.x); 1136*61046927SAndroid Build Coastguard Worker} 1137*61046927SAndroid Build Coastguard Worker 1138*61046927SAndroid Build Coastguard Worker/* Returns the result of converting the double-precision floating-point value 1139*61046927SAndroid Build Coastguard Worker * `a' to the 32-bit two's complement integer format. The conversion is 1140*61046927SAndroid Build Coastguard Worker * performed according to the IEEE Standard for Floating-Point Arithmetic--- 1141*61046927SAndroid Build Coastguard Worker * which means in particular that the conversion is rounded according to the 1142*61046927SAndroid Build Coastguard Worker * current rounding mode. If `a' is a NaN, the largest positive integer is 1143*61046927SAndroid Build Coastguard Worker * returned. Otherwise, if the conversion overflows, the largest integer with 1144*61046927SAndroid Build Coastguard Worker * the same sign as `a' is returned. 1145*61046927SAndroid Build Coastguard Worker */ 1146*61046927SAndroid Build Coastguard Workerint 1147*61046927SAndroid Build Coastguard Worker__fp64_to_int(uint64_t a) 1148*61046927SAndroid Build Coastguard Worker{ 1149*61046927SAndroid Build Coastguard Worker uint aFracLo = __extractFloat64FracLo(a); 1150*61046927SAndroid Build Coastguard Worker uint aFracHi = __extractFloat64FracHi(a); 1151*61046927SAndroid Build Coastguard Worker int aExp = __extractFloat64Exp(a); 1152*61046927SAndroid Build Coastguard Worker uint aSign = __extractFloat64Sign(a); 1153*61046927SAndroid Build Coastguard Worker 1154*61046927SAndroid Build Coastguard Worker uint absZ = 0u; 1155*61046927SAndroid Build Coastguard Worker uint aFracExtra = 0u; 1156*61046927SAndroid Build Coastguard Worker int shiftCount = aExp - 0x413; 1157*61046927SAndroid Build Coastguard Worker 1158*61046927SAndroid Build Coastguard Worker if (0 <= shiftCount) { 1159*61046927SAndroid Build Coastguard Worker if (0x41E < aExp) { 1160*61046927SAndroid Build Coastguard Worker if ((aExp == 0x7FF) && bool(aFracHi | aFracLo)) 1161*61046927SAndroid Build Coastguard Worker aSign = 0u; 1162*61046927SAndroid Build Coastguard Worker return mix(0x7FFFFFFF, 0x80000000, aSign != 0u); 1163*61046927SAndroid Build Coastguard Worker } 1164*61046927SAndroid Build Coastguard Worker __shortShift64Left(aFracHi | 0x00100000u, aFracLo, shiftCount, absZ, aFracExtra); 1165*61046927SAndroid Build Coastguard Worker } else { 1166*61046927SAndroid Build Coastguard Worker if (aExp < 0x3FF) 1167*61046927SAndroid Build Coastguard Worker return 0; 1168*61046927SAndroid Build Coastguard Worker 1169*61046927SAndroid Build Coastguard Worker aFracHi |= 0x00100000u; 1170*61046927SAndroid Build Coastguard Worker aFracExtra = ( aFracHi << (shiftCount & 31)) | aFracLo; 1171*61046927SAndroid Build Coastguard Worker absZ = aFracHi >> (- shiftCount); 1172*61046927SAndroid Build Coastguard Worker } 1173*61046927SAndroid Build Coastguard Worker 1174*61046927SAndroid Build Coastguard Worker int z = mix(int(absZ), -int(absZ), aSign != 0u); 1175*61046927SAndroid Build Coastguard Worker int nan = mix(0x7FFFFFFF, 0x80000000, aSign != 0u); 1176*61046927SAndroid Build Coastguard Worker return mix(z, nan, ((aSign != 0u) != (z < 0)) && bool(z)); 1177*61046927SAndroid Build Coastguard Worker} 1178*61046927SAndroid Build Coastguard Worker 1179*61046927SAndroid Build Coastguard Worker/* Returns the result of converting the 32-bit two's complement integer `a' 1180*61046927SAndroid Build Coastguard Worker * to the double-precision floating-point format. The conversion is performed 1181*61046927SAndroid Build Coastguard Worker * according to the IEEE Standard for Floating-Point Arithmetic. 1182*61046927SAndroid Build Coastguard Worker */ 1183*61046927SAndroid Build Coastguard Workeruint64_t 1184*61046927SAndroid Build Coastguard Worker__int_to_fp64(int a) 1185*61046927SAndroid Build Coastguard Worker{ 1186*61046927SAndroid Build Coastguard Worker uint zFrac0 = 0u; 1187*61046927SAndroid Build Coastguard Worker uint zFrac1 = 0u; 1188*61046927SAndroid Build Coastguard Worker if (a==0) 1189*61046927SAndroid Build Coastguard Worker return __packFloat64(0u, 0, 0u, 0u); 1190*61046927SAndroid Build Coastguard Worker uint zSign = uint(a) & 0x80000000u; 1191*61046927SAndroid Build Coastguard Worker uint absA = mix(uint(a), uint(-a), a < 0); 1192*61046927SAndroid Build Coastguard Worker int shiftCount = __countLeadingZeros32(absA) - 11; 1193*61046927SAndroid Build Coastguard Worker if (0 <= shiftCount) { 1194*61046927SAndroid Build Coastguard Worker zFrac0 = absA << shiftCount; 1195*61046927SAndroid Build Coastguard Worker zFrac1 = 0u; 1196*61046927SAndroid Build Coastguard Worker } else { 1197*61046927SAndroid Build Coastguard Worker __shift64Right(absA, 0u, -shiftCount, zFrac0, zFrac1); 1198*61046927SAndroid Build Coastguard Worker } 1199*61046927SAndroid Build Coastguard Worker return __packFloat64(zSign, 0x412 - shiftCount, zFrac0, zFrac1); 1200*61046927SAndroid Build Coastguard Worker} 1201*61046927SAndroid Build Coastguard Worker 1202*61046927SAndroid Build Coastguard Workeruint64_t 1203*61046927SAndroid Build Coastguard Worker__bool_to_fp64(bool a) 1204*61046927SAndroid Build Coastguard Worker{ 1205*61046927SAndroid Build Coastguard Worker return packUint2x32(uvec2(0x00000000u, uint(-int(a) & 0x3ff00000))); 1206*61046927SAndroid Build Coastguard Worker} 1207*61046927SAndroid Build Coastguard Worker 1208*61046927SAndroid Build Coastguard Worker/* Packs the sign `zSign', exponent `zExp', and significand `zFrac' into a 1209*61046927SAndroid Build Coastguard Worker * single-precision floating-point value, returning the result. After being 1210*61046927SAndroid Build Coastguard Worker * shifted into the proper positions, the three fields are simply added 1211*61046927SAndroid Build Coastguard Worker * together to form the result. This means that any integer portion of `zSig' 1212*61046927SAndroid Build Coastguard Worker * will be added into the exponent. Since a properly normalized significand 1213*61046927SAndroid Build Coastguard Worker * will have an integer portion equal to 1, the `zExp' input should be 1 less 1214*61046927SAndroid Build Coastguard Worker * than the desired result exponent whenever `zFrac' is a complete, normalized 1215*61046927SAndroid Build Coastguard Worker * significand. 1216*61046927SAndroid Build Coastguard Worker */ 1217*61046927SAndroid Build Coastguard Workerfloat 1218*61046927SAndroid Build Coastguard Worker__packFloat32(uint zSign, int zExp, uint zFrac) 1219*61046927SAndroid Build Coastguard Worker{ 1220*61046927SAndroid Build Coastguard Worker return uintBitsToFloat(zSign + (uint(zExp)<<23) + zFrac); 1221*61046927SAndroid Build Coastguard Worker} 1222*61046927SAndroid Build Coastguard Worker 1223*61046927SAndroid Build Coastguard Worker/* Takes an abstract floating-point value having sign `zSign', exponent `zExp', 1224*61046927SAndroid Build Coastguard Worker * and significand `zFrac', and returns the proper single-precision floating- 1225*61046927SAndroid Build Coastguard Worker * point value corresponding to the abstract input. Ordinarily, the abstract 1226*61046927SAndroid Build Coastguard Worker * value is simply rounded and packed into the single-precision format, with 1227*61046927SAndroid Build Coastguard Worker * the inexact exception raised if the abstract input cannot be represented 1228*61046927SAndroid Build Coastguard Worker * exactly. However, if the abstract value is too large, the overflow and 1229*61046927SAndroid Build Coastguard Worker * inexact exceptions are raised and an infinity or maximal finite value is 1230*61046927SAndroid Build Coastguard Worker * returned. If the abstract value is too small, the input value is rounded to 1231*61046927SAndroid Build Coastguard Worker * a subnormal number, and the underflow and inexact exceptions are raised if 1232*61046927SAndroid Build Coastguard Worker * the abstract input cannot be represented exactly as a subnormal single- 1233*61046927SAndroid Build Coastguard Worker * precision floating-point number. 1234*61046927SAndroid Build Coastguard Worker * The input significand `zFrac' has its binary point between bits 30 1235*61046927SAndroid Build Coastguard Worker * and 29, which is 7 bits to the left of the usual location. This shifted 1236*61046927SAndroid Build Coastguard Worker * significand must be normalized or smaller. If `zFrac' is not normalized, 1237*61046927SAndroid Build Coastguard Worker * `zExp' must be 0; in that case, the result returned is a subnormal number, 1238*61046927SAndroid Build Coastguard Worker * and it must not require rounding. In the usual case that `zFrac' is 1239*61046927SAndroid Build Coastguard Worker * normalized, `zExp' must be 1 less than the "true" floating-point exponent. 1240*61046927SAndroid Build Coastguard Worker * The handling of underflow and overflow follows the IEEE Standard for 1241*61046927SAndroid Build Coastguard Worker * Floating-Point Arithmetic. 1242*61046927SAndroid Build Coastguard Worker */ 1243*61046927SAndroid Build Coastguard Workerfloat 1244*61046927SAndroid Build Coastguard Worker__roundAndPackFloat32(uint zSign, int zExp, uint zFrac) 1245*61046927SAndroid Build Coastguard Worker{ 1246*61046927SAndroid Build Coastguard Worker bool roundNearestEven; 1247*61046927SAndroid Build Coastguard Worker int roundIncrement; 1248*61046927SAndroid Build Coastguard Worker int roundBits; 1249*61046927SAndroid Build Coastguard Worker 1250*61046927SAndroid Build Coastguard Worker roundNearestEven = FLOAT_ROUNDING_MODE == FLOAT_ROUND_NEAREST_EVEN; 1251*61046927SAndroid Build Coastguard Worker roundIncrement = 0x40; 1252*61046927SAndroid Build Coastguard Worker if (!roundNearestEven) { 1253*61046927SAndroid Build Coastguard Worker if (FLOAT_ROUNDING_MODE == FLOAT_ROUND_TO_ZERO) { 1254*61046927SAndroid Build Coastguard Worker roundIncrement = 0; 1255*61046927SAndroid Build Coastguard Worker } else { 1256*61046927SAndroid Build Coastguard Worker roundIncrement = 0x7F; 1257*61046927SAndroid Build Coastguard Worker if (zSign != 0u) { 1258*61046927SAndroid Build Coastguard Worker if (FLOAT_ROUNDING_MODE == FLOAT_ROUND_UP) 1259*61046927SAndroid Build Coastguard Worker roundIncrement = 0; 1260*61046927SAndroid Build Coastguard Worker } else { 1261*61046927SAndroid Build Coastguard Worker if (FLOAT_ROUNDING_MODE == FLOAT_ROUND_DOWN) 1262*61046927SAndroid Build Coastguard Worker roundIncrement = 0; 1263*61046927SAndroid Build Coastguard Worker } 1264*61046927SAndroid Build Coastguard Worker } 1265*61046927SAndroid Build Coastguard Worker } 1266*61046927SAndroid Build Coastguard Worker roundBits = int(zFrac & 0x7Fu); 1267*61046927SAndroid Build Coastguard Worker if (0xFDu <= uint(zExp)) { 1268*61046927SAndroid Build Coastguard Worker if ((0xFD < zExp) || ((zExp == 0xFD) && (int(zFrac) + roundIncrement) < 0)) 1269*61046927SAndroid Build Coastguard Worker return __packFloat32(zSign, 0xFF, 0u) - float(roundIncrement == 0); 1270*61046927SAndroid Build Coastguard Worker int count = -zExp; 1271*61046927SAndroid Build Coastguard Worker bool zexp_lt0 = zExp < 0; 1272*61046927SAndroid Build Coastguard Worker uint zFrac_lt0 = mix(uint(zFrac != 0u), (zFrac>>count) | uint((zFrac<<((-count) & 31)) != 0u), (-zExp) < 32); 1273*61046927SAndroid Build Coastguard Worker zFrac = mix(zFrac, zFrac_lt0, zexp_lt0); 1274*61046927SAndroid Build Coastguard Worker roundBits = mix(roundBits, int(zFrac) & 0x7f, zexp_lt0); 1275*61046927SAndroid Build Coastguard Worker zExp = mix(zExp, 0, zexp_lt0); 1276*61046927SAndroid Build Coastguard Worker } 1277*61046927SAndroid Build Coastguard Worker zFrac = (zFrac + uint(roundIncrement))>>7; 1278*61046927SAndroid Build Coastguard Worker zFrac &= ~uint(((roundBits ^ 0x40) == 0) && roundNearestEven); 1279*61046927SAndroid Build Coastguard Worker 1280*61046927SAndroid Build Coastguard Worker return __packFloat32(zSign, mix(zExp, 0, zFrac == 0u), zFrac); 1281*61046927SAndroid Build Coastguard Worker} 1282*61046927SAndroid Build Coastguard Worker 1283*61046927SAndroid Build Coastguard Worker/* Returns the result of converting the double-precision floating-point value 1284*61046927SAndroid Build Coastguard Worker * `a' to the single-precision floating-point format. The conversion is 1285*61046927SAndroid Build Coastguard Worker * performed according to the IEEE Standard for Floating-Point Arithmetic. 1286*61046927SAndroid Build Coastguard Worker */ 1287*61046927SAndroid Build Coastguard Workerfloat 1288*61046927SAndroid Build Coastguard Worker__fp64_to_fp32(uint64_t __a) 1289*61046927SAndroid Build Coastguard Worker{ 1290*61046927SAndroid Build Coastguard Worker uvec2 a = unpackUint2x32(__a); 1291*61046927SAndroid Build Coastguard Worker uint zFrac = 0u; 1292*61046927SAndroid Build Coastguard Worker uint allZero = 0u; 1293*61046927SAndroid Build Coastguard Worker 1294*61046927SAndroid Build Coastguard Worker uint aFracLo = __extractFloat64FracLo(__a); 1295*61046927SAndroid Build Coastguard Worker uint aFracHi = __extractFloat64FracHi(__a); 1296*61046927SAndroid Build Coastguard Worker int aExp = __extractFloat64Exp(__a); 1297*61046927SAndroid Build Coastguard Worker uint aSign = __extractFloat64Sign(__a); 1298*61046927SAndroid Build Coastguard Worker if (aExp == 0x7FF) { 1299*61046927SAndroid Build Coastguard Worker __shortShift64Left(a.y, a.x, 12, a.y, a.x); 1300*61046927SAndroid Build Coastguard Worker float rval = uintBitsToFloat(aSign | 0x7FC00000u | (a.y>>9)); 1301*61046927SAndroid Build Coastguard Worker rval = mix(__packFloat32(aSign, 0xFF, 0u), rval, (aFracHi | aFracLo) != 0u); 1302*61046927SAndroid Build Coastguard Worker return rval; 1303*61046927SAndroid Build Coastguard Worker } 1304*61046927SAndroid Build Coastguard Worker __shift64RightJamming(aFracHi, aFracLo, 22, allZero, zFrac); 1305*61046927SAndroid Build Coastguard Worker zFrac = mix(zFrac, zFrac | 0x40000000u, aExp != 0); 1306*61046927SAndroid Build Coastguard Worker return __roundAndPackFloat32(aSign, aExp - 0x381, zFrac); 1307*61046927SAndroid Build Coastguard Worker} 1308*61046927SAndroid Build Coastguard Worker 1309*61046927SAndroid Build Coastguard Worker/* Returns the result of converting the single-precision floating-point value 1310*61046927SAndroid Build Coastguard Worker * `a' to the double-precision floating-point format. 1311*61046927SAndroid Build Coastguard Worker */ 1312*61046927SAndroid Build Coastguard Workeruint64_t 1313*61046927SAndroid Build Coastguard Worker__fp32_to_fp64(float f) 1314*61046927SAndroid Build Coastguard Worker{ 1315*61046927SAndroid Build Coastguard Worker uint a = floatBitsToUint(f); 1316*61046927SAndroid Build Coastguard Worker uint aFrac = a & 0x007FFFFFu; 1317*61046927SAndroid Build Coastguard Worker int aExp = int((a>>23) & 0xFFu); 1318*61046927SAndroid Build Coastguard Worker uint aSign = a & 0x80000000u; 1319*61046927SAndroid Build Coastguard Worker uint zFrac0 = 0u; 1320*61046927SAndroid Build Coastguard Worker uint zFrac1 = 0u; 1321*61046927SAndroid Build Coastguard Worker 1322*61046927SAndroid Build Coastguard Worker if (aExp == 0xFF) { 1323*61046927SAndroid Build Coastguard Worker if (aFrac != 0u) { 1324*61046927SAndroid Build Coastguard Worker uint nanLo = 0u; 1325*61046927SAndroid Build Coastguard Worker uint nanHi = a<<9; 1326*61046927SAndroid Build Coastguard Worker __shift64Right(nanHi, nanLo, 12, nanHi, nanLo); 1327*61046927SAndroid Build Coastguard Worker nanHi |= aSign | 0x7FF80000u; 1328*61046927SAndroid Build Coastguard Worker return packUint2x32(uvec2(nanLo, nanHi)); 1329*61046927SAndroid Build Coastguard Worker } 1330*61046927SAndroid Build Coastguard Worker return __packFloat64(aSign, 0x7FF, 0u, 0u); 1331*61046927SAndroid Build Coastguard Worker } 1332*61046927SAndroid Build Coastguard Worker 1333*61046927SAndroid Build Coastguard Worker if (aExp == 0) { 1334*61046927SAndroid Build Coastguard Worker if (aFrac == 0u) 1335*61046927SAndroid Build Coastguard Worker return __packFloat64(aSign, 0, 0u, 0u); 1336*61046927SAndroid Build Coastguard Worker /* Normalize subnormal */ 1337*61046927SAndroid Build Coastguard Worker int shiftCount = __countLeadingZeros32(aFrac) - 8; 1338*61046927SAndroid Build Coastguard Worker aFrac <<= shiftCount; 1339*61046927SAndroid Build Coastguard Worker aExp = 1 - shiftCount; 1340*61046927SAndroid Build Coastguard Worker --aExp; 1341*61046927SAndroid Build Coastguard Worker } 1342*61046927SAndroid Build Coastguard Worker 1343*61046927SAndroid Build Coastguard Worker __shift64Right(aFrac, 0u, 3, zFrac0, zFrac1); 1344*61046927SAndroid Build Coastguard Worker return __packFloat64(aSign, aExp + 0x380, zFrac0, zFrac1); 1345*61046927SAndroid Build Coastguard Worker} 1346*61046927SAndroid Build Coastguard Worker 1347*61046927SAndroid Build Coastguard Worker/* Adds the 96-bit value formed by concatenating `a0', `a1', and `a2' to the 1348*61046927SAndroid Build Coastguard Worker * 96-bit value formed by concatenating `b0', `b1', and `b2'. Addition is 1349*61046927SAndroid Build Coastguard Worker * modulo 2^96, so any carry out is lost. The result is broken into three 1350*61046927SAndroid Build Coastguard Worker * 32-bit pieces which are stored at the locations pointed to by `z0Ptr', 1351*61046927SAndroid Build Coastguard Worker * `z1Ptr', and `z2Ptr'. 1352*61046927SAndroid Build Coastguard Worker */ 1353*61046927SAndroid Build Coastguard Workervoid 1354*61046927SAndroid Build Coastguard Worker__add96(uint a0, uint a1, uint a2, 1355*61046927SAndroid Build Coastguard Worker uint b0, uint b1, uint b2, 1356*61046927SAndroid Build Coastguard Worker out uint z0Ptr, 1357*61046927SAndroid Build Coastguard Worker out uint z1Ptr, 1358*61046927SAndroid Build Coastguard Worker out uint z2Ptr) 1359*61046927SAndroid Build Coastguard Worker{ 1360*61046927SAndroid Build Coastguard Worker uint z2 = a2 + b2; 1361*61046927SAndroid Build Coastguard Worker uint carry1 = uint(z2 < a2); 1362*61046927SAndroid Build Coastguard Worker uint z1 = a1 + b1; 1363*61046927SAndroid Build Coastguard Worker uint carry0 = uint(z1 < a1); 1364*61046927SAndroid Build Coastguard Worker uint z0 = a0 + b0; 1365*61046927SAndroid Build Coastguard Worker z1 += carry1; 1366*61046927SAndroid Build Coastguard Worker z0 += uint(z1 < carry1); 1367*61046927SAndroid Build Coastguard Worker z0 += carry0; 1368*61046927SAndroid Build Coastguard Worker z2Ptr = z2; 1369*61046927SAndroid Build Coastguard Worker z1Ptr = z1; 1370*61046927SAndroid Build Coastguard Worker z0Ptr = z0; 1371*61046927SAndroid Build Coastguard Worker} 1372*61046927SAndroid Build Coastguard Worker 1373*61046927SAndroid Build Coastguard Worker/* Subtracts the 96-bit value formed by concatenating `b0', `b1', and `b2' from 1374*61046927SAndroid Build Coastguard Worker * the 96-bit value formed by concatenating `a0', `a1', and `a2'. Subtraction 1375*61046927SAndroid Build Coastguard Worker * is modulo 2^96, so any borrow out (carry out) is lost. The result is broken 1376*61046927SAndroid Build Coastguard Worker * into three 32-bit pieces which are stored at the locations pointed to by 1377*61046927SAndroid Build Coastguard Worker * `z0Ptr', `z1Ptr', and `z2Ptr'. 1378*61046927SAndroid Build Coastguard Worker */ 1379*61046927SAndroid Build Coastguard Workervoid 1380*61046927SAndroid Build Coastguard Worker__sub96(uint a0, uint a1, uint a2, 1381*61046927SAndroid Build Coastguard Worker uint b0, uint b1, uint b2, 1382*61046927SAndroid Build Coastguard Worker out uint z0Ptr, 1383*61046927SAndroid Build Coastguard Worker out uint z1Ptr, 1384*61046927SAndroid Build Coastguard Worker out uint z2Ptr) 1385*61046927SAndroid Build Coastguard Worker{ 1386*61046927SAndroid Build Coastguard Worker uint z2 = a2 - b2; 1387*61046927SAndroid Build Coastguard Worker uint borrow1 = uint(a2 < b2); 1388*61046927SAndroid Build Coastguard Worker uint z1 = a1 - b1; 1389*61046927SAndroid Build Coastguard Worker uint borrow0 = uint(a1 < b1); 1390*61046927SAndroid Build Coastguard Worker uint z0 = a0 - b0; 1391*61046927SAndroid Build Coastguard Worker z0 -= uint(z1 < borrow1); 1392*61046927SAndroid Build Coastguard Worker z1 -= borrow1; 1393*61046927SAndroid Build Coastguard Worker z0 -= borrow0; 1394*61046927SAndroid Build Coastguard Worker z2Ptr = z2; 1395*61046927SAndroid Build Coastguard Worker z1Ptr = z1; 1396*61046927SAndroid Build Coastguard Worker z0Ptr = z0; 1397*61046927SAndroid Build Coastguard Worker} 1398*61046927SAndroid Build Coastguard Worker 1399*61046927SAndroid Build Coastguard Worker/* Returns an approximation to the 32-bit integer quotient obtained by dividing 1400*61046927SAndroid Build Coastguard Worker * `b' into the 64-bit value formed by concatenating `a0' and `a1'. The 1401*61046927SAndroid Build Coastguard Worker * divisor `b' must be at least 2^31. If q is the exact quotient truncated 1402*61046927SAndroid Build Coastguard Worker * toward zero, the approximation returned lies between q and q + 2 inclusive. 1403*61046927SAndroid Build Coastguard Worker * If the exact quotient q is larger than 32 bits, the maximum positive 32-bit 1404*61046927SAndroid Build Coastguard Worker * unsigned integer is returned. 1405*61046927SAndroid Build Coastguard Worker */ 1406*61046927SAndroid Build Coastguard Workeruint 1407*61046927SAndroid Build Coastguard Worker__estimateDiv64To32(uint a0, uint a1, uint b) 1408*61046927SAndroid Build Coastguard Worker{ 1409*61046927SAndroid Build Coastguard Worker uint b0; 1410*61046927SAndroid Build Coastguard Worker uint b1; 1411*61046927SAndroid Build Coastguard Worker uint rem0 = 0u; 1412*61046927SAndroid Build Coastguard Worker uint rem1 = 0u; 1413*61046927SAndroid Build Coastguard Worker uint term0 = 0u; 1414*61046927SAndroid Build Coastguard Worker uint term1 = 0u; 1415*61046927SAndroid Build Coastguard Worker uint z; 1416*61046927SAndroid Build Coastguard Worker 1417*61046927SAndroid Build Coastguard Worker if (b <= a0) 1418*61046927SAndroid Build Coastguard Worker return 0xFFFFFFFFu; 1419*61046927SAndroid Build Coastguard Worker b0 = b>>16; 1420*61046927SAndroid Build Coastguard Worker z = (b0<<16 <= a0) ? 0xFFFF0000u : (a0 / b0)<<16; 1421*61046927SAndroid Build Coastguard Worker umulExtended(b, z, term0, term1); 1422*61046927SAndroid Build Coastguard Worker __sub64(a0, a1, term0, term1, rem0, rem1); 1423*61046927SAndroid Build Coastguard Worker while (int(rem0) < 0) { 1424*61046927SAndroid Build Coastguard Worker z -= 0x10000u; 1425*61046927SAndroid Build Coastguard Worker b1 = b<<16; 1426*61046927SAndroid Build Coastguard Worker __add64(rem0, rem1, b0, b1, rem0, rem1); 1427*61046927SAndroid Build Coastguard Worker } 1428*61046927SAndroid Build Coastguard Worker rem0 = (rem0<<16) | (rem1>>16); 1429*61046927SAndroid Build Coastguard Worker z |= (b0<<16 <= rem0) ? 0xFFFFu : rem0 / b0; 1430*61046927SAndroid Build Coastguard Worker return z; 1431*61046927SAndroid Build Coastguard Worker} 1432*61046927SAndroid Build Coastguard Worker 1433*61046927SAndroid Build Coastguard Workeruint 1434*61046927SAndroid Build Coastguard Worker__sqrtOddAdjustments(int index) 1435*61046927SAndroid Build Coastguard Worker{ 1436*61046927SAndroid Build Coastguard Worker uint res = 0u; 1437*61046927SAndroid Build Coastguard Worker if (index == 0) 1438*61046927SAndroid Build Coastguard Worker res = 0x0004u; 1439*61046927SAndroid Build Coastguard Worker if (index == 1) 1440*61046927SAndroid Build Coastguard Worker res = 0x0022u; 1441*61046927SAndroid Build Coastguard Worker if (index == 2) 1442*61046927SAndroid Build Coastguard Worker res = 0x005Du; 1443*61046927SAndroid Build Coastguard Worker if (index == 3) 1444*61046927SAndroid Build Coastguard Worker res = 0x00B1u; 1445*61046927SAndroid Build Coastguard Worker if (index == 4) 1446*61046927SAndroid Build Coastguard Worker res = 0x011Du; 1447*61046927SAndroid Build Coastguard Worker if (index == 5) 1448*61046927SAndroid Build Coastguard Worker res = 0x019Fu; 1449*61046927SAndroid Build Coastguard Worker if (index == 6) 1450*61046927SAndroid Build Coastguard Worker res = 0x0236u; 1451*61046927SAndroid Build Coastguard Worker if (index == 7) 1452*61046927SAndroid Build Coastguard Worker res = 0x02E0u; 1453*61046927SAndroid Build Coastguard Worker if (index == 8) 1454*61046927SAndroid Build Coastguard Worker res = 0x039Cu; 1455*61046927SAndroid Build Coastguard Worker if (index == 9) 1456*61046927SAndroid Build Coastguard Worker res = 0x0468u; 1457*61046927SAndroid Build Coastguard Worker if (index == 10) 1458*61046927SAndroid Build Coastguard Worker res = 0x0545u; 1459*61046927SAndroid Build Coastguard Worker if (index == 11) 1460*61046927SAndroid Build Coastguard Worker res = 0x631u; 1461*61046927SAndroid Build Coastguard Worker if (index == 12) 1462*61046927SAndroid Build Coastguard Worker res = 0x072Bu; 1463*61046927SAndroid Build Coastguard Worker if (index == 13) 1464*61046927SAndroid Build Coastguard Worker res = 0x0832u; 1465*61046927SAndroid Build Coastguard Worker if (index == 14) 1466*61046927SAndroid Build Coastguard Worker res = 0x0946u; 1467*61046927SAndroid Build Coastguard Worker if (index == 15) 1468*61046927SAndroid Build Coastguard Worker res = 0x0A67u; 1469*61046927SAndroid Build Coastguard Worker 1470*61046927SAndroid Build Coastguard Worker return res; 1471*61046927SAndroid Build Coastguard Worker} 1472*61046927SAndroid Build Coastguard Worker 1473*61046927SAndroid Build Coastguard Workeruint 1474*61046927SAndroid Build Coastguard Worker__sqrtEvenAdjustments(int index) 1475*61046927SAndroid Build Coastguard Worker{ 1476*61046927SAndroid Build Coastguard Worker uint res = 0u; 1477*61046927SAndroid Build Coastguard Worker if (index == 0) 1478*61046927SAndroid Build Coastguard Worker res = 0x0A2Du; 1479*61046927SAndroid Build Coastguard Worker if (index == 1) 1480*61046927SAndroid Build Coastguard Worker res = 0x08AFu; 1481*61046927SAndroid Build Coastguard Worker if (index == 2) 1482*61046927SAndroid Build Coastguard Worker res = 0x075Au; 1483*61046927SAndroid Build Coastguard Worker if (index == 3) 1484*61046927SAndroid Build Coastguard Worker res = 0x0629u; 1485*61046927SAndroid Build Coastguard Worker if (index == 4) 1486*61046927SAndroid Build Coastguard Worker res = 0x051Au; 1487*61046927SAndroid Build Coastguard Worker if (index == 5) 1488*61046927SAndroid Build Coastguard Worker res = 0x0429u; 1489*61046927SAndroid Build Coastguard Worker if (index == 6) 1490*61046927SAndroid Build Coastguard Worker res = 0x0356u; 1491*61046927SAndroid Build Coastguard Worker if (index == 7) 1492*61046927SAndroid Build Coastguard Worker res = 0x029Eu; 1493*61046927SAndroid Build Coastguard Worker if (index == 8) 1494*61046927SAndroid Build Coastguard Worker res = 0x0200u; 1495*61046927SAndroid Build Coastguard Worker if (index == 9) 1496*61046927SAndroid Build Coastguard Worker res = 0x0179u; 1497*61046927SAndroid Build Coastguard Worker if (index == 10) 1498*61046927SAndroid Build Coastguard Worker res = 0x0109u; 1499*61046927SAndroid Build Coastguard Worker if (index == 11) 1500*61046927SAndroid Build Coastguard Worker res = 0x00AFu; 1501*61046927SAndroid Build Coastguard Worker if (index == 12) 1502*61046927SAndroid Build Coastguard Worker res = 0x0068u; 1503*61046927SAndroid Build Coastguard Worker if (index == 13) 1504*61046927SAndroid Build Coastguard Worker res = 0x0034u; 1505*61046927SAndroid Build Coastguard Worker if (index == 14) 1506*61046927SAndroid Build Coastguard Worker res = 0x0012u; 1507*61046927SAndroid Build Coastguard Worker if (index == 15) 1508*61046927SAndroid Build Coastguard Worker res = 0x0002u; 1509*61046927SAndroid Build Coastguard Worker 1510*61046927SAndroid Build Coastguard Worker return res; 1511*61046927SAndroid Build Coastguard Worker} 1512*61046927SAndroid Build Coastguard Worker 1513*61046927SAndroid Build Coastguard Worker/* Returns an approximation to the square root of the 32-bit significand given 1514*61046927SAndroid Build Coastguard Worker * by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of 1515*61046927SAndroid Build Coastguard Worker * `aExp' (the least significant bit) is 1, the integer returned approximates 1516*61046927SAndroid Build Coastguard Worker * 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' 1517*61046927SAndroid Build Coastguard Worker * is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either 1518*61046927SAndroid Build Coastguard Worker * case, the approximation returned lies strictly within +/-2 of the exact 1519*61046927SAndroid Build Coastguard Worker * value. 1520*61046927SAndroid Build Coastguard Worker */ 1521*61046927SAndroid Build Coastguard Workeruint 1522*61046927SAndroid Build Coastguard Worker__estimateSqrt32(int aExp, uint a) 1523*61046927SAndroid Build Coastguard Worker{ 1524*61046927SAndroid Build Coastguard Worker uint z; 1525*61046927SAndroid Build Coastguard Worker 1526*61046927SAndroid Build Coastguard Worker int index = int(a>>27 & 15u); 1527*61046927SAndroid Build Coastguard Worker if ((aExp & 1) != 0) { 1528*61046927SAndroid Build Coastguard Worker z = 0x4000u + (a>>17) - __sqrtOddAdjustments(index); 1529*61046927SAndroid Build Coastguard Worker z = ((a / z)<<14) + (z<<15); 1530*61046927SAndroid Build Coastguard Worker a >>= 1; 1531*61046927SAndroid Build Coastguard Worker } else { 1532*61046927SAndroid Build Coastguard Worker z = 0x8000u + (a>>17) - __sqrtEvenAdjustments(index); 1533*61046927SAndroid Build Coastguard Worker z = a / z + z; 1534*61046927SAndroid Build Coastguard Worker z = (0x20000u <= z) ? 0xFFFF8000u : (z<<15); 1535*61046927SAndroid Build Coastguard Worker if (z <= a) 1536*61046927SAndroid Build Coastguard Worker return uint(int(a)>>1); 1537*61046927SAndroid Build Coastguard Worker } 1538*61046927SAndroid Build Coastguard Worker return ((__estimateDiv64To32(a, 0u, z))>>1) + (z>>1); 1539*61046927SAndroid Build Coastguard Worker} 1540*61046927SAndroid Build Coastguard Worker 1541*61046927SAndroid Build Coastguard Worker/* Returns the square root of the double-precision floating-point value `a'. 1542*61046927SAndroid Build Coastguard Worker * The operation is performed according to the IEEE Standard for Floating-Point 1543*61046927SAndroid Build Coastguard Worker * Arithmetic. 1544*61046927SAndroid Build Coastguard Worker */ 1545*61046927SAndroid Build Coastguard Workeruint64_t 1546*61046927SAndroid Build Coastguard Worker__fsqrt64(uint64_t a) 1547*61046927SAndroid Build Coastguard Worker{ 1548*61046927SAndroid Build Coastguard Worker uint zFrac0 = 0u; 1549*61046927SAndroid Build Coastguard Worker uint zFrac1 = 0u; 1550*61046927SAndroid Build Coastguard Worker uint zFrac2 = 0u; 1551*61046927SAndroid Build Coastguard Worker uint doubleZFrac0 = 0u; 1552*61046927SAndroid Build Coastguard Worker uint rem0 = 0u; 1553*61046927SAndroid Build Coastguard Worker uint rem1 = 0u; 1554*61046927SAndroid Build Coastguard Worker uint rem2 = 0u; 1555*61046927SAndroid Build Coastguard Worker uint rem3 = 0u; 1556*61046927SAndroid Build Coastguard Worker uint term0 = 0u; 1557*61046927SAndroid Build Coastguard Worker uint term1 = 0u; 1558*61046927SAndroid Build Coastguard Worker uint term2 = 0u; 1559*61046927SAndroid Build Coastguard Worker uint term3 = 0u; 1560*61046927SAndroid Build Coastguard Worker uint64_t default_nan = 0xFFFFFFFFFFFFFFFFUL; 1561*61046927SAndroid Build Coastguard Worker 1562*61046927SAndroid Build Coastguard Worker uint aFracLo = __extractFloat64FracLo(a); 1563*61046927SAndroid Build Coastguard Worker uint aFracHi = __extractFloat64FracHi(a); 1564*61046927SAndroid Build Coastguard Worker int aExp = __extractFloat64Exp(a); 1565*61046927SAndroid Build Coastguard Worker uint aSign = __extractFloat64Sign(a); 1566*61046927SAndroid Build Coastguard Worker if (aExp == 0x7FF) { 1567*61046927SAndroid Build Coastguard Worker if ((aFracHi | aFracLo) != 0u) 1568*61046927SAndroid Build Coastguard Worker return __propagateFloat64NaN(a, a); 1569*61046927SAndroid Build Coastguard Worker if (aSign == 0u) 1570*61046927SAndroid Build Coastguard Worker return a; 1571*61046927SAndroid Build Coastguard Worker return default_nan; 1572*61046927SAndroid Build Coastguard Worker } 1573*61046927SAndroid Build Coastguard Worker if (aSign != 0u) { 1574*61046927SAndroid Build Coastguard Worker if ((uint(aExp) | aFracHi | aFracLo) == 0u) 1575*61046927SAndroid Build Coastguard Worker return a; 1576*61046927SAndroid Build Coastguard Worker return default_nan; 1577*61046927SAndroid Build Coastguard Worker } 1578*61046927SAndroid Build Coastguard Worker if (aExp == 0) { 1579*61046927SAndroid Build Coastguard Worker if ((aFracHi | aFracLo) == 0u) 1580*61046927SAndroid Build Coastguard Worker return __packFloat64(0u, 0, 0u, 0u); 1581*61046927SAndroid Build Coastguard Worker __normalizeFloat64Subnormal(aFracHi, aFracLo, aExp, aFracHi, aFracLo); 1582*61046927SAndroid Build Coastguard Worker } 1583*61046927SAndroid Build Coastguard Worker int zExp = ((aExp - 0x3FF)>>1) + 0x3FE; 1584*61046927SAndroid Build Coastguard Worker aFracHi |= 0x00100000u; 1585*61046927SAndroid Build Coastguard Worker __shortShift64Left(aFracHi, aFracLo, 11, term0, term1); 1586*61046927SAndroid Build Coastguard Worker zFrac0 = (__estimateSqrt32(aExp, term0)>>1) + 1u; 1587*61046927SAndroid Build Coastguard Worker if (zFrac0 == 0u) 1588*61046927SAndroid Build Coastguard Worker zFrac0 = 0x7FFFFFFFu; 1589*61046927SAndroid Build Coastguard Worker doubleZFrac0 = zFrac0 + zFrac0; 1590*61046927SAndroid Build Coastguard Worker __shortShift64Left(aFracHi, aFracLo, 9 - (aExp & 1), aFracHi, aFracLo); 1591*61046927SAndroid Build Coastguard Worker umulExtended(zFrac0, zFrac0, term0, term1); 1592*61046927SAndroid Build Coastguard Worker __sub64(aFracHi, aFracLo, term0, term1, rem0, rem1); 1593*61046927SAndroid Build Coastguard Worker while (int(rem0) < 0) { 1594*61046927SAndroid Build Coastguard Worker --zFrac0; 1595*61046927SAndroid Build Coastguard Worker doubleZFrac0 -= 2u; 1596*61046927SAndroid Build Coastguard Worker __add64(rem0, rem1, 0u, doubleZFrac0 | 1u, rem0, rem1); 1597*61046927SAndroid Build Coastguard Worker } 1598*61046927SAndroid Build Coastguard Worker zFrac1 = __estimateDiv64To32(rem1, 0u, doubleZFrac0); 1599*61046927SAndroid Build Coastguard Worker if ((zFrac1 & 0x1FFu) <= 5u) { 1600*61046927SAndroid Build Coastguard Worker if (zFrac1 == 0u) 1601*61046927SAndroid Build Coastguard Worker zFrac1 = 1u; 1602*61046927SAndroid Build Coastguard Worker umulExtended(doubleZFrac0, zFrac1, term1, term2); 1603*61046927SAndroid Build Coastguard Worker __sub64(rem1, 0u, term1, term2, rem1, rem2); 1604*61046927SAndroid Build Coastguard Worker umulExtended(zFrac1, zFrac1, term2, term3); 1605*61046927SAndroid Build Coastguard Worker __sub96(rem1, rem2, 0u, 0u, term2, term3, rem1, rem2, rem3); 1606*61046927SAndroid Build Coastguard Worker while (int(rem1) < 0) { 1607*61046927SAndroid Build Coastguard Worker --zFrac1; 1608*61046927SAndroid Build Coastguard Worker __shortShift64Left(0u, zFrac1, 1, term2, term3); 1609*61046927SAndroid Build Coastguard Worker term3 |= 1u; 1610*61046927SAndroid Build Coastguard Worker term2 |= doubleZFrac0; 1611*61046927SAndroid Build Coastguard Worker __add96(rem1, rem2, rem3, 0u, term2, term3, rem1, rem2, rem3); 1612*61046927SAndroid Build Coastguard Worker } 1613*61046927SAndroid Build Coastguard Worker zFrac1 |= uint((rem1 | rem2 | rem3) != 0u); 1614*61046927SAndroid Build Coastguard Worker } 1615*61046927SAndroid Build Coastguard Worker __shift64ExtraRightJamming(zFrac0, zFrac1, 0u, 10, zFrac0, zFrac1, zFrac2); 1616*61046927SAndroid Build Coastguard Worker return __roundAndPackFloat64(0u, zExp, zFrac0, zFrac1, zFrac2); 1617*61046927SAndroid Build Coastguard Worker} 1618*61046927SAndroid Build Coastguard Worker 1619*61046927SAndroid Build Coastguard Workeruint64_t 1620*61046927SAndroid Build Coastguard Worker__ftrunc64(uint64_t __a) 1621*61046927SAndroid Build Coastguard Worker{ 1622*61046927SAndroid Build Coastguard Worker uvec2 a = unpackUint2x32(__a); 1623*61046927SAndroid Build Coastguard Worker int aExp = __extractFloat64Exp(__a); 1624*61046927SAndroid Build Coastguard Worker uint zLo; 1625*61046927SAndroid Build Coastguard Worker uint zHi; 1626*61046927SAndroid Build Coastguard Worker 1627*61046927SAndroid Build Coastguard Worker int unbiasedExp = aExp - 1023; 1628*61046927SAndroid Build Coastguard Worker int fracBits = 52 - unbiasedExp; 1629*61046927SAndroid Build Coastguard Worker uint maskLo = mix(~0u << fracBits, 0u, fracBits >= 32); 1630*61046927SAndroid Build Coastguard Worker uint maskHi = mix(~0u << (fracBits - 32), ~0u, fracBits < 33); 1631*61046927SAndroid Build Coastguard Worker zLo = maskLo & a.x; 1632*61046927SAndroid Build Coastguard Worker zHi = maskHi & a.y; 1633*61046927SAndroid Build Coastguard Worker 1634*61046927SAndroid Build Coastguard Worker zLo = mix(zLo, 0u, unbiasedExp < 0); 1635*61046927SAndroid Build Coastguard Worker zHi = mix(zHi, 0u, unbiasedExp < 0); 1636*61046927SAndroid Build Coastguard Worker zLo = mix(zLo, a.x, unbiasedExp > 52); 1637*61046927SAndroid Build Coastguard Worker zHi = mix(zHi, a.y, unbiasedExp > 52); 1638*61046927SAndroid Build Coastguard Worker return packUint2x32(uvec2(zLo, zHi)); 1639*61046927SAndroid Build Coastguard Worker} 1640*61046927SAndroid Build Coastguard Worker 1641*61046927SAndroid Build Coastguard Workeruint64_t 1642*61046927SAndroid Build Coastguard Worker__ffloor64(uint64_t a) 1643*61046927SAndroid Build Coastguard Worker{ 1644*61046927SAndroid Build Coastguard Worker /* The big assumption is that when 'a' is NaN, __ftrunc(a) returns a. Based 1645*61046927SAndroid Build Coastguard Worker * on that assumption, NaN values that don't have the sign bit will safely 1646*61046927SAndroid Build Coastguard Worker * return NaN (identity). This is guarded by RELAXED_NAN_PROPAGATION 1647*61046927SAndroid Build Coastguard Worker * because otherwise the NaN should have the "signal" bit set. The 1648*61046927SAndroid Build Coastguard Worker * __fadd64 will ensure that occurs. 1649*61046927SAndroid Build Coastguard Worker */ 1650*61046927SAndroid Build Coastguard Worker bool is_positive = 1651*61046927SAndroid Build Coastguard Worker#if defined RELAXED_NAN_PROPAGATION 1652*61046927SAndroid Build Coastguard Worker int(unpackUint2x32(a).y) >= 0 1653*61046927SAndroid Build Coastguard Worker#else 1654*61046927SAndroid Build Coastguard Worker __fge64(a, 0ul) 1655*61046927SAndroid Build Coastguard Worker#endif 1656*61046927SAndroid Build Coastguard Worker ; 1657*61046927SAndroid Build Coastguard Worker uint64_t tr = __ftrunc64(a); 1658*61046927SAndroid Build Coastguard Worker 1659*61046927SAndroid Build Coastguard Worker if (is_positive || __feq64(tr, a)) { 1660*61046927SAndroid Build Coastguard Worker return tr; 1661*61046927SAndroid Build Coastguard Worker } else { 1662*61046927SAndroid Build Coastguard Worker return __fadd64(tr, 0xbff0000000000000ul /* -1.0 */); 1663*61046927SAndroid Build Coastguard Worker } 1664*61046927SAndroid Build Coastguard Worker} 1665*61046927SAndroid Build Coastguard Worker 1666*61046927SAndroid Build Coastguard Workeruint64_t 1667*61046927SAndroid Build Coastguard Worker__fround64(uint64_t __a) 1668*61046927SAndroid Build Coastguard Worker{ 1669*61046927SAndroid Build Coastguard Worker uvec2 a = unpackUint2x32(__a); 1670*61046927SAndroid Build Coastguard Worker int unbiasedExp = __extractFloat64Exp(__a) - 1023; 1671*61046927SAndroid Build Coastguard Worker uint aHi = a.y; 1672*61046927SAndroid Build Coastguard Worker uint aLo = a.x; 1673*61046927SAndroid Build Coastguard Worker 1674*61046927SAndroid Build Coastguard Worker if (unbiasedExp < 20) { 1675*61046927SAndroid Build Coastguard Worker if (unbiasedExp < 0) { 1676*61046927SAndroid Build Coastguard Worker if ((aHi & 0x80000000u) != 0u && aLo == 0u) { 1677*61046927SAndroid Build Coastguard Worker return 0ul; 1678*61046927SAndroid Build Coastguard Worker } 1679*61046927SAndroid Build Coastguard Worker aHi &= 0x80000000u; 1680*61046927SAndroid Build Coastguard Worker if ((a.y & 0x000FFFFFu) == 0u && a.x == 0u) { 1681*61046927SAndroid Build Coastguard Worker aLo = 0u; 1682*61046927SAndroid Build Coastguard Worker return packUint2x32(uvec2(aLo, aHi)); 1683*61046927SAndroid Build Coastguard Worker } 1684*61046927SAndroid Build Coastguard Worker aHi = mix(aHi, (aHi | 0x3FF00000u), unbiasedExp == -1); 1685*61046927SAndroid Build Coastguard Worker aLo = 0u; 1686*61046927SAndroid Build Coastguard Worker } else { 1687*61046927SAndroid Build Coastguard Worker uint maskExp = 0x000FFFFFu >> unbiasedExp; 1688*61046927SAndroid Build Coastguard Worker uint lastBit = maskExp + 1; 1689*61046927SAndroid Build Coastguard Worker aHi += 0x00080000u >> unbiasedExp; 1690*61046927SAndroid Build Coastguard Worker if ((aHi & maskExp) == 0u) 1691*61046927SAndroid Build Coastguard Worker aHi &= ~lastBit; 1692*61046927SAndroid Build Coastguard Worker aHi &= ~maskExp; 1693*61046927SAndroid Build Coastguard Worker aLo = 0u; 1694*61046927SAndroid Build Coastguard Worker } 1695*61046927SAndroid Build Coastguard Worker } else if (unbiasedExp > 51 || unbiasedExp == 1024) { 1696*61046927SAndroid Build Coastguard Worker return __a; 1697*61046927SAndroid Build Coastguard Worker } else { 1698*61046927SAndroid Build Coastguard Worker uint maskExp = 0xFFFFFFFFu >> (unbiasedExp - 20); 1699*61046927SAndroid Build Coastguard Worker if ((aLo & maskExp) == 0u) 1700*61046927SAndroid Build Coastguard Worker return __a; 1701*61046927SAndroid Build Coastguard Worker uint tmp = aLo + (1u << (51 - unbiasedExp)); 1702*61046927SAndroid Build Coastguard Worker if(tmp < aLo) 1703*61046927SAndroid Build Coastguard Worker aHi += 1u; 1704*61046927SAndroid Build Coastguard Worker aLo = tmp; 1705*61046927SAndroid Build Coastguard Worker aLo &= ~maskExp; 1706*61046927SAndroid Build Coastguard Worker } 1707*61046927SAndroid Build Coastguard Worker 1708*61046927SAndroid Build Coastguard Worker return packUint2x32(uvec2(aLo, aHi)); 1709*61046927SAndroid Build Coastguard Worker} 1710*61046927SAndroid Build Coastguard Worker 1711*61046927SAndroid Build Coastguard Workeruint64_t 1712*61046927SAndroid Build Coastguard Worker__fmin64(uint64_t a, uint64_t b) 1713*61046927SAndroid Build Coastguard Worker{ 1714*61046927SAndroid Build Coastguard Worker /* This weird layout matters. Doing the "obvious" thing results in extra 1715*61046927SAndroid Build Coastguard Worker * flow control being inserted to implement the short-circuit evaluation 1716*61046927SAndroid Build Coastguard Worker * rules. Flow control is bad! 1717*61046927SAndroid Build Coastguard Worker */ 1718*61046927SAndroid Build Coastguard Worker bool b_nan = __is_nan(b); 1719*61046927SAndroid Build Coastguard Worker bool a_lt_b = __flt64_nonnan_minmax(a, b); 1720*61046927SAndroid Build Coastguard Worker bool a_nan = __is_nan(a); 1721*61046927SAndroid Build Coastguard Worker 1722*61046927SAndroid Build Coastguard Worker return (b_nan || a_lt_b) && !a_nan ? a : b; 1723*61046927SAndroid Build Coastguard Worker} 1724*61046927SAndroid Build Coastguard Worker 1725*61046927SAndroid Build Coastguard Workeruint64_t 1726*61046927SAndroid Build Coastguard Worker__fmax64(uint64_t a, uint64_t b) 1727*61046927SAndroid Build Coastguard Worker{ 1728*61046927SAndroid Build Coastguard Worker /* This weird layout matters. Doing the "obvious" thing results in extra 1729*61046927SAndroid Build Coastguard Worker * flow control being inserted to implement the short-circuit evaluation 1730*61046927SAndroid Build Coastguard Worker * rules. Flow control is bad! 1731*61046927SAndroid Build Coastguard Worker */ 1732*61046927SAndroid Build Coastguard Worker bool b_nan = __is_nan(b); 1733*61046927SAndroid Build Coastguard Worker bool a_lt_b = __flt64_nonnan_minmax(a, b); 1734*61046927SAndroid Build Coastguard Worker bool a_nan = __is_nan(a); 1735*61046927SAndroid Build Coastguard Worker 1736*61046927SAndroid Build Coastguard Worker return (b_nan || a_lt_b) && !a_nan ? b : a; 1737*61046927SAndroid Build Coastguard Worker} 1738*61046927SAndroid Build Coastguard Worker 1739*61046927SAndroid Build Coastguard Workeruint64_t 1740*61046927SAndroid Build Coastguard Worker__ffract64(uint64_t a) 1741*61046927SAndroid Build Coastguard Worker{ 1742*61046927SAndroid Build Coastguard Worker return __fadd64(a, __fneg64(__ffloor64(a))); 1743*61046927SAndroid Build Coastguard Worker} 1744*61046927SAndroid Build Coastguard Worker 1745*61046927SAndroid Build Coastguard Workerbool 1746*61046927SAndroid Build Coastguard Worker__fisfinite64(uint64_t __a) 1747*61046927SAndroid Build Coastguard Worker{ 1748*61046927SAndroid Build Coastguard Worker return __extractFloat64Exp(__a) != 0x7ff; 1749*61046927SAndroid Build Coastguard Worker} 1750