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