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