19e49fb63d355446b91d20ff78ad78b297e89a50dcaryclark@google.com/*
29e49fb63d355446b91d20ff78ad78b297e89a50dcaryclark@google.com * Copyright 2012 Google Inc.
39e49fb63d355446b91d20ff78ad78b297e89a50dcaryclark@google.com *
49e49fb63d355446b91d20ff78ad78b297e89a50dcaryclark@google.com * Use of this source code is governed by a BSD-style license that can be
59e49fb63d355446b91d20ff78ad78b297e89a50dcaryclark@google.com * found in the LICENSE file.
69e49fb63d355446b91d20ff78ad78b297e89a50dcaryclark@google.com */
7639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com#ifndef __DataTypes_h__
8639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com#define __DataTypes_h__
9639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com
10aa35831d1d0e4c798a63fe772430adc4f3a038cdcaryclark@google.com#include <float.h> // for FLT_EPSILON
11aa35831d1d0e4c798a63fe772430adc4f3a038cdcaryclark@google.com#include <math.h> // for fabs, sqrt
12aa35831d1d0e4c798a63fe772430adc4f3a038cdcaryclark@google.com
1345a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com#include "SkPoint.h"
1445a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com
15ebf95ba28db75212a1313edc947ed68decc30273caryclark@google.com#define FORCE_RELEASE 0  // set force release to 1 for multiple thread -- no debugging
16ebf95ba28db75212a1313edc947ed68decc30273caryclark@google.com#define ONE_OFF_DEBUG 1
17d4c8e1e035bc2edb6caf2c9eac71ef918e60b80bcaryclark@google.com#define ONE_OFF_DEBUG_MATHEMATICA 0
182e7f4c810dc717383df42d27bdba862514ab6d51caryclark@google.com
19beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com// FIXME: move these into SkTypes.h
20beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.comtemplate <typename T> inline T SkTMax(T a, T b) {
21beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com    if (a < b)
22beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com        a = b;
23beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com    return a;
24beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com}
25beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com
26beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.comtemplate <typename T> inline T SkTMin(T a, T b) {
27beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com    if (a > b)
28beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com        a = b;
29beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com    return a;
30beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com}
31beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com
320b7da433fe0eaa2833d1b2900715b013b36d93dacaryclark@google.comextern bool AlmostEqualUlps(float A, float B);
336d0032a8ec680221c2a704cac2391f2a2d77546fcaryclark@google.cominline bool AlmostEqualUlps(double A, double B) { return AlmostEqualUlps((float) A, (float) B); }
346d0032a8ec680221c2a704cac2391f2a2d77546fcaryclark@google.com
350b7da433fe0eaa2833d1b2900715b013b36d93dacaryclark@google.com// FIXME: delete
36b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.comint UlpsDiff(float A, float B);
37b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com
389f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com// FLT_EPSILON == 1.19209290E-07 == 1 / (2 ^ 23)
3947d73daa7a971e7eee5822def7922f7d43b2dc47caryclark@google.com// DBL_EPSILON == 2.22045e-16
409f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.comconst double FLT_EPSILON_CUBED = FLT_EPSILON * FLT_EPSILON * FLT_EPSILON;
4145a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.comconst double FLT_EPSILON_HALF = FLT_EPSILON / 2;
4273ca6243b31e225e9fd5b75a96cbc82d62557de6caryclark@google.comconst double FLT_EPSILON_SQUARED = FLT_EPSILON * FLT_EPSILON;
4373ca6243b31e225e9fd5b75a96cbc82d62557de6caryclark@google.comconst double FLT_EPSILON_SQRT = sqrt(FLT_EPSILON);
4485ec74ca543b13739db1ad55dedd7bdfae4ab1a6caryclark@google.comconst double FLT_EPSILON_INVERSE = 1 / FLT_EPSILON;
4547d73daa7a971e7eee5822def7922f7d43b2dc47caryclark@google.comconst double DBL_EPSILON_ERR = DBL_EPSILON * 4; // tune -- allow a few bits of error
46996d78b7cf9863a5b574fc1b64b1715cad4d0a23caryclark@google.comconst double ROUGH_EPSILON = FLT_EPSILON * 64;
471304bb25aa3b0baa61fc2e2900fabcef88801b59caryclark@google.comconst double MORE_ROUGH_EPSILON = FLT_EPSILON * 256;
48d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
4945a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.cominline bool approximately_zero(double x) {
50b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com    return fabs(x) < FLT_EPSILON;
51b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com}
52b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com
53a461ff0866526bc51dbd4c4f9f066a727ec21510caryclark@google.cominline bool precisely_zero(double x) {
5447d73daa7a971e7eee5822def7922f7d43b2dc47caryclark@google.com    return fabs(x) < DBL_EPSILON_ERR;
55a461ff0866526bc51dbd4c4f9f066a727ec21510caryclark@google.com}
56a461ff0866526bc51dbd4c4f9f066a727ec21510caryclark@google.com
57c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.cominline bool approximately_zero(float x) {
58c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    return fabs(x) < FLT_EPSILON;
59c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com}
60c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com
619f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.cominline bool approximately_zero_cubed(double x) {
629f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com    return fabs(x) < FLT_EPSILON_CUBED;
639f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com}
649f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com
6545a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.cominline bool approximately_zero_half(double x) {
6645a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com    return fabs(x) < FLT_EPSILON_HALF;
6745a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com}
6845a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com
69d1688744d537d928699b6069f99c4470a0f6e772caryclark@google.cominline bool approximately_zero_squared(double x) {
7073ca6243b31e225e9fd5b75a96cbc82d62557de6caryclark@google.com    return fabs(x) < FLT_EPSILON_SQUARED;
7173ca6243b31e225e9fd5b75a96cbc82d62557de6caryclark@google.com}
7273ca6243b31e225e9fd5b75a96cbc82d62557de6caryclark@google.com
7373ca6243b31e225e9fd5b75a96cbc82d62557de6caryclark@google.cominline bool approximately_zero_sqrt(double x) {
7473ca6243b31e225e9fd5b75a96cbc82d62557de6caryclark@google.com    return fabs(x) < FLT_EPSILON_SQRT;
75d1688744d537d928699b6069f99c4470a0f6e772caryclark@google.com}
76d1688744d537d928699b6069f99c4470a0f6e772caryclark@google.com
7785ec74ca543b13739db1ad55dedd7bdfae4ab1a6caryclark@google.cominline bool approximately_zero_inverse(double x) {
7885ec74ca543b13739db1ad55dedd7bdfae4ab1a6caryclark@google.com    return fabs(x) > FLT_EPSILON_INVERSE;
7985ec74ca543b13739db1ad55dedd7bdfae4ab1a6caryclark@google.com}
8085ec74ca543b13739db1ad55dedd7bdfae4ab1a6caryclark@google.com
81beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com// FIXME: if called multiple times with the same denom, we want to pass 1/y instead
82f9502d7dfad5b361a3cdaa42eb75b593c95f79d8caryclark@google.cominline bool approximately_zero_when_compared_to(double x, double y) {
83beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com    return x == 0 || fabs(x / y) < FLT_EPSILON;
84f9502d7dfad5b361a3cdaa42eb75b593c95f79d8caryclark@google.com}
85f9502d7dfad5b361a3cdaa42eb75b593c95f79d8caryclark@google.com
869f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com// Use this for comparing Ts in the range of 0 to 1. For general numbers (larger and smaller) use
879f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com// AlmostEqualUlps instead.
88b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.cominline bool approximately_equal(double x, double y) {
899f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com#if 1
900b7da433fe0eaa2833d1b2900715b013b36d93dacaryclark@google.com    return approximately_zero(x - y);
919f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com#else
929f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com// see http://visualstudiomagazine.com/blogs/tool-tracker/2011/11/compare-floating-point-numbers.aspx
934024f32d99b63a599c544a49f526e53c25135159skia.committer@gmail.com// this allows very small (e.g. degenerate) values to compare unequally, but in this case,
949f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com// AlmostEqualUlps should be used instead.
959f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com    if (x == y) {
969f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com        return true;
979f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com    }
989f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com    double absY = fabs(y);
999f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com    if (x == 0) {
1009f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com        return absY < FLT_EPSILON;
1019f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com    }
1029f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com    double absX = fabs(x);
1039f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com    if (y == 0) {
1049f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com        return absX < FLT_EPSILON;
1059f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com    }
1069f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com    return fabs(x - y) < (absX > absY ? absX : absY) * FLT_EPSILON;
1079f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com#endif
108b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com}
109b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com
11047d73daa7a971e7eee5822def7922f7d43b2dc47caryclark@google.cominline bool precisely_equal(double x, double y) {
11147d73daa7a971e7eee5822def7922f7d43b2dc47caryclark@google.com    return precisely_zero(x - y);
11247d73daa7a971e7eee5822def7922f7d43b2dc47caryclark@google.com}
11347d73daa7a971e7eee5822def7922f7d43b2dc47caryclark@google.com
11445a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.cominline bool approximately_equal_half(double x, double y) {
11545a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com    return approximately_zero_half(x - y);
11645a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com}
11745a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com
118b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.cominline bool approximately_equal_squared(double x, double y) {
119b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com    return approximately_equal(x, y);
120b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com}
121b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com
122b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.cominline bool approximately_greater(double x, double y) {
1235e0500fb5f17fe14db42fc3e0aad08e6b41ccc5fcaryclark@google.com    return x - FLT_EPSILON >= y;
1245e0500fb5f17fe14db42fc3e0aad08e6b41ccc5fcaryclark@google.com}
1255e0500fb5f17fe14db42fc3e0aad08e6b41ccc5fcaryclark@google.com
1265e0500fb5f17fe14db42fc3e0aad08e6b41ccc5fcaryclark@google.cominline bool approximately_greater_or_equal(double x, double y) {
1275e0500fb5f17fe14db42fc3e0aad08e6b41ccc5fcaryclark@google.com    return x + FLT_EPSILON > y;
128b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com}
129b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com
130b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.cominline bool approximately_lesser(double x, double y) {
1315e0500fb5f17fe14db42fc3e0aad08e6b41ccc5fcaryclark@google.com    return x + FLT_EPSILON <= y;
1325e0500fb5f17fe14db42fc3e0aad08e6b41ccc5fcaryclark@google.com}
1335e0500fb5f17fe14db42fc3e0aad08e6b41ccc5fcaryclark@google.com
1345e0500fb5f17fe14db42fc3e0aad08e6b41ccc5fcaryclark@google.cominline bool approximately_lesser_or_equal(double x, double y) {
1355e0500fb5f17fe14db42fc3e0aad08e6b41ccc5fcaryclark@google.com    return x - FLT_EPSILON < y;
136b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com}
137b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com
138c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.cominline double approximately_pin(double x) {
139c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    return approximately_zero(x) ? 0 : x;
140c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com}
141c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com
142c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.cominline float approximately_pin(float x) {
143c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com    return approximately_zero(x) ? 0 : x;
144c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com}
145c899ad9c7fa28234d99479ab09afb6866bbd8dc3caryclark@google.com
1463350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.cominline bool approximately_greater_than_one(double x) {
1473350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.com    return x > 1 - FLT_EPSILON;
1483350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.com}
1493350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.com
150185c7c47983dde02b5542cf45fe3fc58a3ecb055caryclark@google.cominline bool precisely_greater_than_one(double x) {
15147d73daa7a971e7eee5822def7922f7d43b2dc47caryclark@google.com    return x > 1 - DBL_EPSILON_ERR;
152185c7c47983dde02b5542cf45fe3fc58a3ecb055caryclark@google.com}
153185c7c47983dde02b5542cf45fe3fc58a3ecb055caryclark@google.com
1543350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.cominline bool approximately_less_than_zero(double x) {
1553350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.com    return x < FLT_EPSILON;
1563350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.com}
1573350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.com
158185c7c47983dde02b5542cf45fe3fc58a3ecb055caryclark@google.cominline bool precisely_less_than_zero(double x) {
15947d73daa7a971e7eee5822def7922f7d43b2dc47caryclark@google.com    return x < DBL_EPSILON_ERR;
160185c7c47983dde02b5542cf45fe3fc58a3ecb055caryclark@google.com}
161185c7c47983dde02b5542cf45fe3fc58a3ecb055caryclark@google.com
162b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.cominline bool approximately_negative(double x) {
163b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com    return x < FLT_EPSILON;
164b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com}
165b45a1b46ee25e9b19800b028bb1ca925212ac7b4caryclark@google.com
166a461ff0866526bc51dbd4c4f9f066a727ec21510caryclark@google.cominline bool precisely_negative(double x) {
16747d73daa7a971e7eee5822def7922f7d43b2dc47caryclark@google.com    return x < DBL_EPSILON_ERR;
168a461ff0866526bc51dbd4c4f9f066a727ec21510caryclark@google.com}
169a461ff0866526bc51dbd4c4f9f066a727ec21510caryclark@google.com
1703350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.cominline bool approximately_one_or_less(double x) {
1713350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.com    return x < 1 + FLT_EPSILON;
1723350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.com}
1733350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.com
1743350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.cominline bool approximately_positive(double x) {
1753350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.com    return x > -FLT_EPSILON;
1763350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.com}
1773350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.com
178e7bd5f4041701cbab87f6e779eb18fbb9fe74216caryclark@google.cominline bool approximately_positive_squared(double x) {
17973ca6243b31e225e9fd5b75a96cbc82d62557de6caryclark@google.com    return x > -(FLT_EPSILON_SQUARED);
180e7bd5f4041701cbab87f6e779eb18fbb9fe74216caryclark@google.com}
181e7bd5f4041701cbab87f6e779eb18fbb9fe74216caryclark@google.com
1823350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.cominline bool approximately_zero_or_more(double x) {
1833350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.com    return x > -FLT_EPSILON;
1843350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.com}
1853350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.com
186235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.cominline bool approximately_between(double a, double b, double c) {
187235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com    return a <= c ? approximately_negative(a - b) && approximately_negative(b - c)
188235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com            : approximately_negative(b - a) && approximately_negative(c - b);
189235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com}
190235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com
191235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com// returns true if (a <= b <= c) || (a >= b >= c)
192235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.cominline bool between(double a, double b, double c) {
193aa35831d1d0e4c798a63fe772430adc4f3a038cdcaryclark@google.com    SkASSERT(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <= 0));
194235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com    return (a - b) * (c - b) <= 0;
195235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com}
1963350c3c68ab75cd08721da3a938b8d2b10096d70caryclark@google.com
1971304bb25aa3b0baa61fc2e2900fabcef88801b59caryclark@google.cominline bool more_roughly_equal(double x, double y) {
1981304bb25aa3b0baa61fc2e2900fabcef88801b59caryclark@google.com    return fabs(x - y) < MORE_ROUGH_EPSILON;
1991304bb25aa3b0baa61fc2e2900fabcef88801b59caryclark@google.com}
2001304bb25aa3b0baa61fc2e2900fabcef88801b59caryclark@google.com
20145a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.cominline bool roughly_equal(double x, double y) {
20245a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com    return fabs(x - y) < ROUGH_EPSILON;
20345a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com}
20445a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com
2057ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.comstruct _Point;
2067ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com
2077ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.comstruct _Vector {
208639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    double x;
209639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    double y;
210639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com
2117ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    friend _Point operator+(const _Point& a, const _Vector& b);
21273ca6243b31e225e9fd5b75a96cbc82d62557de6caryclark@google.com
2137ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    void operator+=(const _Vector& v) {
21405c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com        x += v.x;
21505c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com        y += v.y;
21605c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com    }
21705c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com
2187ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    void operator-=(const _Vector& v) {
219639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com        x -= v.x;
220639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com        y -= v.y;
221639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    }
222639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com
22305c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com    void operator/=(const double s) {
22405c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com        x /= s;
22505c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com        y /= s;
22605c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com    }
22705c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com
22805c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com    void operator*=(const double s) {
22905c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com        x *= s;
23005c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com        y *= s;
23105c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com    }
23205c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com
2337ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    double cross(const _Vector& a) const {
2347ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com        return x * a.y - y * a.x;
2357ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    }
2367ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com
2377ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    double dot(const _Vector& a) const {
2387ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com        return x * a.x + y * a.y;
2397ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    }
2407ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com
2417ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    double length() const {
2427ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com        return sqrt(lengthSquared());
2437ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    }
2447ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com
2457ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    double lengthSquared() const {
2467ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com        return x * x + y * y;
2477ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    }
2487ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com
2497ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    SkVector asSkVector() const {
2507ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com        SkVector v = {SkDoubleToScalar(x), SkDoubleToScalar(y)};
2517ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com        return v;
2527ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    }
2537ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com};
2547ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com
2557ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.comstruct _Point {
2567ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    double x;
2577ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    double y;
2587ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com
2597ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    friend _Vector operator-(const _Point& a, const _Point& b);
2607ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com
2617ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    void operator+=(const _Vector& v) {
2627ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com        x += v.x;
2637ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com        y += v.y;
2647ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    }
2657ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com
2667ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    void operator-=(const _Vector& v) {
2677ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com        x -= v.x;
2687ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com        y -= v.y;
2697ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com    }
2707ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com
271639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    friend bool operator==(const _Point& a, const _Point& b) {
272639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com        return a.x == b.x && a.y == b.y;
273639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    }
274639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com
275639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    friend bool operator!=(const _Point& a, const _Point& b) {
2769f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com        return a.x != b.x || a.y != b.y;
277639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    }
278d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
2790b7da433fe0eaa2833d1b2900715b013b36d93dacaryclark@google.com    // note: this can not be implemented with
2800b7da433fe0eaa2833d1b2900715b013b36d93dacaryclark@google.com    // return approximately_equal(a.y, y) && approximately_equal(a.x, x);
2810b7da433fe0eaa2833d1b2900715b013b36d93dacaryclark@google.com    // because that will not take the magnitude of the values
282639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    bool approximatelyEqual(const _Point& a) const {
283beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com        double denom = SkTMax(fabs(x), SkTMax(fabs(y), SkTMax(fabs(a.x), fabs(a.y))));
284beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com        if (denom == 0) {
285beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com            return true;
286beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com        }
287beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com        double inv = 1 / denom;
288beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com        return approximately_equal(x * inv, a.x * inv) && approximately_equal(y * inv, a.y * inv);
28945a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com    }
290044679ef8c08e1f01afadf5bc08251fe8597df81skia.committer@gmail.com
291c83c70e911a38aea03db4af8dd9841d0d77bd129caryclark@google.com    bool approximatelyEqual(const SkPoint& a) const {
292c83c70e911a38aea03db4af8dd9841d0d77bd129caryclark@google.com        double denom = SkTMax(fabs(x), SkTMax(fabs(y), SkTMax(fabs(a.fX), fabs(a.fY))));
293c83c70e911a38aea03db4af8dd9841d0d77bd129caryclark@google.com        if (denom == 0) {
294c83c70e911a38aea03db4af8dd9841d0d77bd129caryclark@google.com            return true;
295c83c70e911a38aea03db4af8dd9841d0d77bd129caryclark@google.com        }
296c83c70e911a38aea03db4af8dd9841d0d77bd129caryclark@google.com        double inv = 1 / denom;
297c83c70e911a38aea03db4af8dd9841d0d77bd129caryclark@google.com        return approximately_equal(x * inv, a.fX * inv) && approximately_equal(y * inv, a.fY * inv);
298c83c70e911a38aea03db4af8dd9841d0d77bd129caryclark@google.com    }
299c83c70e911a38aea03db4af8dd9841d0d77bd129caryclark@google.com
30045a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com    bool approximatelyEqualHalf(const _Point& a) const {
30145a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com        double denom = SkTMax(fabs(x), SkTMax(fabs(y), SkTMax(fabs(a.x), fabs(a.y))));
30245a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com        if (denom == 0) {
30345a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com            return true;
30445a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com        }
30545a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com        double inv = 1 / denom;
30645a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com        return approximately_equal_half(x * inv, a.x * inv)
30745a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com                && approximately_equal_half(y * inv, a.y * inv);
308639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    }
3090c38ed3b1d704a0ed6147299046f51fd52e841a2skia.committer@gmail.com
310f9502d7dfad5b361a3cdaa42eb75b593c95f79d8caryclark@google.com    bool approximatelyZero() const {
311f9502d7dfad5b361a3cdaa42eb75b593c95f79d8caryclark@google.com        return approximately_zero(x) && approximately_zero(y);
312f9502d7dfad5b361a3cdaa42eb75b593c95f79d8caryclark@google.com    }
313044679ef8c08e1f01afadf5bc08251fe8597df81skia.committer@gmail.com
31445a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com    SkPoint asSkPoint() const {
31545a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com        SkPoint pt = {SkDoubleToScalar(x), SkDoubleToScalar(y)};
31645a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com        return pt;
31745a8fc6a8b00451f807783f2a6ec640e9bcc7256caryclark@google.com    }
31815dd300ac6d7695b4d2aca81d8f3648eae704451skia.committer@gmail.com
319f9502d7dfad5b361a3cdaa42eb75b593c95f79d8caryclark@google.com    double distance(const _Point& a) const {
3207ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com        _Vector temp = *this - a;
321f9502d7dfad5b361a3cdaa42eb75b593c95f79d8caryclark@google.com        return temp.length();
322f9502d7dfad5b361a3cdaa42eb75b593c95f79d8caryclark@google.com    }
323f9502d7dfad5b361a3cdaa42eb75b593c95f79d8caryclark@google.com
324beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com    double distanceSquared(const _Point& a) const {
3257ff5c841bf669826b4cbd708ae1a6b3527f15dcacaryclark@google.com        _Vector temp = *this - a;
326beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com        return temp.lengthSquared();
327beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com    }
328beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com
3291304bb25aa3b0baa61fc2e2900fabcef88801b59caryclark@google.com    double moreRoughlyEqual(const _Point& a) const {
3301304bb25aa3b0baa61fc2e2900fabcef88801b59caryclark@google.com        return more_roughly_equal(a.y, y) && more_roughly_equal(a.x, x);
3311304bb25aa3b0baa61fc2e2900fabcef88801b59caryclark@google.com    }
3321304bb25aa3b0baa61fc2e2900fabcef88801b59caryclark@google.com
3335e0500fb5f17fe14db42fc3e0aad08e6b41ccc5fcaryclark@google.com    double roughlyEqual(const _Point& a) const {
3345e0500fb5f17fe14db42fc3e0aad08e6b41ccc5fcaryclark@google.com        return roughly_equal(a.y, y) && roughly_equal(a.x, x);
3355e0500fb5f17fe14db42fc3e0aad08e6b41ccc5fcaryclark@google.com    }
336639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com};
337639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com
338639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comtypedef _Point _Line[2];
339639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comtypedef _Point Quadratic[3];
340beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.comtypedef _Point Triangle[3];
341639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comtypedef _Point Cubic[4];
342639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com
343639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstruct _Rect {
344639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    double left;
345639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    double top;
346639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    double right;
347639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    double bottom;
348d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
349639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    void add(const _Point& pt) {
350639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com        if (left > pt.x) {
351639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com            left = pt.x;
352639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com        }
353639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com        if (top > pt.y) {
354639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com            top = pt.y;
355639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com        }
356639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com        if (right < pt.x) {
357639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com            right = pt.x;
358639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com        }
359639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com        if (bottom < pt.y) {
360639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com            bottom = pt.y;
361639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com        }
362639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    }
363055c7c299cb47eebd360b809ad58a0006e2e55f7skia.committer@gmail.com
364235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com    // FIXME: used by debugging only ?
36505c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com    bool contains(const _Point& pt) const {
366235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com        return approximately_between(left, pt.x, right)
367235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com                && approximately_between(top, pt.y, bottom);
368235f56a92f6eb6accbb243e11b3c45e3798f38f2caryclark@google.com    }
369d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
37005c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com    bool intersects(_Rect& r) const {
371aa35831d1d0e4c798a63fe772430adc4f3a038cdcaryclark@google.com        SkASSERT(left <= right);
372aa35831d1d0e4c798a63fe772430adc4f3a038cdcaryclark@google.com        SkASSERT(top <= bottom);
373aa35831d1d0e4c798a63fe772430adc4f3a038cdcaryclark@google.com        SkASSERT(r.left <= r.right);
374aa35831d1d0e4c798a63fe772430adc4f3a038cdcaryclark@google.com        SkASSERT(r.top <= r.bottom);
37585ec74ca543b13739db1ad55dedd7bdfae4ab1a6caryclark@google.com        return r.left <= right && left <= r.right && r.top <= bottom && top <= r.bottom;
37605c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com    }
37705c4bad470722bc4e5e6ae3d79aa8bcf9e732f06caryclark@google.com
378c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com    void set(const _Point& pt) {
379c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com        left = right = pt.x;
380c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com        top = bottom = pt.y;
381c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com    }
382d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
383639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    void setBounds(const _Line& line) {
384c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com        set(line[0]);
385639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com        add(line[1]);
386639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    }
387d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
388c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com    void setBounds(const Cubic& );
389c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com    void setBounds(const Quadratic& );
390c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com    void setRawBounds(const Cubic& );
391c682590538a27d73489bc91c098e000fdfb07ccfcaryclark@google.com    void setRawBounds(const Quadratic& );
392639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com};
393639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com
394639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstruct CubicPair {
395639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    const Cubic& first() const { return (const Cubic&) pts[0]; }
396639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    const Cubic& second() const { return (const Cubic&) pts[3]; }
397639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    _Point pts[7];
398639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com};
399639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com
400639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.comstruct QuadraticPair {
401639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    const Quadratic& first() const { return (const Quadratic&) pts[0]; }
402639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    const Quadratic& second() const { return (const Quadratic&) pts[2]; }
403639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com    _Point pts[5];
404639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com};
405639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com
406beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com// FIXME: move these into SkFloatingPoint.h
407beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com#include "SkFloatingPoint.h"
4089f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com
409beda389e646d6be3cfef853584a78ca8ba39d0fccaryclark@google.com#define sk_double_isnan(a) sk_float_isnan(a)
4109f60291c5375457f8adf228dbe6e8ff1186b13e1caryclark@google.com
411c83c70e911a38aea03db4af8dd9841d0d77bd129caryclark@google.com// FIXME: move these to debugging file
412753b870c62bd22cee3d9a15efc634822724084acmtklein#ifdef SK_DEBUG
4135e0500fb5f17fe14db42fc3e0aad08e6b41ccc5fcaryclark@google.comvoid mathematica_ize(char* str, size_t bufferSize);
414c83c70e911a38aea03db4af8dd9841d0d77bd129caryclark@google.combool valid_wind(int winding);
415c83c70e911a38aea03db4af8dd9841d0d77bd129caryclark@google.comvoid winding_printf(int winding);
4165e0500fb5f17fe14db42fc3e0aad08e6b41ccc5fcaryclark@google.com#endif
4175e0500fb5f17fe14db42fc3e0aad08e6b41ccc5fcaryclark@google.com
418639df891487e40925a4f8d9a34fd3dc0c18b40a7caryclark@google.com#endif // __DataTypes_h__
419