summaryrefslogtreecommitdiff
path: root/include/libcss/fpmath.h
blob: bed5ee6f71386522a9f8a69f3c440d1388060cea (plain)
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
/*
 * This file is part of LibCSS.
 * Licensed under the MIT License,
 *                http://www.opensource.org/licenses/mit-license.php
 * Copyright 2008 John-Mark Bell <jmb@netsurf-browser.org>
 */

#ifndef libcss_fpmath_h_
#define libcss_fpmath_h_

#ifdef __cplusplus
extern "C"
{
#endif

#include <stdint.h>
#include <limits.h>

/* 22:10 fixed point math */
#define CSS_RADIX_POINT 10

/* type for fixed point numbers */
typedef int32_t css_fixed;

static inline css_fixed
css_add_fixed(const css_fixed x, const css_fixed y) {
	int32_t ux = x;
	int32_t uy = y;
	int32_t res = ux + uy;

	/* Calculate overflowed result. (Don't change the sign bit of ux) */
	ux = (ux >> 31) + INT_MAX;

	/* Force compiler to use cmovns instruction */
	if ((int32_t) ((ux ^ uy) | ~(uy ^ res)) >= 0) {
		res = ux;
	}

	return res;
}

static inline css_fixed
css_subtract_fixed(const css_fixed x, const css_fixed y) {
	int32_t ux = x;
	int32_t uy = y;
	int32_t res = ux - uy;

	ux = (ux >> 31) + INT_MAX;

	/* Force compiler to use cmovns instruction */
	if ((int32_t)((ux ^ uy) & (ux ^ res)) < 0) {
		res = ux;
	}

	return res;
}

static inline css_fixed
css_divide_fixed(const css_fixed x, const css_fixed y) {
	int64_t xx = ((int64_t)x * (1 << CSS_RADIX_POINT)) / y;

	if (xx < INT_MIN)
		xx = INT_MIN;

	if (xx > INT_MAX)
		xx = INT_MAX;

	return xx;
}

static inline css_fixed
css_multiply_fixed(const css_fixed x, const css_fixed y) {
	int64_t xx = ((int64_t)x * (int64_t)y) >> CSS_RADIX_POINT;

	if (xx < INT_MIN)
		xx = INT_MIN;

	if (xx > INT_MAX)
		xx = INT_MAX;

	return xx;
}

static inline css_fixed
css_int_to_fixed(const int a) {
	int64_t xx = ((int64_t) a) * (1 << CSS_RADIX_POINT);

	if (xx < INT_MIN)
		xx = INT_MIN;

	if (xx > INT_MAX)
		xx = INT_MAX;

	return xx;
}

static inline css_fixed
css_float_to_fixed(const float a) {
	float xx = a * (float) (1 << CSS_RADIX_POINT);

	if (xx < INT_MIN)
		xx = INT_MIN;

	if (xx > INT_MAX)
		xx = INT_MAX;

	return (css_fixed) xx;
}

/* Add two fixed point values */
#define FADD(a, b) (css_add_fixed((a), (b)))
/* Subtract two fixed point values */
#define FSUB(a, b) (css_subtract_fixed((a), (b)))
/* Multiply two fixed point values */
#define FMUL(a, b) (css_multiply_fixed((a), (b)))
/* Divide two fixed point values */
#define FDIV(a, b) (css_divide_fixed((a), (b)))

/* Convert a floating point value to fixed point */
#define FLTTOFIX(a) ((css_fixed) ((a) * (float) (1 << CSS_RADIX_POINT)))
/* Convert a fixed point value to floating point */
#define FIXTOFLT(a) ((float) (a) / (float) (1 << CSS_RADIX_POINT))

/* Convert an integer to a fixed point value */
#define INTTOFIX(a) (css_int_to_fixed(a))
/* Convert a fixed point value to an integer */
#define FIXTOINT(a) ((a) >> CSS_RADIX_POINT)

/* truncate a fixed point value */
#define TRUNCATEFIX(a) (a & ~((1 << CSS_RADIX_POINT)- 1 ))

/* Useful values */
#define F_PI_2	0x00000648	/* 1.5708 (PI/2) */
#define F_PI	0x00000c91	/* 3.1415 (PI) */
#define F_3PI_2	0x000012d9	/* 4.7124 (3PI/2) */
#define F_2PI	0x00001922	/* 6.2831 (2 PI) */

#define F_90	0x00016800	/*  90 */
#define F_180	0x0002d000	/* 180 */
#define F_270	0x00043800	/* 270 */
#define F_360	0x0005a000	/* 360 */

#define F_0_5	0x00000200	/* 0.5 */
#define F_1	0x00000400	/*   1 */
#define F_10	0x00002800	/*  10 */
#define F_72	0x00012000	/*  72 */
#define F_96	0x00018000	/*  96 */
#define F_100	0x00019000	/* 100 */
#define F_200	0x00032000	/* 200 */
#define F_255	0x0003FC00	/* 255 */
#define F_300	0x0004b000	/* 300 */
#define F_400	0x00064000	/* 400 */

#ifdef __cplusplus
}
#endif

#endif