| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "floatRt.h" |
| #include <stdbool.h> |
| |
| |
| #include <stdio.h> |
| |
| /* |
| * FLOAT: |
| * seeeeeee emmmmmmm mmmmmmmm mmmmmmmm |
| * |
| * s = negative |
| * e = exponent |
| * m = mantissa (with one bit removed) |
| * |
| * if (e == 0xFF) |
| * if (f) val = inf |
| * else val = nan |
| * goto valDone |
| * else if (e == 0x00) |
| * useLeadingOne = 0 |
| * e = -126 |
| * else |
| * e = e - 127 |
| * useLeadingOne = 1 |
| * |
| * val = ((useLeadingOne << 24) + m) / (2 ^ 23) |
| * val *= 2 ^ e |
| * |
| * valDone: |
| * |
| * if (s) |
| * val = -val; |
| */ |
| |
| #define BIT_SIGN 0x80000000UL |
| #define MANTISSA_BITS 23 |
| #define EXP_SHIFT MANTISSA_BITS |
| #define EXP_ADJUST 127 |
| |
| |
| #ifdef USE_NANOHUB_FLOAT_RUNTIME |
| |
| uint64_t floatToUint64(float f) |
| { |
| uint32_t e, word = *(const uint32_t*)&f; |
| uint64_t ret; |
| |
| |
| //all negatives become zero |
| if (word & BIT_SIGN) |
| return 0; |
| |
| //all values with exponent < 0 are less than one and thus become zero |
| if (word < (EXP_ADJUST << EXP_SHIFT)) |
| return 0; |
| |
| //standard does not say what happens to NaNs, infs & other too-large values, we return a large value as an approximation (though a zero would be equally valid) |
| if (word >= (EXP_ADJUST + 64) << EXP_SHIFT) |
| return 0xFFFFFFFFFFFFFFFFULL; |
| |
| //get mantissa and the implied leading one |
| ret = (word & ((1 << MANTISSA_BITS) - 1)) | (1 << MANTISSA_BITS); |
| e = ((word >> EXP_SHIFT) - EXP_ADJUST); |
| |
| //shift it by the exp |
| if (e < MANTISSA_BITS) |
| ret >>= MANTISSA_BITS - e; |
| else |
| ret <<= e - MANTISSA_BITS; |
| |
| return ret; |
| } |
| |
| int64_t floatToInt64(float f) |
| { |
| uint32_t e, word = *(const uint32_t*)&f; |
| bool neg = (word & BIT_SIGN); |
| uint64_t ret; |
| |
| |
| //all negatives become positive for now |
| word &=~ BIT_SIGN; |
| |
| //all values with exponent < 0 are less than one and thus become zero |
| if (word < (EXP_ADJUST << EXP_SHIFT)) |
| return 0; |
| |
| //standard does not say what happens to NaNs, infs & other too-large values, we return a large value as an approximation (though a zero would be equally valid) |
| if (word >= (EXP_ADJUST + 63) << EXP_SHIFT) |
| ret = 0x7FFFFFFFFFFFFFFFULL; |
| |
| else { |
| //get mantissa and the implied leading one |
| ret = (word & ((1 << MANTISSA_BITS) - 1)) | (1 << MANTISSA_BITS); |
| e = ((word >> EXP_SHIFT) - EXP_ADJUST); |
| |
| //shift it by the exp |
| if (e < MANTISSA_BITS) |
| ret >>= MANTISSA_BITS - e; |
| else |
| ret <<= e - MANTISSA_BITS; |
| } |
| |
| if (neg) |
| ret = -ret; |
| |
| return ret; |
| } |
| |
| float floatFromUint64(uint64_t v) |
| { |
| uint32_t hi = v >> 32, lo = v; |
| |
| if (!hi) //this is very fast for cases where we fit into a uint32_t |
| return(float)lo; |
| else { |
| return ((float)hi) * 4294967296.0f + (float)lo; |
| } |
| } |
| |
| float floatFromInt64(int64_t v) |
| { |
| uint32_t hi = ((uint64_t)v) >> 32, lo = v; |
| |
| if ((hi == 0x00000000 && !(lo >> 31)) || (hi == 0xffffffff && (lo >> 31))) //this complex test is a lot faster then the simpler ((v >> 33) == -1 || (v >> 33) == 0) |
| return (float)(int32_t)lo; |
| else if (hi >> 31) //the case of 0x8000000000000000 is handled here, as negated it remains the same |
| return -floatFromUint64(-v); |
| else |
| return floatFromUint64(v); |
| } |
| |
| |
| |
| |
| |
| #endif // USE_NANOHUB_FLOAT_RUNTIME |