cd910107c74c046d65c4369d8f41ff6b747303b6
[riscv-isa-sim.git] / softfloat / f64_sqrt.c
1
2 #include <stdbool.h>
3 #include <stdint.h>
4 #include "platform.h"
5 #include "primitives.h"
6 #include "internals.h"
7 #include "specialize.h"
8 #include "softfloat.h"
9
10 float64_t f64_sqrt( float64_t a )
11 {
12 union ui64_f64 uA;
13 uint_fast64_t uiA;
14 bool signA;
15 int_fast16_t expA;
16 uint_fast64_t sigA, uiZ;
17 struct exp16_sig64 normExpSig;
18 int_fast16_t expZ;
19 uint_fast32_t sigZ32;
20 uint_fast64_t sigZ;
21 struct uint128 term, rem;
22 union ui64_f64 uZ;
23
24 uA.f = a;
25 uiA = uA.ui;
26 signA = signF64UI( uiA );
27 expA = expF64UI( uiA );
28 sigA = fracF64UI( uiA );
29 if ( expA == 0x7FF ) {
30 if ( sigA ) {
31 uiZ = softfloat_propagateNaNF64UI( uiA, 0 );
32 goto uiZ;
33 }
34 if ( ! signA ) return a;
35 goto invalid;
36 }
37 if ( signA ) {
38 if ( ! ( expA | sigA ) ) return a;
39 goto invalid;
40 }
41 if ( ! expA ) {
42 if ( ! sigA ) return a;
43 normExpSig = softfloat_normSubnormalF64Sig( sigA );
44 expA = normExpSig.exp;
45 sigA = normExpSig.sig;
46 }
47 expZ = ( ( expA - 0x3FF )>>1 ) + 0x3FE;
48 sigA |= UINT64_C( 0x0010000000000000 );
49 sigZ32 = softfloat_estimateSqrt32( expA, sigA>>21 );
50 sigA <<= 9 - ( expA & 1 );
51 sigZ =
52 softfloat_estimateDiv128To64( sigA, 0, (uint_fast64_t) sigZ32<<32 )
53 + ( (uint_fast64_t) sigZ32<<30 );
54 if ( ( sigZ & 0x1FF ) <= 5 ) {
55 term = softfloat_mul64To128( sigZ, sigZ );
56 rem = softfloat_sub128( sigA, 0, term.v64, term.v0 );
57 while ( UINT64_C( 0x8000000000000000 ) <= rem.v64 ) {
58 --sigZ;
59 rem =
60 softfloat_add128(
61 rem.v64, rem.v0, sigZ>>63, (uint64_t) ( sigZ<<1 ) );
62 }
63 sigZ |= ( ( rem.v64 | rem.v0 ) != 0 );
64 }
65 return softfloat_roundPackToF64( 0, expZ, sigZ );
66 invalid:
67 softfloat_raiseFlags( softfloat_flag_invalid );
68 uiZ = defaultNaNF64UI;
69 uiZ:
70 uZ.ui = uiZ;
71 return uZ.f;
72
73 }
74