/* Portable version which should work on pretty much any compiler. *Obviouslyyoucan'trelyoncompilersupportforthingslike *conversionto/from32-bitfloats,somakesureyoualwaysusethe *functionsandmacrosinthisfile! * *Theportableimplementationsare(heavily)basedonCC0codeby *FabianGiesen:<https://gist.github.com/rygorous/2156668> (see also *<https://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/>). *IhavebasicallyjustmodifiedittogetridofsomeUB(lotsof *aliasing,rightshiftinganegativevalue),usefixed-widthtypes,
* and work in C. */ #define SIMDE_FLOAT16_API_PORTABLE 1 /* _Float16, per C standard (TS 18661-3;
* <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1945.pdf>). */ #define SIMDE_FLOAT16_API_FLOAT16 2 /* clang >= 6.0 supports __fp16 as an interchange format on all *targets,butonlyallowsyoutousethemforargumentsandreturn *valuesontargetswhichhavedefinedanABI.Wegetaroundthe *restrictionbywrappingthe__fp16inastruct,butwecan'tdo *thatonArmsinceitwouldbreakcompatibilitywiththeNEONF16
* functions. */ #define SIMDE_FLOAT16_API_FP16_NO_ABI 3 /* This is basically __fp16 as specified by Arm, where arugments and
* return values are raw __fp16 values not structs. */ #define SIMDE_FLOAT16_API_FP16 4
/* Choosing an implementation. This is a bit rough, but I don't have *anyideasonhowtoimproveit.Ifyoudo,patchesaredefinitely
* welcome. */ #if !defined(SIMDE_FLOAT16_API) #if0 && !defined(__cplusplus) /* I haven't found a way to detect this. It seems like defining *__STDC_WANT_IEC_60559_TYPES_EXT__,thenincludingfloat.h,then *checkingfordefined(FLT16_MAX)shouldwork,butbothgccand *clangwilldefinetheconstantsevenif_Float16isnot
* supported. Ideas welcome. */ #define SIMDE_FLOAT16_API SIMDE_FLOAT16_API_FLOAT16 #elifdefined(__ARM_FP16_FORMAT_IEEE) && defined(SIMDE_ARM_NEON_FP16) #define SIMDE_FLOAT16_API SIMDE_FLOAT16_API_FP16 #elifdefined(__FLT16_MIN__) && (defined(__clang__) && (!defined(SIMDE_ARCH_AARCH64) || SIMDE_DETECT_CLANG_VERSION_CHECK(7,0,0))) #define SIMDE_FLOAT16_API SIMDE_FLOAT16_API_FP16_NO_ABI #else #define SIMDE_FLOAT16_API SIMDE_FLOAT16_API_PORTABLE #endif #endif
/* Reinterpret -- you *generally* shouldn't need these, they're really *intendedforinternaluse.However,onx86half-precisionfloats
* get stuffed into a __m128i/__m256i, so it may be useful. */
/* NOTE all the integer compares in this function cast the operands *tosignedvaluestohelpcompilersvectorizetoSSE2,whichlacks *unsignedcomparisoninstructions.Thisisfinesinceall
* operands are below 0x80000000 (we clear the sign bit). */
if (f32u > f16u_max) { /* result is Inf or NaN (all exponent bits set) */
f16u = (f32u > f32u_infty) ? UINT32_C(0x7e00) : UINT32_C(0x7c00); /* NaN->qNaN and Inf->Inf */
} else { /* (De)normalized number or zero */ if (f32u < (UINT32_C(113) << 23)) { /* resulting FP16 is subnormal or zero */ /* use a magic value to align our 10 mantissa bits at the bottom of *thefloat.aslongasFPadditionisround-to-nearest-eventhis
* just works. */
f32u = simde_float32_as_uint32(simde_uint32_as_float32(f32u) + simde_uint32_as_float32(denorm_magic));
/* and one integer subtract of the bias later, we have our final float! */
f16u = HEDLEY_STATIC_CAST(uint16_t, f32u - denorm_magic);
} else {
uint32_t mant_odd = (f32u >> 13) & 1;
/* update exponent, rounding bias part 1 */
f32u += (HEDLEY_STATIC_CAST(uint32_t, 15 - 127) << 23) + UINT32_C(0xfff); /* rounding bias part 2 */
f32u += mant_odd; /* take the bits! */
f16u = HEDLEY_STATIC_CAST(uint16_t, f32u >> 13);
}
}
f16u |= sign >> 16;
res = simde_uint16_as_float16(f16u); #endif
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.