|
#ifndef _RKNPU2_RKNN_MATMUL_API_DEMO_H_ |
|
#define _RKNPU2_RKNN_MATMUL_API_DEMO_H_ |
|
|
|
namespace rknpu2 { |
|
|
|
using ushort = unsigned short; |
|
|
|
typedef union suf32 |
|
{ |
|
int i; |
|
unsigned u; |
|
float f; |
|
} suf32; |
|
|
|
class float16 |
|
{ |
|
public: |
|
float16() {} |
|
explicit float16(float x) { w = bits(x); } |
|
|
|
operator float() const |
|
{ |
|
suf32 out; |
|
|
|
unsigned t = ((w & 0x7fff) << 13) + 0x38000000; |
|
unsigned sign = (w & 0x8000) << 16; |
|
unsigned e = w & 0x7c00; |
|
|
|
out.u = t + (1 << 23); |
|
out.u = (e >= 0x7c00 ? t + 0x38000000 : e == 0 ? (static_cast<void>(out.f -= 6.103515625e-05f), out.u) : t) | sign; |
|
return out.f; |
|
} |
|
|
|
static float16 fromBits(ushort b) |
|
{ |
|
float16 result; |
|
result.w = b; |
|
return result; |
|
} |
|
static float16 zero() |
|
{ |
|
float16 result; |
|
result.w = (ushort)0; |
|
return result; |
|
} |
|
ushort bits() const { return w; } |
|
|
|
static ushort bits(float x) |
|
{ |
|
suf32 in; |
|
in.f = x; |
|
unsigned sign = in.u & 0x80000000; |
|
in.u ^= sign; |
|
ushort w; |
|
|
|
if (in.u >= 0x47800000) |
|
w = (ushort)(in.u > 0x7f800000 ? 0x7e00 : 0x7c00); |
|
else { |
|
if (in.u < 0x38800000) { |
|
in.f += 0.5f; |
|
w = (ushort)(in.u - 0x3f000000); |
|
} else { |
|
unsigned t = in.u + 0xc8000fff; |
|
w = (ushort)((t + ((in.u >> 13) & 1)) >> 13); |
|
} |
|
} |
|
|
|
w = (ushort)(w | (sign >> 16)); |
|
|
|
return w; |
|
} |
|
|
|
float16& operator=(float x) |
|
{ |
|
w = bits(x); |
|
return *this; |
|
} |
|
|
|
float16& operator+=(float x) |
|
{ |
|
w = bits(float() + x); |
|
return *this; |
|
} |
|
|
|
float16& operator/(float x) |
|
{ |
|
w = bits(float() / x); |
|
return *this; |
|
} |
|
|
|
inline bool is_nan() const { return ((w & 0x7c00u) == 0x7c00u) && ((w & 0x03ffu) != 0x0000u); } |
|
|
|
inline bool greater(const float16& x) const |
|
{ |
|
bool sign = w & 0x8000; |
|
bool sign_x = x.w & 0x8000; |
|
if (sign) { |
|
if (sign_x) |
|
return w < x.w; |
|
else |
|
return false; |
|
} else { |
|
if (sign_x) |
|
|
|
return (w != 0 || x.w != 0x8000); |
|
else |
|
return w > x.w; |
|
} |
|
return false; |
|
} |
|
|
|
inline bool less(const float16& x) const |
|
{ |
|
bool sign = w & 0x8000; |
|
bool sign_x = x.w & 0x8000; |
|
if (sign) { |
|
if (sign_x) |
|
return w > x.w; |
|
else |
|
|
|
return (w != 0x8000 || x.w != 0); |
|
} else { |
|
if (sign_x) |
|
return false; |
|
else |
|
return w < x.w; |
|
} |
|
return false; |
|
} |
|
|
|
inline bool operator>(const float16& x) const |
|
{ |
|
if (is_nan() || x.is_nan()) { |
|
return false; |
|
} |
|
return greater(x); |
|
} |
|
|
|
inline bool operator<(const float16& x) const |
|
{ |
|
if (is_nan() || x.is_nan()) { |
|
return false; |
|
} |
|
return less(x); |
|
} |
|
|
|
inline bool operator>=(const float16& x) const |
|
{ |
|
if (is_nan() || x.is_nan()) { |
|
return false; |
|
} |
|
return !less(x); |
|
} |
|
|
|
inline bool operator<=(const float16& x) const |
|
{ |
|
if (is_nan() || x.is_nan()) { |
|
return false; |
|
} |
|
return !greater(x); |
|
} |
|
|
|
inline bool operator==(const float16& x) const |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
if (is_nan() || x.is_nan()) { |
|
return false; |
|
} |
|
return (w == x.w || ((w | x.w) & 0x7fff) == 0); |
|
} |
|
|
|
inline bool operator!=(const float16& x) const { return !((*this) == x); } |
|
|
|
protected: |
|
ushort w = 0; |
|
}; |
|
|
|
} |
|
|
|
#endif |