-
Notifications
You must be signed in to change notification settings - Fork 0
/
afloat.h
120 lines (98 loc) · 3.26 KB
/
afloat.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//
// afloat.h
// AFloat
//
// Created by Chris Nash on 16/01/2022.
// Copyright © 2022 Chris Nash. All rights reserved.
//
#pragma once
#include <math.h>
#include <iostream>
template<class TYPE>
union afloat_t {
float f;
struct fp {
unsigned int mantissa : 23;
unsigned int exponent : 8;
unsigned int sign : 1;
} parts;
TYPE pcm;
afloat_t() : f(_zero) {}
static float encode(TYPE pcm){
unsigned int i = pcm | ((sizeof(TYPE) == 2 ? 135 : 143) << 23);
return *(float*)&i;
}
operator float() const {
return f - _bias;
}
afloat_t& operator=(signed char x){
pcm = (TYPE)((x << (sizeof(TYPE) == 2 ? 8 : 0)) + (1<<(sizeof(TYPE)*8-1)));
return *this;
}
afloat_t& operator=(unsigned char x){
pcm = (x << (sizeof(TYPE) == 2 ? 8 : 0));
return *this;
}
afloat_t& operator=(signed short x){
pcm = (TYPE)(x + (1<<(sizeof(TYPE)*8-1)));
return *this;
}
afloat_t& operator=(unsigned short x){
pcm = x;
return *this;
}
afloat_t& operator=(float x){
f = x + _bias;
return *this;
}
afloat_t& operator=(double x){
f = x + _bias;
return *this;
}
#define AFLOAT_BUFFER_SIZE 17
static void info() {
float buffer[AFLOAT_BUFFER_SIZE] = { 0 };
TYPE ibuffer[AFLOAT_BUFFER_SIZE] = { 0 };
printf("Memory: %d\n", (int)sizeof(afloat_t));
printf("Saving: %d > %d\n", (int)sizeof(buffer), (int)sizeof(ibuffer));
printf("bias = %f\n", afloat_t::_bias);
}
static bool check() {
bool status = true;
const int RANGE = 1<<(sizeof(TYPE)*8);
float buffer[AFLOAT_BUFFER_SIZE] = { 0 };
unsigned short ibuffer[AFLOAT_BUFFER_SIZE] = { 0 };
for(int x=0; x<AFLOAT_BUFFER_SIZE; x++){
buffer[x] = x / (float)(AFLOAT_BUFFER_SIZE - 1);
ibuffer[x] = std::min((int)(buffer[x] * RANGE), RANGE - 1);
}
const float TOLERANCE = sizeof(TYPE) == 2 ? 0.0001f : 0.01f;
afloat_t fl;
for(int x=0; x<AFLOAT_BUFFER_SIZE; x++){
fl.pcm = ibuffer[x];
float correct = buffer[x] * 2 - 1;
float encoded = fl;
if(correct != encoded && fabs(correct-encoded) > TOLERANCE){
if(status)
printf("afloat integrity check: failed\n");
status = false;
printf(" %f >> [%d|%d|%d] = %f", correct, fl.parts.mantissa, fl.parts.exponent, fl.parts.sign, encoded);
printf(" (+%f)\n", fabs(correct-encoded));
}else{
//printf(" %f >> [%d|%d|%d] = %f\n", correct, fl.parts.mantissa, fl.parts.exponent, fl.parts.sign, encoded);
}
}
if(status)
printf("afloat integrity check: passed\n");
return status;
}
private:
const static float _zero;
const static float _bias;
};
template<class TYPE>
const float afloat_t<TYPE>::_zero = afloat_t::encode(0);
template<class TYPE>
const float afloat_t<TYPE>::_bias = afloat_t::encode(1<<(sizeof(TYPE)*8-1));
typedef afloat_t<unsigned short> afloat;
typedef afloat_t<unsigned char> afloat8;