LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkFDot6.h (source / functions) Hit Total Coverage
Test: output.info Lines: 28 32 87.5 %
Date: 2017-07-14 16:53:18 Functions: 5 6 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2006 The Android Open Source Project
       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             : 
       8             : 
       9             : #ifndef SkFDot6_DEFINED
      10             : #define SkFDot6_DEFINED
      11             : 
      12             : #include "SkFixed.h"
      13             : #include "SkScalar.h"
      14             : #include "SkMath.h"
      15             : 
      16             : typedef int32_t SkFDot6;
      17             : 
      18             : /* This uses the magic number approach suggested here:
      19             :  * http://stereopsis.com/sree/fpu2006.html and used in
      20             :  * _cairo_fixed_from_double. It does banker's rounding
      21             :  * (i.e. round to nearest even)
      22             :  */
      23        4932 : inline SkFDot6 SkScalarRoundToFDot6(SkScalar x, int shift = 0)
      24             : {
      25             :     union {
      26             :         double  fDouble;
      27             :         int32_t fBits[2];
      28             :     } tmp;
      29        4932 :     int fractionalBits = 6 + shift;
      30        4932 :     double magic = (1LL << (52 - (fractionalBits))) * 1.5;
      31             : 
      32        4932 :     tmp.fDouble = SkScalarToDouble(x) + magic;
      33             : #ifdef SK_CPU_BENDIAN
      34             :     return tmp.fBits[1];
      35             : #else
      36        4932 :     return tmp.fBits[0];
      37             : #endif
      38             : }
      39             : 
      40             : #define SK_FDot6One         (64)
      41             : #define SK_FDot6Half        (32)
      42             : 
      43             : #ifdef SK_DEBUG
      44           0 :     inline SkFDot6 SkIntToFDot6(S16CPU x) {
      45           0 :         SkASSERT(SkToS16(x) == x);
      46           0 :         return x << 6;
      47             :     }
      48             : #else
      49             :     #define SkIntToFDot6(x) ((x) << 6)
      50             : #endif
      51             : 
      52             : #define SkFDot6Floor(x)     ((x) >> 6)
      53             : #define SkFDot6Ceil(x)      (((x) + 63) >> 6)
      54             : #define SkFDot6Round(x)     (((x) + 32) >> 6)
      55             : 
      56             : #define SkFixedToFDot6(x)   ((x) >> 10)
      57             : 
      58        6738 : inline SkFixed SkFDot6ToFixed(SkFDot6 x) {
      59        6738 :     SkASSERT((SkLeftShift(x, 10) >> 10) == x);
      60             : 
      61        6738 :     return SkLeftShift(x, 10);
      62             : }
      63             : 
      64             : #define SkScalarToFDot6(x)  (SkFDot6)((x) * 64)
      65             : #define SkFDot6ToScalar(x)  ((SkScalar)(x) * 0.015625f)
      66             : #define SkFDot6ToFloat      SkFDot6ToScalar
      67             : 
      68        3061 : inline SkFixed SkFDot6Div(SkFDot6 a, SkFDot6 b) {
      69        3061 :     SkASSERT(b != 0);
      70             : 
      71        3061 :     if (a == (int16_t)a) {
      72        3061 :         return SkLeftShift(a, 16) / b;
      73             :     } else {
      74           0 :         return SkFixedDiv(a, b);
      75             :     }
      76             : }
      77             : 
      78             : #include "SkFDot6Constants.h"
      79             : 
      80             : class QuickFDot6Inverse {
      81             : public:
      82        1311 :     inline static SkFixed Lookup(SkFDot6 x) {
      83        1311 :         SkASSERT(SkAbs32(x) < kInverseTableSize);
      84        1311 :         return gFDot6INVERSE[kInverseTableSize + x];
      85             :     }
      86             : };
      87             : 
      88         441 : static inline SkFixed QuickSkFDot6Div(SkFDot6 a, SkFDot6 b) {
      89         441 :     const int kMinBits = 3;  // abs(b) should be at least (1 << kMinBits) for quick division
      90         441 :     const int kMaxBits = 31; // Number of bits available in signed int
      91             :     // Given abs(b) <= (1 << kMinBits), the inverse of abs(b) is at most 1 << (22 - kMinBits) in
      92             :     // SkFixed format. Hence abs(a) should be less than kMaxAbsA
      93         441 :     const int kMaxAbsA = 1 << (kMaxBits - (22 - kMinBits));
      94         441 :     SkFDot6 abs_a = SkAbs32(a);
      95         441 :     SkFDot6 abs_b = SkAbs32(b);
      96         441 :     if (abs_b >= (1 << kMinBits) && abs_b < kInverseTableSize && abs_a < kMaxAbsA) {
      97          73 :         SkASSERT((int64_t)a * QuickFDot6Inverse::Lookup(b) <= SK_MaxS32
      98             :                 && (int64_t)a * QuickFDot6Inverse::Lookup(b) >= SK_MinS32);
      99          73 :         SkFixed ourAnswer = (a * QuickFDot6Inverse::Lookup(b)) >> 6;
     100             :         #ifdef SK_DEBUG
     101          73 :         SkFixed directAnswer = SkFDot6Div(a, b);
     102          73 :         SkASSERT(
     103             :             (directAnswer == 0 && ourAnswer == 0) ||
     104             :             SkFixedDiv(SkAbs32(directAnswer - ourAnswer), SkAbs32(directAnswer)) <= 1 << 10
     105             :         );
     106             :         #endif
     107          73 :         return ourAnswer;
     108             :     } else {
     109         368 :         return SkFDot6Div(a, b);
     110             :     }
     111             : }
     112             : 
     113             : #endif

Generated by: LCOV version 1.13