SkPathOpsTypes.cpp revision 07393cab57ce74a4aae89a31fae9aaa9780fc19d
107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/*
207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Copyright 2012 Google Inc.
307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *
407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Use of this source code is governed by a BSD-style license that can be
507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * found in the LICENSE file.
607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */
707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkPathOpsTypes.h"
807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comconst int UlpsEpsilon = 16;
1007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// from http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
1207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comunion SkPathOpsUlpsFloat {
1307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int32_t fInt;
1407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    float fFloat;
1507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkPathOpsUlpsFloat(float num = 0.0f) : fFloat(num) {}
1707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool negative() const { return fInt < 0; }
1807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com};
1907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.combool AlmostEqualUlps(float A, float B) {
2107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkPathOpsUlpsFloat uA(A);
2207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkPathOpsUlpsFloat uB(B);
2307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // Different signs means they do not match.
2407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (uA.negative() != uB.negative())
2507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    {
2607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        // Check for equality to make sure +0 == -0
2707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return A == B;
2807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
2907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // Find the difference in ULPs.
3007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    int ulpsDiff = abs(uA.fInt - uB.fInt);
3107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return ulpsDiff <= UlpsEpsilon;
3207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
3307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
3407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// cube root approximation using bit hack for 64-bit float
3507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// adapted from Kahan's cbrt
3607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comstatic  double cbrt_5d(double d) {
3707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    const unsigned int B1 = 715094163;
3807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    double t = 0.0;
3907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    unsigned int* pt = (unsigned int*) &t;
4007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    unsigned int* px = (unsigned int*) &d;
4107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    pt[1] = px[1] / 3 + B1;
4207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return t;
4307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
4407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
4507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// iterative cube root approximation using Halley's method (double)
4607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comstatic  double cbrta_halleyd(const double a, const double R) {
4707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    const double a3 = a * a * a;
4807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    const double b = a * (a3 + R + R) / (a3 + a3 + R);
4907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return b;
5007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
5107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
5207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// cube root approximation using 3 iterations of Halley's method (double)
5307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comstatic double halley_cbrt3d(double d) {
5407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    double a = cbrt_5d(d);
5507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    a = cbrta_halleyd(a, d);
5607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    a = cbrta_halleyd(a, d);
5707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return cbrta_halleyd(a, d);
5807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
5907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
6007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comdouble SkDCubeRoot(double x) {
6107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (approximately_zero_cubed(x)) {
6207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return 0;
6307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
6407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    double result = halley_cbrt3d(fabs(x));
6507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (x < 0) {
6607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        result = -result;
6707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
6807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return result;
6907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
70