forked from aseprite/aseprite
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfixmath.h
149 lines (118 loc) · 2.8 KB
/
fixmath.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
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
/*
* Fixed point type.
* Based on Allegro library by Shawn Hargreaves.
*/
#ifndef FIXMATH_FIXMATH_H
#define FIXMATH_FIXMATH_H
#include "base/ints.h"
#include <cerrno>
namespace fixmath {
typedef int32_t fixed;
extern const fixed fixtorad_r;
extern const fixed radtofix_r;
extern fixed _cos_tbl[];
extern fixed _tan_tbl[];
extern fixed _acos_tbl[];
fixed fixsqrt(fixed x);
fixed fixhypot(fixed x, fixed y);
fixed fixatan(fixed x);
fixed fixatan2(fixed y, fixed x);
// ftofix and fixtof are used in generic C versions of fixmul and fixdiv
inline fixed ftofix(double x) {
if (x > 32767.0) {
errno = ERANGE;
return 0x7FFFFFFF;
}
if (x < -32767.0) {
errno = ERANGE;
return -0x7FFFFFFF;
}
return (fixed)(x * 65536.0 + (x < 0 ? -0.5 : 0.5));
}
inline double fixtof(fixed x) {
return (double)x / 65536.0;
};
inline fixed fixadd(fixed x, fixed y) {
fixed result = x + y;
if (result >= 0) {
if ((x < 0) && (y < 0)) {
errno = ERANGE;
return -0x7FFFFFFF;
}
return result;
}
if ((x > 0) && (y > 0)) {
errno = ERANGE;
return 0x7FFFFFFF;
}
return result;
}
inline fixed fixsub(fixed x, fixed y) {
fixed result = x - y;
if (result >= 0) {
if ((x < 0) && (y > 0)) {
errno = ERANGE;
return -0x7FFFFFFF;
}
return result;
}
if ((x > 0) && (y < 0)) {
errno = ERANGE;
return 0x7FFFFFFF;
}
return result;
}
inline fixed fixmul(fixed x, fixed y) {
return ftofix(fixtof(x) * fixtof(y));
}
inline fixed fixdiv(fixed x, fixed y) {
if (y == 0) {
errno = ERANGE;
return (x < 0) ? -0x7FFFFFFF : 0x7FFFFFFF;
}
return ftofix(fixtof(x) / fixtof(y));
}
inline int fixfloor(fixed x) {
/* (x >> 16) is not portable */
if (x >= 0)
return (x >> 16);
return ~((~x) >> 16);
}
inline int fixceil(fixed x) {
if (x > 0x7FFF0000) {
errno = ERANGE;
return 0x7FFF;
}
return fixfloor(x + 0xFFFF);
}
inline fixed itofix(int x) {
return x << 16;
}
inline int fixtoi(fixed x) {
return fixfloor(x) + ((x & 0x8000) >> 15);
}
inline fixed fixcos(fixed x) {
return _cos_tbl[((x + 0x4000) >> 15) & 0x1FF];
}
inline fixed fixsin(fixed x) {
return _cos_tbl[((x - 0x400000 + 0x4000) >> 15) & 0x1FF];
}
inline fixed fixtan(fixed x) {
return _tan_tbl[((x + 0x4000) >> 15) & 0xFF];
}
inline fixed fixacos(fixed x) {
if ((x < -65536) || (x > 65536)) {
errno = EDOM;
return 0;
}
return _acos_tbl[(x+65536+127)>>8];
}
inline fixed fixasin(fixed x) {
if ((x < -65536) || (x > 65536)) {
errno = EDOM;
return 0;
}
return 0x00400000 - _acos_tbl[(x+65536+127)>>8];
}
} // namespace fixmath
#endif