aptos-move/framework/aptos-stdlib/doc/math128.md
<a id="0x1_math128"></a>
0x1::math128Standard math utilities missing in the Move Language.
maxminaveragegcdlcmmul_divclamppowfloor_log2log2log2_64sqrtceil_div<a id="@Constants_0"></a>
<a id="0x1_math128_EINVALID_ARG_FLOOR_LOG2"></a>
Cannot log2 the value 0
<pre><code><b>const</b> <a href="math128.md#0x1_math128_EINVALID_ARG_FLOOR_LOG2">EINVALID_ARG_FLOOR_LOG2</a>: u64 = 1; </code></pre><a id="0x1_math128_max"></a>
maxReturn the largest of two numbers.
<pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_max">max</a>(a: u128, b: u128): u128 </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_max">max</a>(a: u128, b: u128): u128 { <b>if</b> (a >= b) a <b>else</b> b } </code></pre> </details><a id="0x1_math128_min"></a>
minReturn the smallest of two numbers.
<pre><code><b>public</b> <b>fun</b> <b>min</b>(a: u128, b: u128): u128 </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <b>min</b>(a: u128, b: u128): u128 { <b>if</b> (a < b) a <b>else</b> b } </code></pre> </details><a id="0x1_math128_average"></a>
averageReturn the average of two.
<pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_average">average</a>(a: u128, b: u128): u128 </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_average">average</a>(a: u128, b: u128): u128 { <b>if</b> (a < b) { a + (b - a) / 2 } <b>else</b> { b + (a - b) / 2 } } </code></pre> </details><a id="0x1_math128_gcd"></a>
gcdReturn greatest common divisor of <code>a</code> & <code>b</code>, via the Euclidean algorithm.
<pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_gcd">gcd</a>(a: u128, b: u128): u128 </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> inline <b>fun</b> <a href="math128.md#0x1_math128_gcd">gcd</a>(a: u128, b: u128): u128 { <b>let</b> (large, small) = <b>if</b> (a > b) (a, b) <b>else</b> (b, a); <b>while</b> (small != 0) { <b>let</b> tmp = small; small = large % small; large = tmp; }; large } </code></pre> </details><a id="0x1_math128_lcm"></a>
lcmReturn least common multiple of <code>a</code> & <code>b</code>
<pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_lcm">lcm</a>(a: u128, b: u128): u128 </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> inline <b>fun</b> <a href="math128.md#0x1_math128_lcm">lcm</a>(a: u128, b: u128): u128 { <b>if</b> (a == 0 || b == 0) { 0 } <b>else</b> { a / <a href="math128.md#0x1_math128_gcd">gcd</a>(a, b) * b } } </code></pre> </details><a id="0x1_math128_mul_div"></a>
mul_divReturns a * b / c going through u256 to prevent intermediate overflow
<pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_mul_div">mul_div</a>(a: u128, b: u128, c: u128): u128 </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> inline <b>fun</b> <a href="math128.md#0x1_math128_mul_div">mul_div</a>(a: u128, b: u128, c: u128): u128 { // Inline functions cannot take constants, <b>as</b> then every <b>module</b> using it needs the constant <b>assert</b>!(c != 0, std::error::invalid_argument(4)); (((a <b>as</b> u256) * (b <b>as</b> u256) / (c <b>as</b> u256)) <b>as</b> u128) } </code></pre> </details><a id="0x1_math128_clamp"></a>
clampReturn x clamped to the interval [lower, upper].
<pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_clamp">clamp</a>(x: u128, lower: u128, upper: u128): u128 </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_clamp">clamp</a>(x: u128, lower: u128, upper: u128): u128 { <b>min</b>(upper, <a href="math128.md#0x1_math128_max">max</a>(lower, x)) } </code></pre> </details><a id="0x1_math128_pow"></a>
powReturn the value of n raised to power e
<pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_pow">pow</a>(n: u128, e: u128): u128 </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_pow">pow</a>(n: u128, e: u128): u128 { <b>if</b> (e == 0) { 1 } <b>else</b> { <b>let</b> p = 1; <b>while</b> (e > 1) { <b>if</b> (e % 2 == 1) { p *= n; }; e /= 2; n *= n; }; p * n } } </code></pre> </details><a id="0x1_math128_floor_log2"></a>
floor_log2Returns floor(log2(x))
<pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_floor_log2">floor_log2</a>(x: u128): u8 </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_floor_log2">floor_log2</a>(x: u128): u8 { <b>let</b> res = 0; <b>assert</b>!(x != 0, std::error::invalid_argument(<a href="math128.md#0x1_math128_EINVALID_ARG_FLOOR_LOG2">EINVALID_ARG_FLOOR_LOG2</a>)); // Effectively the position of the most significant set bit <b>let</b> n = 64; <b>while</b> (n > 0) { <b>if</b> (x >= (1 << n)) { x >>= n; res += n; }; n >>= 1; }; res } </code></pre> </details><a id="0x1_math128_log2"></a>
log2<a id="0x1_math128_log2_64"></a>
log2_64<a id="0x1_math128_sqrt"></a>
sqrtReturns square root of x, precisely floor(sqrt(x))
<pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_sqrt">sqrt</a>(x: u128): u128 </code></pre> <details> <summary>Implementation</summary> <pre><code><b>public</b> <b>fun</b> <a href="math128.md#0x1_math128_sqrt">sqrt</a>(x: u128): u128 { <b>if</b> (x == 0) <b>return</b> 0; // Note the plus 1 in the expression. Let n = floor_lg2(x) we have x in [2^n, 2^{n+1}) and thus the answer in // the half-open interval [2^(n/2), 2^{(n+1)/2}). For even n we can write this <b>as</b> [2^(n/2), <a href="math128.md#0x1_math128_sqrt">sqrt</a>(2) 2^{n/2}) // for odd n [2^((n+1)/2)/<a href="math128.md#0x1_math128_sqrt">sqrt</a>(2), 2^((n+1)/2). For even n the left end point is integer for odd the right // end point is integer. If we <b>choose</b> <b>as</b> our first approximation the integer end point we have <b>as</b> maximum // relative <a href="../../move-stdlib/doc/error.md#0x1_error">error</a> either (<a href="math128.md#0x1_math128_sqrt">sqrt</a>(2) - 1) or (1 - 1/<a href="math128.md#0x1_math128_sqrt">sqrt</a>(2)) both are smaller then 1/2. <b>let</b> res = 1 << ((<a href="math128.md#0x1_math128_floor_log2">floor_log2</a>(x) + 1) >> 1); // We <b>use</b> standard newton-rhapson iteration <b>to</b> improve the initial approximation. // The <a href="../../move-stdlib/doc/error.md#0x1_error">error</a> term evolves <b>as</b> delta_i+1 = delta_i^2 / 2 (quadratic convergence). // It turns out that after 5 iterations the delta is smaller than 2^-64 and thus below the treshold. res = (res + x / res) >> 1; res = (res + x / res) >> 1; res = (res + x / res) >> 1; res = (res + x / res) >> 1; res = (res + x / res) >> 1; <b>min</b>(res, x / res) } </code></pre> </details><a id="0x1_math128_ceil_div"></a>
ceil_div<a id="@Specification_1"></a>
<a id="@Specification_1_max"></a>
max<a id="@Specification_1_min"></a>
min<a id="@Specification_1_average"></a>
average<a id="@Specification_1_clamp"></a>
clamp<a id="@Specification_1_pow"></a>
pow<a id="@Specification_1_floor_log2"></a>
floor_log2<a id="@Specification_1_sqrt"></a>
sqrt<a id="0x1_math128_spec_pow"></a>
<pre><code><b>fun</b> <a href="math128.md#0x1_math128_spec_pow">spec_pow</a>(n: u128, e: u128): u128 { <b>if</b> (e == 0) { 1 } <b>else</b> { n * <a href="math128.md#0x1_math128_spec_pow">spec_pow</a>(n, e-1) } } </code></pre>