float32和float16互转(C语言实现)

// based on https://gist.github.com/martin-kallman/5049614
// float32
// Martin Kallman
//
// Fast half-precision to single-precision floating point conversion
//  - Supports signed zero and denormals-as-zero (DAZ)
//  - Does not support infinities or NaN
//  - Few, partially pipelinable, non-branching instructions,
//  - Core opreations ~6 clock cycles on modern x86-64
void float32(float *__restrict out, const short in) {
    unsigned int t1;
    unsigned int t2;
    unsigned int t3;
 
    t1 = in & 0x7fffu;                       // Non-sign bits
    t2 = in & 0x8000u;                       // Sign bit
    t3 = in & 0x7c00u;                       // Exponent
 
    t1 <<= 13u;                              // Align mantissa on MSB
    t2 <<= 16u;                              // Shift sign bit into position
 
    t1 += 0x38000000;                       // Adjust bias
 
    t1 = (t3 == 0 ? 0 : t1);                // Denormals-as-zero
 
    t1 |= t2;                               // Re-insert sign bit
 
    *((unsigned int *)out) = t1;
};
 
// float16
// Martin Kallman
//
// Fast single-precision to half-precision floating point conversion
//  - Supports signed zero, denormals-as-zero (DAZ), flush-to-zero (FTZ),
//    clamp-to-max
//  - Does not support infinities or NaN
//  - Few, partially pipelinable, non-branching instructions,
//  - Core opreations ~10 clock cycles on modern x86-64
void float16(short *__restrict out, const float in) {
    unsigned int  inu = *((unsigned int  *)& in);
    unsigned int  t1;
    unsigned int  t2;
    unsigned int  t3;
 
    t1 = inu & 0x7fffffffu;                 // Non-sign bits
    t2 = inu & 0x80000000u;                 // Sign bit
    t3 = inu & 0x7f800000u;                 // Exponent
 
    t1 >>= 13u;                             // Align mantissa on MSB
    t2 >>= 16u;                             // Shift sign bit into position
 
    t1 -= 0x1c000;                         // Adjust bias
 
    t1 = (t3 < 0x38800000u) ? 0 : t1;       // Flush-to-zero
    t1 = (t3 > 0x8e000000u) ? 0x7bff : t1;  // Clamp-to-max
    t1 = (t3 == 0 ? 0 : t1);               // Denormals-as-zero
 
    t1 |= t2;                              // Re-insert sign bit
 
    *((short *)out) = t1;
};
 
#define ABS(A) ((A) >= 0 ? (A) : -(A))
 
int main() {
    float original = -42.42f;
    short small = 0;
    float16(&small, original);
    float quantized = 0.0f;
    float32(&quantized, small);
    float diff = ABS(original - quantized);
    printf("orig %f quantized %f absdiff %f\n", original, quantized, diff);
    getchar();
    //assert(diff < 0.1f);
}

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值