Skip to main content

tiny_skia/
math.rs

1// Copyright 2006 The Android Open Source Project
2// Copyright 2020 Yevhenii Reizner
3//
4// Use of this source code is governed by a BSD-style license that can be
5// found in the LICENSE file.
6
7use crate::LengthU32;
8
9#[cfg(all(not(feature = "std"), feature = "no-std-float"))]
10use tiny_skia_path::NoStdFloat;
11
12// Perfectly safe.
13pub const LENGTH_U32_ONE: LengthU32 = unsafe { LengthU32::new_unchecked(1) };
14
15pub fn left_shift(value: i32, shift: i32) -> i32 {
16    ((value as u32) << shift) as i32
17}
18
19pub fn left_shift64(value: i64, shift: i32) -> i64 {
20    ((value as u64) << shift) as i64
21}
22
23pub fn bound<T: Ord + Copy>(min: T, value: T, max: T) -> T {
24    max.min(value).max(min)
25}
26
27// Skia cites http://www.machinedlearnings.com/2011/06/fast-approximate-logarithm-exponential.html
28pub fn approx_powf(x: f32, y: f32) -> f32 {
29    if x == 0.0 || x == 1.0 {
30        return x;
31    }
32
33    let e = x.to_bits() as f32 * (1.0f32 / ((1 << 23) as f32));
34    let m = f32::from_bits((x.to_bits() & 0x007fffff) | 0x3f000000);
35
36    let log2_x = e - 124.225514990f32 - 1.498030302f32 * m - 1.725879990f32 / (0.3520887068f32 + m);
37
38    let x = log2_x * y;
39
40    let f = x - x.floor();
41
42    let mut a = x + 121.274057500f32;
43    a -= f * 1.490129070f32;
44    a += 27.728023300f32 / (4.84252568f32 - f);
45    a *= (1 << 23) as f32;
46
47    if a < f32::INFINITY.to_bits() as f32 {
48        if a > 0.0 {
49            f32::from_bits(a.round() as u32)
50        } else {
51            0.0
52        }
53    } else {
54        f32::INFINITY
55    }
56}