Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
f16_rem.c File Reference
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
Include dependency graph for f16_rem.c:

Go to the source code of this file.

Functions

float16_t f16_rem (float16_t a, float16_t b)
 

Function Documentation

◆ f16_rem()

float16_t f16_rem ( float16_t a,
float16_t b )

Definition at line 44 of file f16_rem.c.

45{
46 union ui16_f16 uA;
47 uint_fast16_t uiA;
48 bool signA;
49 int_fast8_t expA;
50 uint_fast16_t sigA;
51 union ui16_f16 uB;
52 uint_fast16_t uiB;
53 int_fast8_t expB;
54 uint_fast16_t sigB;
55 struct exp8_sig16 normExpSig;
56 uint16_t rem;
57 int_fast8_t expDiff;
59 uint32_t recip32, q32;
60 uint16_t altRem, meanRem;
61 bool signRem;
62 uint_fast16_t uiZ;
63 union ui16_f16 uZ;
64
65 /*------------------------------------------------------------------------
66 *------------------------------------------------------------------------*/
67 uA.f = a;
68 uiA = uA.ui;
69 signA = signF16UI( uiA );
70 expA = expF16UI( uiA );
71 sigA = fracF16UI( uiA );
72 uB.f = b;
73 uiB = uB.ui;
74 expB = expF16UI( uiB );
75 sigB = fracF16UI( uiB );
76 /*------------------------------------------------------------------------
77 *------------------------------------------------------------------------*/
78 if ( expA == 0x1F ) {
79 if ( sigA || ((expB == 0x1F) && sigB) ) goto propagateNaN;
80 goto invalid;
81 }
82 if ( expB == 0x1F ) {
83 if ( sigB ) goto propagateNaN;
84 return a;
85 }
86 /*------------------------------------------------------------------------
87 *------------------------------------------------------------------------*/
88 if ( ! expB ) {
89 if ( ! sigB ) goto invalid;
90 normExpSig = softfloat_normSubnormalF16Sig( sigB );
91 expB = normExpSig.exp;
92 sigB = normExpSig.sig;
93 }
94 if ( ! expA ) {
95 if ( ! sigA ) return a;
96 normExpSig = softfloat_normSubnormalF16Sig( sigA );
97 expA = normExpSig.exp;
98 sigA = normExpSig.sig;
99 }
100 /*------------------------------------------------------------------------
101 *------------------------------------------------------------------------*/
102 rem = sigA | 0x0400;
103 sigB |= 0x0400;
104 expDiff = expA - expB;
105 if ( expDiff < 1 ) {
106 if ( expDiff < -1 ) return a;
107 sigB <<= 3;
108 if ( expDiff ) {
109 rem <<= 2;
110 q = 0;
111 } else {
112 rem <<= 3;
113 q = (sigB <= rem);
114 if ( q ) rem -= sigB;
115 }
116 } else {
117 recip32 = softfloat_approxRecip32_1( (uint_fast32_t) sigB<<21 );
118 /*--------------------------------------------------------------------
119 | Changing the shift of `rem' here requires also changing the initial
120 | subtraction from `expDiff'.
121 *--------------------------------------------------------------------*/
122 rem <<= 4;
123 expDiff -= 31;
124 /*--------------------------------------------------------------------
125 | The scale of `sigB' affects how many bits are obtained during each
126 | cycle of the loop. Currently this is 29 bits per loop iteration,
127 | which is believed to be the maximum possible.
128 *--------------------------------------------------------------------*/
129 sigB <<= 3;
130 for (;;) {
131 q32 = (rem * (uint_fast64_t) recip32)>>16;
132 if ( expDiff < 0 ) break;
133 rem = -((uint_fast16_t) q32 * sigB);
134 expDiff -= 29;
135 }
136 /*--------------------------------------------------------------------
137 | (`expDiff' cannot be less than -30 here.)
138 *--------------------------------------------------------------------*/
139 q32 >>= ~expDiff & 31;
140 q = q32;
141 rem = (rem<<(expDiff + 30)) - q * sigB;
142 }
143 /*------------------------------------------------------------------------
144 *------------------------------------------------------------------------*/
145 do {
146 altRem = rem;
147 ++q;
148 rem -= sigB;
149 } while ( ! (rem & 0x8000) );
150 meanRem = rem + altRem;
151 if ( (meanRem & 0x8000) || (! meanRem && (q & 1)) ) rem = altRem;
152 signRem = signA;
153 if ( 0x8000 <= rem ) {
154 signRem = ! signRem;
155 rem = -rem;
156 }
157 return softfloat_normRoundPackToF16( signRem, expB, rem );
158 /*------------------------------------------------------------------------
159 *------------------------------------------------------------------------*/
160 propagateNaN:
161 uiZ = softfloat_propagateNaNF16UI( uiA, uiB );
162 goto uiZ;
163 invalid:
165 uiZ = defaultNaNF16UI;
166 uiZ:
167 uZ.ui = uiZ;
168 return uZ.f;
169
170}
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB)
void softfloat_raiseFlags(uint_fast8_t flags)
#define defaultNaNF16UI
Definition specialize.h:88
#define expF16UI(a)
Definition internals.h:84
#define signF16UI(a)
Definition internals.h:83
#define fracF16UI(a)
Definition internals.h:85
struct exp8_sig16 softfloat_normSubnormalF16Sig(uint_fast16_t)
float16_t softfloat_normRoundPackToF16(bool, int_fast16_t, uint_fast16_t)
uint32_t softfloat_approxRecip32_1(uint32_t a)
@ softfloat_flag_invalid
Definition softfloat.h:89
unsigned short uint16_t
Definition stdint.h:125
unsigned int uint32_t
Definition stdint.h:126
uint16_t uint_fast16_t
Definition stdint.h:155
uint64_t uint_fast64_t
Definition stdint.h:157
int8_t int_fast8_t
Definition stdint.h:150
uint32_t uint_fast32_t
Definition stdint.h:156
float16_t f
Definition internals.h:45
Here is the call graph for this function: