1 /*
2    mkvmerge -- utility for splicing together matroska files
3    from component media subtypes
4 
5    Distributed under the GPL v2
6    see the file COPYING for details
7    or visit https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
8 
9    math helper functions
10 
11    Written by Moritz Bunkus <moritz@bunkus.org>.
12 */
13 
14 #include "common/common_pch.h"
15 
16 #include "common/math.h"
17 
18 namespace mtx::math {
19 
20 uint64_t
round_to_nearest_pow2(uint64_t value)21 round_to_nearest_pow2(uint64_t value) {
22   uint64_t best_value = 0;
23   uint64_t test_value = 1;
24 
25   while (0x8000000000000000ull >= test_value) {
26     if (  (value > test_value ? value - test_value : test_value - value)
27         < (value > best_value ? value - best_value : best_value - value))
28       best_value = test_value;
29     test_value <<= 1;
30   }
31 
32   return best_value;
33 }
34 
35 int
int_log2(uint64_t value)36 int_log2(uint64_t value) {
37   for (int bit = 63; bit >= 0; --bit)
38     if (value & (1ull << bit))
39       return bit;
40 
41   return -1;
42 }
43 
44 double
int_to_double(int64_t value)45 int_to_double(int64_t value) {
46   if (static_cast<uint64_t>(value + value) > (0xffeull << 52))
47     return static_cast<double>(NAN);
48   return std::ldexp(((value & ((1ll << 52) - 1)) + (1ll << 52)) * (value >> 63 | 1), (value >> 52 & 0x7ff) - 1075);
49 }
50 
51 mtx_mp_rational_t
clamp_values_to(mtx_mp_rational_t const & r,int64_t max_value)52 clamp_values_to(mtx_mp_rational_t const &r,
53                 int64_t max_value) {
54   auto num = boost::multiprecision::numerator(r);
55   auto den = boost::multiprecision::denominator(r);
56 
57   if (!num || !den || ((num <= max_value) && (den <= max_value)))
58     return r;
59 
60   // 333 / 1000 , clamp = 500, mul = 1/2 = 1/(max/clamp) = clamp/max
61 
62   auto mult = mtx::rational(max_value, std::max(num, den));
63   den       = mtx::to_int(den * mult);
64 
65   return mtx::rational(num * mult, den ? den : 1);
66 }
67 }
68