DataTypes.h revision d1688744d537d928699b6069f99c4470a0f6e772
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
21bool AlmostEqualUlps(float A, float B, int maxUlpsDiff);
22int UlpsDiff(float A, float B);
23int FloatAsInt(float A);
24
25#define USE_EPSILON 0
26
27#if USE_EPSILON
28extern const double PointEpsilon;
29extern const double SquaredEpsilon;
30
31inline bool approximately_equal(double x, double y) {
32    return fabs(x - y) < PointEpsilon;
33}
34
35inline bool approximately_equal_squared(double x, double y) {
36    return fabs(x - y) < SquaredEpsilon;
37}
38
39inline bool approximately_greater(double x, double y) {
40    return x > y - PointEpsilon;
41}
42
43inline bool approximately_lesser(double x, double y) {
44    return x < y + PointEpsilon;
45}
46
47inline bool approximately_zero(double x) {
48    return fabs(x) < PointEpsilon;
49}
50
51inline bool approximately_zero_squared(double x) {
52    return fabs(x) < SquaredEpsilon;
53}
54
55inline bool approximately_negative(double x) {
56    return x < PointEpsilon;
57}
58#else
59extern const int UlpsEpsilon;
60
61#if defined(IN_TEST)
62// FIXME: move to test-only header
63const double PointEpsilon = 0.000001;
64const double SquaredEpsilon = PointEpsilon * PointEpsilon;
65#endif
66
67inline bool approximately_zero(double x) {
68
69    return fabs(x) < FLT_EPSILON;
70}
71
72inline bool approximately_zero(float x) {
73
74    return fabs(x) < FLT_EPSILON;
75}
76
77inline bool approximately_zero_squared(double x) {
78    return fabs(x) < FLT_EPSILON * FLT_EPSILON;
79}
80
81inline bool approximately_equal(double x, double y) {
82    if (approximately_zero(x - y)) {
83        return true;
84    }
85    return AlmostEqualUlps((float) x, (float) y, UlpsEpsilon);
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 approximately_less_than_zero(double x) {
113    return x < FLT_EPSILON;
114}
115
116inline bool approximately_negative(double x) {
117    return x < FLT_EPSILON;
118}
119
120inline bool approximately_one_or_less(double x) {
121    return x < 1 + FLT_EPSILON;
122}
123
124inline bool approximately_positive(double x) {
125    return x > -FLT_EPSILON;
126}
127
128inline bool approximately_zero_or_more(double x) {
129    return x > -FLT_EPSILON;
130}
131
132inline bool approximately_between(double a, double b, double c) {
133    assert(a <= c);
134    return a <= c ? approximately_negative(a - b) && approximately_negative(b - c)
135            : approximately_negative(b - a) && approximately_negative(c - b);
136}
137
138// returns true if (a <= b <= c) || (a >= b >= c)
139inline bool between(double a, double b, double c) {
140    assert(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <= 0));
141    return (a - b) * (c - b) <= 0;
142}
143
144#endif
145
146struct _Point {
147    double x;
148    double y;
149
150    void operator-=(const _Point& v) {
151        x -= v.x;
152        y -= v.y;
153    }
154
155    friend bool operator==(const _Point& a, const _Point& b) {
156        return a.x == b.x && a.y == b.y;
157    }
158
159    friend bool operator!=(const _Point& a, const _Point& b) {
160        return a.x!= b.x || a.y != b.y;
161    }
162
163    bool approximatelyEqual(const _Point& a) const {
164        return approximately_equal(a.y, y) && approximately_equal(a.x, x);
165    }
166
167};
168
169typedef _Point _Line[2];
170typedef _Point Quadratic[3];
171typedef _Point Cubic[4];
172
173struct _Rect {
174    double left;
175    double top;
176    double right;
177    double bottom;
178
179    void add(const _Point& pt) {
180        if (left > pt.x) {
181            left = pt.x;
182        }
183        if (top > pt.y) {
184            top = pt.y;
185        }
186        if (right < pt.x) {
187            right = pt.x;
188        }
189        if (bottom < pt.y) {
190            bottom = pt.y;
191        }
192    }
193
194    // FIXME: used by debugging only ?
195    bool contains(const _Point& pt) {
196        return approximately_between(left, pt.x, right)
197                && approximately_between(top, pt.y, bottom);
198    }
199
200    void set(const _Point& pt) {
201        left = right = pt.x;
202        top = bottom = pt.y;
203    }
204
205    void setBounds(const _Line& line) {
206        set(line[0]);
207        add(line[1]);
208    }
209
210    void setBounds(const Cubic& );
211    void setBounds(const Quadratic& );
212    void setRawBounds(const Cubic& );
213    void setRawBounds(const Quadratic& );
214};
215
216struct CubicPair {
217    const Cubic& first() const { return (const Cubic&) pts[0]; }
218    const Cubic& second() const { return (const Cubic&) pts[3]; }
219    _Point pts[7];
220};
221
222struct QuadraticPair {
223    const Quadratic& first() const { return (const Quadratic&) pts[0]; }
224    const Quadratic& second() const { return (const Quadratic&) pts[2]; }
225    _Point pts[5];
226};
227
228#endif // __DataTypes_h__
229