1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#ifndef SkCubicSolver_DEFINED 9cb93a386Sopenharmony_ci#define SkCubicSolver_DEFINED 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 12cb93a386Sopenharmony_ci#include "include/private/SkFloatingPoint.h" 13cb93a386Sopenharmony_ci 14cb93a386Sopenharmony_ci//#define CUBICMAP_TRACK_MAX_ERROR 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_cinamespace SK_OPTS_NS { 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ci static float eval_poly(float t, float b) { 19cb93a386Sopenharmony_ci return b; 20cb93a386Sopenharmony_ci } 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_ci template <typename... Rest> 23cb93a386Sopenharmony_ci static float eval_poly(float t, float m, float b, Rest... rest) { 24cb93a386Sopenharmony_ci return eval_poly(t, sk_fmaf(m,t,b), rest...); 25cb93a386Sopenharmony_ci } 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ci inline float cubic_solver(float A, float B, float C, float D) { 28cb93a386Sopenharmony_ci #ifdef CUBICMAP_TRACK_MAX_ERROR 29cb93a386Sopenharmony_ci static int max_iters = 0; 30cb93a386Sopenharmony_ci #endif 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_ci #ifdef SK_DEBUG 33cb93a386Sopenharmony_ci auto valid = [](float t) { 34cb93a386Sopenharmony_ci return t >= 0 && t <= 1; 35cb93a386Sopenharmony_ci }; 36cb93a386Sopenharmony_ci #endif 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ci auto guess_nice_cubic_root = [](float a, float b, float c, float d) { 39cb93a386Sopenharmony_ci return -d; 40cb93a386Sopenharmony_ci }; 41cb93a386Sopenharmony_ci float t = guess_nice_cubic_root(A, B, C, D); 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ci int iters = 0; 44cb93a386Sopenharmony_ci const int MAX_ITERS = 8; 45cb93a386Sopenharmony_ci for (; iters < MAX_ITERS; ++iters) { 46cb93a386Sopenharmony_ci SkASSERT(valid(t)); 47cb93a386Sopenharmony_ci float f = eval_poly(t, A,B,C,D); // f = At^3 + Bt^2 + Ct + D 48cb93a386Sopenharmony_ci if (sk_float_abs(f) <= 0.00005f) { 49cb93a386Sopenharmony_ci break; 50cb93a386Sopenharmony_ci } 51cb93a386Sopenharmony_ci float fp = eval_poly(t, 3*A, 2*B, C); // f' = 3At^2 + 2Bt + C 52cb93a386Sopenharmony_ci float fpp = eval_poly(t, 3*A+3*A, 2*B); // f'' = 6At + 2B 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci float numer = 2 * fp * f; 55cb93a386Sopenharmony_ci float denom = sk_fmaf(2*fp, fp, -(f*fpp)); 56cb93a386Sopenharmony_ci 57cb93a386Sopenharmony_ci t -= numer / denom; 58cb93a386Sopenharmony_ci } 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci #ifdef CUBICMAP_TRACK_MAX_ERROR 61cb93a386Sopenharmony_ci if (max_iters < iters) { 62cb93a386Sopenharmony_ci max_iters = iters; 63cb93a386Sopenharmony_ci SkDebugf("max_iters %d\n", max_iters); 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ci #endif 66cb93a386Sopenharmony_ci SkASSERT(valid(t)); 67cb93a386Sopenharmony_ci return t; 68cb93a386Sopenharmony_ci } 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_ci} // namespace SK_OPTS_NS 71cb93a386Sopenharmony_ci#endif 72