Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdint.h>
- typedef uint16_t Float16T;
- enum {
- FRAC_MASK = (1 << 10) - 1,
- EXP_MASK = ((1 << 5) - 1) << 10,
- SIGN_MASK = 1 << 15,
- FRAC_WIDTH = 10,
- FIXED_EXP = 24,
- EXP_WIDTH = 5,
- NAN = EXP_MASK + FRAC_MASK,
- CONST24 = 24
- };
- uint16_t is_nan(Float16T x) {
- if ((x & EXP_MASK) == EXP_MASK && (x & FRAC_MASK) != 0) {
- return 1;
- }
- return 0;
- }
- uint16_t is_inf(Float16T x) {
- if ((x & EXP_MASK) == EXP_MASK && (x & FRAC_MASK) == 0) {
- return 1;
- }
- return 0;
- }
- int64_t cast_fp16_to_fixed(Float16T x) {
- int64_t res;
- if (x & EXP_MASK) {
- res = (int64_t)((1 << FRAC_WIDTH) | (x & FRAC_MASK)) << (((x & EXP_MASK) >> FRAC_WIDTH) - 1);
- } else {
- res = x & FRAC_MASK;
- }
- if (x & SIGN_MASK) {
- res = -res;
- }
- return res;
- }
- Float16T cast_fixed_to_fp16(int64_t x) {
- int u = 0;
- if (x < 0) {
- x = -x;
- u = 1;
- }
- if (x <= ((1 << FRAC_WIDTH) | FRAC_MASK)) {
- if (u) {
- return SIGN_MASK | x;
- }
- return x;
- }
- int exp = 1;
- while (x >= (1 << (FRAC_WIDTH + 2))) {
- x = x >> 1;
- ++exp;
- }
- ++x;
- while (x >= 1 << (FRAC_WIDTH + 1)) {
- x = x >> 1;
- ++exp;
- }
- if (exp >= (1 << EXP_WIDTH) - 1) {
- if (u) {
- return EXP_MASK | SIGN_MASK;
- }
- return EXP_MASK;
- }
- if (u) {
- return SIGN_MASK | (exp << FRAC_WIDTH) | (x & FRAC_MASK);
- }
- return (exp << FRAC_WIDTH) | (x & FRAC_MASK);
- }
- uint16_t fp16_mul2(uint16_t x) {
- if (is_nan(x) || is_inf(x)) {
- return x;
- }
- return cast_fixed_to_fp16(cast_fp16_to_fixed(x) << 1);
- }
- uint16_t fp16_div2(uint16_t x) {
- if (is_nan(x) || is_inf(x)) {
- return x;
- }
- return cast_fixed_to_fp16(cast_fp16_to_fixed(x) >> 1);
- }
- uint16_t fp16_neg(uint16_t x) { return x ^ SIGN_MASK; }
- uint16_t fp16_add(uint16_t x, uint16_t y) {
- if ((is_nan(x) || is_inf(x)) || (is_inf(x) && is_inf(y) && (x ^ y) != 0)) {
- return NAN;
- }
- if (is_inf(x) || is_inf(y)) {
- return x;
- }
- return cast_fixed_to_fp16(cast_fp16_to_fixed(x) + cast_fp16_to_fixed(y));
- }
- int fp16_cmp(uint16_t x, uint16_t y) {
- if (is_inf(x) && is_inf(y)) {
- if (x == y) {
- return 0;
- }
- if (x & SIGN_MASK) {
- return 1;
- }
- return -1;
- }
- if (is_inf(x) && !is_inf(y)) {
- if (x & SIGN_MASK) {
- return -1;
- }
- return 1;
- }
- if (!is_inf(x) && is_inf(y)) {
- if (y & SIGN_MASK) {
- return 1;
- }
- return -1;
- }
- if (cast_fp16_to_fixed(x) < cast_fp16_to_fixed(y)) {
- return -1;
- }
- if (cast_fp16_to_fixed(x) == cast_fp16_to_fixed(y)) {
- return 0;
- }
- return 1;
- }
- uint16_t fp16_cast(unsigned int x) { return cast_fixed_to_fp16((int64_t)x << CONST24); }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement