-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfixed32.c
More file actions
188 lines (153 loc) · 4.82 KB
/
fixed32.c
File metadata and controls
188 lines (153 loc) · 4.82 KB
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
Copyright 2011 Hoyoung Lee.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, please visit www.gnu.org.
*/
#include <stdio.h>
#include <stdint.h>
#include <limits.h>
#include <stdlib.h>
#include <inttypes.h>
#include "fixed32.h"
fixed32_t fixed32_convert(fixed32_t fix32, fixed32_qformat_t q1, fixed32_qformat_t q2)
{
int dist;
dist = q2 - q1;
if (dist > 0) fix32 <<= dist;
else if (dist < 0) fix32 >>= abs(dist);
return fix32;
}
fixed32_qformat_t fixed32_get_qformat_covering_range(double fmin, double fmax)
{
fixed32_qformat_t q;
fixed32_t fixmin = INT32_MIN, fixmax = INT32_MAX;
for (q = Q0_31; q >= Q30_1; --q) {
if ((fmin >= fixed32_to_double(fixmin, q)) &&
(fmax <= fixed32_to_double(fixmax, q)))
return q;
}
fprintf(stderr, "This range isn't covered by 'fixed32' at %s, line %d.\n", __FILE__, __LINE__);
//exit(-1);
return q; // Q32_OUT_OF_RANGE
}
fixed32_qformat_t fixed32_get_qformat_covering_resolution(double epsilon)
{
fixed32_t value;
fixed32_qformat_t q;
value = 1;
for (q = Q30_1; q <= Q0_31; ++q) {
if (epsilon >= fixed32_to_double(value, q))
return q;
}
fprintf(stderr, "This resolution isn't specified by 'fixed32' at %s, line %d.\n", __FILE__, __LINE__);
//exit(-1);
return q; // Q32_OUT_OF_RESOLUTION
}
void fixed32_generate_resolutions_in_float(void)
{
fixed32_qformat_t q;
printf("Q format of 32bit - Unit resolution in float-typed container\n");
for (q = Q30_1; q <= Q0_31; ++q) {
printf("\tQ%d.%d:\t%.18e\n", 31-q, q, fixed32_to_float((fixed32_t)1, q));
}
}
void fixed32_generate_resolutions_in_double(void)
{
fixed32_qformat_t q;
printf("Q format of 32bit - Unit resolution in double-typed container\n");
for (q = Q30_1; q <= Q0_31; q++) {
printf("\tQ%d.%d:\t%.18e\n", 31-q, q, fixed32_to_double((fixed32_t)1, q));
}
}
void fixed32_generate_ranges_in_float(void)
{
fixed32_t vmin, vmax;
fixed32_qformat_t q;
printf("Q format of 32bit - Covering range in float-typed container\n");
vmin = INT32_MIN;
vmax = INT32_MAX;
for (q = Q30_1; q <= Q0_31; ++q) {
printf("\tQ%d.%d:\t[%.18e, %.18e]\n", 31-q, q, fixed32_to_float(vmin, q), fixed32_to_float(vmax, q));
}
}
void fixed32_generate_ranges_in_double(void)
{
fixed32_t vmin, vmax;
fixed32_qformat_t q;
printf("Q format of 16bit - Covering range in double-typed container\n");
vmin = INT32_MIN;
vmax = INT32_MAX;
for (q = Q30_1; q <= Q0_31; ++q) {
printf("\tQ%d.%d:\t[%.18e, %.18e]\n", 31-q, q, fixed32_to_double(vmin, q), fixed32_to_double(vmax, q));
}
}
fixed32_t fixed32_add_with_trim(fixed32_t a, fixed32_t b)
{
fixed32_t c;
int64_t tmp;
tmp = (int64_t)a + (int64_t)b;
if (tmp > INT32_MAX) {
fprintf(stderr, "The saturation is occurred at %s, line %d.\n", __FILE__, __LINE__);
tmp = INT32_MAX;
} else if (tmp < INT32_MIN) {
fprintf(stderr, "The saturation is occurred at %s, line %d.\n", __FILE__, __LINE__);
tmp = INT32_MIN;
}
c = (fixed32_t)tmp;
return c;
}
fixed32_t fixed32_subtract_with_trim(fixed32_t a, fixed32_t b)
{
fixed32_t c;
int64_t tmp;
tmp = (int64_t)a - (int64_t)b;
if (tmp > INT32_MAX) {
fprintf(stderr, "The saturation is occurred at %s, line %d.\n", __FILE__, __LINE__);
tmp = INT32_MAX;
} else if (tmp < INT32_MIN) {
fprintf(stderr, "The saturation is occurred at %s, line %d.\n", __FILE__, __LINE__);
tmp = INT32_MIN;
}
c = (fixed32_t)tmp;
return c;
}
fixed32_t fixed32_multiply(fixed32_t a, fixed32_t b, fixed32_qformat_t q)
{
fixed32_t c;
int64_t tmp;
tmp = (int64_t)a * (int64_t)b;
// Rounding
tmp += (1 << (q-1));
tmp >>= q;
if (tmp > INT32_MAX) {
fprintf(stderr, "The saturation is occurred at %s, line %d.\n", __FILE__, __LINE__);
tmp = INT32_MAX;
} else if (tmp < INT32_MIN) {
fprintf(stderr, "The saturation is occurred at %s, line %d.\n", __FILE__, __LINE__);
tmp = INT32_MIN;
}
c = (fixed32_t)tmp;
return c;
}
fixed32_t fixed32_divide(fixed32_t a, fixed32_t b, fixed32_qformat_t q)
{
fixed32_t c;
int64_t tmp;
// pre-multiply by the base (Upscale to Q16 so that will be in Q8 format)
tmp = (int64_t)a << q;
// Rounding: mid values are rounded up (down for negative values).
if ((tmp >= 0 && b >= 0) || (tmp < 0 && b < 0))
tmp += b>>1;
else
tmp -= b>>1;
c = (fixed32_t)(tmp / b);
return c;
}