190f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe/* 290f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe * Shamelessly lifted from Beej's Guide to Network Programming, found here: 390f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe * 490f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe * http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#serialization 590f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe * 690f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe * Below code was granted to the public domain. 790f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe */ 890f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe#include <inttypes.h> 9802ad4a83e92a30b5fdccf117d59fbb69068c054Jens Axboe#include "ieee754.h" 1090f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe 1190f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboeuint64_t pack754(long double f, unsigned bits, unsigned expbits) 1290f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe{ 1390f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe long double fnorm; 1490f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe int shift; 1590f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe long long sign, exp, significand; 1690f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe unsigned significandbits = bits - expbits - 1; // -1 for sign bit 1790f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe 1890f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe // get this special case out of the way 1990f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe if (f == 0.0) 2090f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe return 0; 2190f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe 2290f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe // check sign and begin normalization 2390f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe if (f < 0) { 2490f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe sign = 1; 2590f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe fnorm = -f; 2690f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe } else { 2790f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe sign = 0; 2890f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe fnorm = f; 2990f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe } 3090f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe 3190f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe // get the normalized form of f and track the exponent 3290f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe shift = 0; 3390f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe while (fnorm >= 2.0) { 3490f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe fnorm /= 2.0; 3590f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe shift++; 3690f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe } 3790f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe while (fnorm < 1.0) { 3890f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe fnorm *= 2.0; 3990f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe shift--; 4090f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe } 4190f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe fnorm = fnorm - 1.0; 4290f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe 4390f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe // calculate the binary form (non-float) of the significand data 4490f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe significand = fnorm * ((1LL << significandbits) + 0.5f); 4590f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe 4690f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe // get the biased exponent 4790f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe exp = shift + ((1 << (expbits - 1)) - 1); // shift + bias 4890f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe 4990f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe // return the final answer 5090f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe return (sign << (bits - 1)) | (exp << (bits-expbits - 1)) | significand; 5190f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe} 5290f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe 5390f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboelong double unpack754(uint64_t i, unsigned bits, unsigned expbits) 5490f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe{ 5590f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe long double result; 5690f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe long long shift; 5790f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe unsigned bias; 5890f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe unsigned significandbits = bits - expbits - 1; // -1 for sign bit 5990f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe 6090f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe if (i == 0) 6190f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe return 0.0; 6290f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe 6390f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe // pull the significand 6490f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe result = (i & ((1LL << significandbits) - 1)); // mask 6590f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe result /= (1LL << significandbits); // convert back to float 6690f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe result += 1.0f; // add the one back on 6790f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe 6890f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe // deal with the exponent 6990f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe bias = (1 << (expbits - 1)) - 1; 7090f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe shift = ((i >> significandbits) & ((1LL << expbits) - 1)) - bias; 7190f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe while (shift > 0) { 7290f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe result *= 2.0; 7390f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe shift--; 7490f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe } 7590f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe while (shift < 0) { 7690f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe result /= 2.0; 7790f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe shift++; 7890f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe } 7990f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe 8090f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe // sign it 8190f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe result *= (i >> (bits - 1)) & 1 ? -1.0 : 1.0; 8290f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe 8390f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe return result; 8490f326d04602d0df35ca32f251dd6cc353d26a25Jens Axboe} 85