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#include "DataTypes.h"
8
9#include <sys/types.h>
10#include <stdlib.h>
11
12#if USE_EPSILON
13const double PointEpsilon = 0.000001;
14const double SquaredEpsilon = PointEpsilon * PointEpsilon;
15#endif
16
17const int UlpsEpsilon = 16;
18
19_Vector operator-(const _Point& a, const _Point& b) {
20    _Vector v = {a.x - b.x, a.y - b.y};
21    return v;
22}
23
24_Point operator+(const _Point& a, const _Vector& b) {
25    _Point v = {a.x + b.x, a.y + b.y};
26    return v;
27}
28
29// from http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
30union Float_t
31{
32    Float_t(float num = 0.0f) : f(num) {}
33    // Portable extraction of components.
34    bool negative() const { return (i >> 31) != 0; }
35#if 0 // unused
36    int32_t RawMantissa() const { return i & ((1 << 23) - 1); }
37    int32_t RawExponent() const { return (i >> 23) & 0xFF; }
38#endif
39    int32_t i;
40    float f;
41#ifdef SK_DEBUG
42    struct
43    {   // Bitfields for exploration. Do not use in production code.
44        uint32_t mantissa : 23;
45        uint32_t exponent : 8;
46        uint32_t sign : 1;
47    } parts;
48#endif
49};
50
51bool AlmostEqualUlps(float A, float B)
52{
53    Float_t uA(A);
54    Float_t uB(B);
55
56    // Different signs means they do not match.
57    if (uA.negative() != uB.negative())
58    {
59        // Check for equality to make sure +0==-0
60        return A == B;
61    }
62
63    // Find the difference in ULPs.
64    int ulpsDiff = abs(uA.i - uB.i);
65    return ulpsDiff <= UlpsEpsilon;
66}
67
68// FIXME: obsolete, delete
69#if 1
70int UlpsDiff(float A, float B)
71{
72    Float_t uA(A);
73    Float_t uB(B);
74
75    return abs(uA.i - uB.i);
76}
77#endif
78
79#ifdef SK_DEBUG
80void mathematica_ize(char* str, size_t bufferLen) {
81    size_t len = strlen(str);
82    bool num = false;
83    for (size_t idx = 0; idx < len; ++idx) {
84        if (num && str[idx] == 'e') {
85            if (len + 2 >= bufferLen) {
86                return;
87            }
88            memmove(&str[idx + 2], &str[idx + 1], len - idx);
89            str[idx] = '*';
90            str[idx + 1] = '^';
91            ++len;
92        }
93        num = str[idx] >= '0' && str[idx] <= '9';
94    }
95}
96
97bool valid_wind(int wind) {
98    return wind > SK_MinS32 + 0xFFFF && wind < SK_MaxS32 - 0xFFFF;
99}
100
101void winding_printf(int wind) {
102    if (wind == SK_MinS32) {
103        SkDebugf("?");
104    } else {
105        SkDebugf("%d", wind);
106    }
107}
108#endif
109