DataTypes.h revision 85ec74ca543b13739db1ad55dedd7bdfae4ab1a6
1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7#ifndef __DataTypes_h__
8#define __DataTypes_h__
9
10#include <assert.h>
11#include <float.h>
12#include <limits.h>
13#include <math.h>
14#include <stdarg.h>
15#include <stdio.h>
16#include <stdint.h>
17#include <stdlib.h>
18#include <strings.h>
19#include <sys/types.h>
20
21extern bool AlmostEqualUlps(float A, float B);
22inline bool AlmostEqualUlps(double A, double B) { return AlmostEqualUlps((float) A, (float) B); }
23
24// FIXME: delete
25int UlpsDiff(float A, float B);
26
27// FLT_EPSILON == 1.19209290E-07 == 1 / (2 ^ 23)
28const double FLT_EPSILON_CUBED = FLT_EPSILON * FLT_EPSILON * FLT_EPSILON;
29const double FLT_EPSILON_SQUARED = FLT_EPSILON * FLT_EPSILON;
30const double FLT_EPSILON_SQRT = sqrt(FLT_EPSILON);
31const double FLT_EPSILON_INVERSE = 1 / FLT_EPSILON;
32
33inline bool approximately_zero(double x) {
34
35    return fabs(x) < FLT_EPSILON;
36}
37
38inline bool precisely_zero(double x) {
39
40    return fabs(x) < DBL_EPSILON;
41}
42
43inline bool approximately_zero(float x) {
44
45    return fabs(x) < FLT_EPSILON;
46}
47
48inline bool approximately_zero_cubed(double x) {
49    return fabs(x) < FLT_EPSILON_CUBED;
50}
51
52inline bool approximately_zero_squared(double x) {
53    return fabs(x) < FLT_EPSILON_SQUARED;
54}
55
56inline bool approximately_zero_sqrt(double x) {
57    return fabs(x) < FLT_EPSILON_SQRT;
58}
59
60inline bool approximately_zero_inverse(double x) {
61    return fabs(x) > FLT_EPSILON_INVERSE;
62}
63
64// Use this for comparing Ts in the range of 0 to 1. For general numbers (larger and smaller) use
65// AlmostEqualUlps instead.
66inline bool approximately_equal(double x, double y) {
67#if 1
68    return approximately_zero(x - y);
69#else
70// see http://visualstudiomagazine.com/blogs/tool-tracker/2011/11/compare-floating-point-numbers.aspx
71// this allows very small (e.g. degenerate) values to compare unequally, but in this case,
72// AlmostEqualUlps should be used instead.
73    if (x == y) {
74        return true;
75    }
76    double absY = fabs(y);
77    if (x == 0) {
78        return absY < FLT_EPSILON;
79    }
80    double absX = fabs(x);
81    if (y == 0) {
82        return absX < FLT_EPSILON;
83    }
84    return fabs(x - y) < (absX > absY ? absX : absY) * FLT_EPSILON;
85#endif
86}
87
88inline bool approximately_equal_squared(double x, double y) {
89    return approximately_equal(x, y);
90}
91
92inline bool approximately_greater(double x, double y) {
93    return approximately_equal(x, y) ? false : x > y;
94}
95
96inline bool approximately_lesser(double x, double y) {
97    return approximately_equal(x, y) ? false : x < y;
98}
99
100inline double approximately_pin(double x) {
101    return approximately_zero(x) ? 0 : x;
102}
103
104inline float approximately_pin(float x) {
105    return approximately_zero(x) ? 0 : x;
106}
107
108inline bool approximately_greater_than_one(double x) {
109    return x > 1 - FLT_EPSILON;
110}
111
112inline bool precisely_greater_than_one(double x) {
113    return x > 1 - DBL_EPSILON;
114}
115
116inline bool approximately_less_than_zero(double x) {
117    return x < FLT_EPSILON;
118}
119
120inline bool precisely_less_than_zero(double x) {
121    return x < DBL_EPSILON;
122}
123
124inline bool approximately_negative(double x) {
125    return x < FLT_EPSILON;
126}
127
128inline bool precisely_negative(double x) {
129    return x < DBL_EPSILON;
130}
131
132inline bool approximately_one_or_less(double x) {
133    return x < 1 + FLT_EPSILON;
134}
135
136inline bool approximately_positive(double x) {
137    return x > -FLT_EPSILON;
138}
139
140inline bool approximately_positive_squared(double x) {
141    return x > -(FLT_EPSILON_SQUARED);
142}
143
144inline bool approximately_zero_or_more(double x) {
145    return x > -FLT_EPSILON;
146}
147
148inline bool approximately_between(double a, double b, double c) {
149    assert(a <= c);
150    return a <= c ? approximately_negative(a - b) && approximately_negative(b - c)
151            : approximately_negative(b - a) && approximately_negative(c - b);
152}
153
154// returns true if (a <= b <= c) || (a >= b >= c)
155inline bool between(double a, double b, double c) {
156    assert(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <= 0));
157    return (a - b) * (c - b) <= 0;
158}
159
160struct _Point {
161    double x;
162    double y;
163
164    friend _Point operator-(const _Point& a, const _Point& b) {
165        _Point v = {a.x - b.x, a.y - b.y};
166        return v;
167    }
168
169    void operator+=(const _Point& v) {
170        x += v.x;
171        y += v.y;
172    }
173
174    void operator-=(const _Point& v) {
175        x -= v.x;
176        y -= v.y;
177    }
178
179    void operator/=(const double s) {
180        x /= s;
181        y /= s;
182    }
183
184    void operator*=(const double s) {
185        x *= s;
186        y *= s;
187    }
188
189    friend bool operator==(const _Point& a, const _Point& b) {
190        return a.x == b.x && a.y == b.y;
191    }
192
193    friend bool operator!=(const _Point& a, const _Point& b) {
194        return a.x != b.x || a.y != b.y;
195    }
196
197    // note: this can not be implemented with
198    // return approximately_equal(a.y, y) && approximately_equal(a.x, x);
199    // because that will not take the magnitude of the values
200    bool approximatelyEqual(const _Point& a) const {
201        return AlmostEqualUlps((float) x, (float) a.x)
202                && AlmostEqualUlps((float) y, (float) a.y);
203    }
204
205    double cross(const _Point& a) const {
206        return x * a.y - y * a.x;
207    }
208
209    double dot(const _Point& a) const {
210        return x * a.x + y * a.y;
211    }
212
213    double length() const {
214        return sqrt(lengthSquared());
215    }
216
217    double lengthSquared() const {
218        return x * x + y * y;
219    }
220
221};
222
223typedef _Point _Line[2];
224typedef _Point Quadratic[3];
225typedef _Point Cubic[4];
226
227struct _Rect {
228    double left;
229    double top;
230    double right;
231    double bottom;
232
233    void add(const _Point& pt) {
234        if (left > pt.x) {
235            left = pt.x;
236        }
237        if (top > pt.y) {
238            top = pt.y;
239        }
240        if (right < pt.x) {
241            right = pt.x;
242        }
243        if (bottom < pt.y) {
244            bottom = pt.y;
245        }
246    }
247
248    // FIXME: used by debugging only ?
249    bool contains(const _Point& pt) const {
250        return approximately_between(left, pt.x, right)
251                && approximately_between(top, pt.y, bottom);
252    }
253
254    bool intersects(_Rect& r) const {
255        assert(left <= right);
256        assert(top <= bottom);
257        assert(r.left <= r.right);
258        assert(r.top <= r.bottom);
259        return r.left <= right && left <= r.right && r.top <= bottom && top <= r.bottom;
260    }
261
262    void set(const _Point& pt) {
263        left = right = pt.x;
264        top = bottom = pt.y;
265    }
266
267    void setBounds(const _Line& line) {
268        set(line[0]);
269        add(line[1]);
270    }
271
272    void setBounds(const Cubic& );
273    void setBounds(const Quadratic& );
274    void setRawBounds(const Cubic& );
275    void setRawBounds(const Quadratic& );
276};
277
278struct CubicPair {
279    const Cubic& first() const { return (const Cubic&) pts[0]; }
280    const Cubic& second() const { return (const Cubic&) pts[3]; }
281    _Point pts[7];
282};
283
284struct QuadraticPair {
285    const Quadratic& first() const { return (const Quadratic&) pts[0]; }
286    const Quadratic& second() const { return (const Quadratic&) pts[2]; }
287    _Point pts[5];
288};
289
290// FIXME: move these into SkTypes.h
291template <typename T> inline T SkTMax(T a, T b) {
292    if (a < b)
293        a = b;
294    return a;
295}
296
297template <typename T> inline T SkTMin(T a, T b) {
298    if (a > b)
299        a = b;
300    return a;
301}
302
303#endif // __DataTypes_h__
304