OpenVDB 11.0.0
|
#include <openvdb/Platform.h>
#include <openvdb/version.h>
#include <iostream>
#include <stdint.h>
#include <stdio.h>
#include <limits>
Go to the source code of this file.
Classes | |
union | imath_half_uif |
a type for both C-only programs and C++ to use the same utilities More... | |
class | half |
class | numeric_limits< openvdb::math::internal::half > |
Namespaces | |
namespace | std |
Macros | |
#define | IMATH_HALF_NO_LOOKUP_TABLE |
#define | VDBB_HALF_DENORM_MIN 5.96046448e-08 |
#define | VDB_HALF_NRM_MIN 6.10351562e-05 |
#define | VDB_HALF_MIN 6.10351562e-05f |
#define | VDB_HALF_MAX 65504.0 |
#define | VDB_HALF_EPSILON 0.00097656 |
#define | VDB_HALF_MANT_DIG 11 |
#define | VDB_HALF_DIG 3 |
#define | VDB_HALF_DECIMAL_DIG 5 |
#define | VDB_HALF_RADIX 2 |
#define | VDBB_HALF_DENORM_MIN_EXP -13 |
#define | VDB_HALF_MAX_EXP 16 |
#define | VDBB_HALF_DENORM_MIN_10_EXP -4 |
#define | VDB_HALF_MAX_10_EXP 4 |
Typedefs | |
typedef union imath_half_uif | imath_half_uif_t |
a type for both C-only programs and C++ to use the same utilities | |
typedef uint16_t | imath_half_bits_t |
a type for both C-only programs and C++ to use the same utilities | |
typedef imath_half_bits_t | half |
if we're in a C-only context, alias the half bits type to half | |
Functions | |
static float | imath_half_to_float (imath_half_bits_t h) |
static imath_half_bits_t | imath_float_to_half (float f) |
OPENVDB_API void | printBits (std::ostream &os, half h) |
OPENVDB_API void | printBits (std::ostream &os, float f) |
OPENVDB_API void | printBits (char c[19], half h) |
OPENVDB_API void | printBits (char c[35], float f) |
OPENVDB_API std::ostream & | operator<< (std::ostream &os, half h) |
Output h to os, formatted as a float. | |
OPENVDB_API std::istream & | operator>> (std::istream &is, half &h) |
Input h from is. | |
The half type is a 16-bit floating number, compatible with the IEEE 754-2008 binary16 type.
Representation of a 32-bit float:
We assume that a float, f, is an IEEE 754 single-precision floating point number, whose bits are arranged as follows:
31 (msb) | | 30 23 | | | | | | 22 0 (lsb) | | | | | X XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX s e m
S is the sign-bit, e is the exponent and m is the significand.
If e is between 1 and 254, f is a normalized number:
s e-127 f = (-1) * 2 * 1.m
If e is 0, and m is not zero, f is a denormalized number:
s -126 f = (-1) * 2 * 0.m
If e and m are both zero, f is zero:
f = 0.0
If e is 255, f is an "infinity" or "not a number" (NAN), depending on whether m is zero or not.
Examples:
0 00000000 00000000000000000000000 = 0.0 0 01111110 00000000000000000000000 = 0.5 0 01111111 00000000000000000000000 = 1.0 0 10000000 00000000000000000000000 = 2.0 0 10000000 10000000000000000000000 = 3.0 1 10000101 11110000010000000000000 = -124.0625 0 11111111 00000000000000000000000 = +infinity 1 11111111 00000000000000000000000 = -infinity 0 11111111 10000000000000000000000 = NAN 1 11111111 11111111111111111111111 = NAN
Representation of a 16-bit half:
Here is the bit-layout for a half number, h:
15 (msb) | | 14 10 | | | | | | 9 0 (lsb) | | | | | X XXXXX XXXXXXXXXX s e m
S is the sign-bit, e is the exponent and m is the significand.
If e is between 1 and 30, h is a normalized number:
s e-15 h = (-1) * 2 * 1.m
If e is 0, and m is not zero, h is a denormalized number:
S -14 h = (-1) * 2 * 0.m
If e and m are both zero, h is zero:
h = 0.0
If e is 31, h is an "infinity" or "not a number" (NAN), depending on whether m is zero or not.
Examples:
0 00000 0000000000 = 0.0 0 01110 0000000000 = 0.5 0 01111 0000000000 = 1.0 0 10000 0000000000 = 2.0 0 10000 1000000000 = 3.0 1 10101 1111000001 = -124.0625 0 11111 0000000000 = +infinity 1 11111 0000000000 = -infinity 0 11111 1000000000 = NAN 1 11111 1111111111 = NAN
Conversion via Lookup Table:
Converting from half to float is performed by default using a lookup table. There are only 65,536 different half numbers; each of these numbers has been converted and stored in a table pointed to by the imath_half_to_float_table
pointer. / / Prior to Imath v3.1, conversion from float to half was / accomplished with the help of an exponent look table, but this is / now replaced with explicit bit shifting. / / Conversion via Hardware: / / For Imath v3.1, the conversion routines have been extended to use / F16C SSE instructions whenever present and enabled by compiler / flags. / / Conversion via Bit-Shifting / / If F16C SSE instructions are not available, conversion can be / accomplished by a bit-shifting algorithm. For half-to-float / conversion, this is generally slower than the lookup table, but it / may be preferable when memory limits preclude storing of the / 65,536-entry lookup table. / / The lookup table symbol is included in the compilation even if / IMATH_HALF_USE_LOOKUP_TABLE
is false, because application code / using the exported half.h
may choose to enable the use of the table. / / An implementation can eliminate the table from compilation by / defining the IMATH_HALF_NO_LOOKUP_TABLE
preprocessor symbol. / Simply add: / / #define IMATH_HALF_NO_LOOKUP_TABLE / / before including half.h
, or define the symbol on the compile / command line. / / Furthermore, an implementation wishing to receive FE_OVERFLOW
/ and FE_UNDERFLOW
floating point exceptions when converting / float to half by the bit-shift algorithm can define the / preprocessor symbol IMATH_HALF_ENABLE_FP_EXCEPTIONS
prior to / including half.h
: / / #define IMATH_HALF_ENABLE_FP_EXCEPTIONS / / Conversion Performance Comparison: / / Testing on a Core i9, the timings are approximately: / / half to float / - table: 0.71 ns / call / - no table: 1.06 ns / call / - f16c: 0.45 ns / call / / float-to-half: / - original: 5.2 ns / call / - no exp table + opt: 1.27 ns / call / - f16c: 0.45 ns / call / / Note: the timing above depends on the distribution of the / floats in question. /
OPENVDB_NO_TYPE_CONVERSION_WARNING_BEGIN
namespace openvdb { OPENVDB_USE_VERSION_NAMESPACE namespace v11_0 { namespace math { namespace internal {
Use of lookup table is explicitly suppressed and the generation of a lookup table is suppressed. This is required because we namespace our type, but the lookup table is extern "C" and lacks a namespace. Thus any attempt to link two versions of OpenVDB with different namespaces will clash due to redefinition with a new type. The default was not to use a lookup table.
#define IMATH_HALF_NO_LOOKUP_TABLE
Limits
Visual C++ will complain if VDBB_HALF_DENORM_MIN, VDB_HALF_NRM_MIN etc. are not float constants, but at least one other compiler (gcc 2.96) produces incorrect
/ Smallest positive denormalized half #define VDBB_HALF_DENORM_MIN
/ Smallest positive normalized half #define VDB_HALF_NRM_MIN
/ Smallest positive normalized half #define VDB_HALF_MIN
/ Largest positive half #define VDB_HALF_MAX
/ Smallest positive e for which half(1.0 + e) != half(1.0)
#define VDB_HALF_EPSILON
/ Number of digits in mantissa (significand + hidden leading 1) #define VDB_HALF_MANT_DIG
/ Number of base 10 digits that can be represented without change: / / floor( (HALF_MANT_DIG - 1) * log10(2) ) => 3.01... -> 3
#define VDB_HALF_DIG
/ Number of base-10 digits that are necessary to uniquely represent / all distinct values: / / ceil(HALF_MANT_DIG * log10(2) + 1) => 4.31... -> 5
#define VDB_HALF_DECIMAL_DIG
/ Base of the exponent #define VDB_HALF_RADIX
/ Minimum negative integer such that HALF_RADIX
raised to the power / of one less than that integer is a normalized half #define VDBB_HALF_DENORM_MIN_EXP
/ Maximum positive integer such that HALF_RADIX
raised to the power of one less than that integer is a normalized half
#define IMATH_HALF_NO_LOOKUP_TABLE |
#define VDB_HALF_DECIMAL_DIG 5 |
#define VDB_HALF_DIG 3 |
#define VDB_HALF_EPSILON 0.00097656 |
#define VDB_HALF_MANT_DIG 11 |
#define VDB_HALF_MAX 65504.0 |
#define VDB_HALF_MAX_10_EXP 4 |
Maximum positive integer such that 10 raised to that power is a normalized half
#define VDB_HALF_MAX_EXP 16 |
#define VDB_HALF_MIN 6.10351562e-05f |
#define VDB_HALF_NRM_MIN 6.10351562e-05 |
#define VDB_HALF_RADIX 2 |
#define VDBB_HALF_DENORM_MIN 5.96046448e-08 |
#define VDBB_HALF_DENORM_MIN_10_EXP -4 |
Minimum positive integer such that 10 raised to that power is a normalized half
#define VDBB_HALF_DENORM_MIN_EXP -13 |
typedef imath_half_bits_t half |
if we're in a C-only context, alias the half bits type to half
typedef uint16_t imath_half_bits_t |
a type for both C-only programs and C++ to use the same utilities
typedef union imath_half_uif imath_half_uif_t |
a type for both C-only programs and C++ to use the same utilities
|
inlinestatic |
Convert half to float
Note: This only supports the "round to even" rounding mode, which was the only mode supported by the original OpenEXR library
|
inlinestatic |
Convert half to float
OPENVDB_API std::ostream & operator<< | ( | std::ostream & | os, |
half | h ) |
Output h to os, formatted as a float.
OPENVDB_API std::istream & operator>> | ( | std::istream & | is, |
half & | h ) |
Input h from is.
OPENVDB_API void printBits | ( | char | c[19], |
half | h ) |
OPENVDB_API void printBits | ( | char | c[35], |
float | f ) |
OPENVDB_API void printBits | ( | std::ostream & | os, |
float | f ) |
OPENVDB_API void printBits | ( | std::ostream & | os, |
half | h ) |