mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add @intlog2 for Floored CT log-base2 (#2355)
* Add `@intlog2` for Floored CT log-base2 --------- Co-authored-by: Christoffer Lerno <christoffer@aegik.com>
This commit is contained in:
@@ -344,6 +344,23 @@ macro log(x, base)
|
|||||||
*>
|
*>
|
||||||
macro log2(x) => $$log2(values::promote_int(x));
|
macro log2(x) => $$log2(values::promote_int(x));
|
||||||
|
|
||||||
|
<*
|
||||||
|
@require values::@is_int($x) : `The input value must be an integer.`
|
||||||
|
@require $x >= 0 : `The input value must be a positive integer.`
|
||||||
|
@return `A floored base-2 log of an input integer value.`
|
||||||
|
*>
|
||||||
|
macro @intlog2($x)
|
||||||
|
{
|
||||||
|
$if $x <= 1:
|
||||||
|
return 0;
|
||||||
|
$endif
|
||||||
|
|
||||||
|
$typeof($x) $z = 0;
|
||||||
|
$for var $y = $x; $y > 0; $y >>= 1, ++$z: $endfor
|
||||||
|
|
||||||
|
return $z - 1;
|
||||||
|
}
|
||||||
|
|
||||||
<*
|
<*
|
||||||
@require values::@is_promotable_to_floatlike(x) : `The input must be a number or a float vector`
|
@require values::@is_promotable_to_floatlike(x) : `The input must be a number or a float vector`
|
||||||
*>
|
*>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
### Changes / improvements
|
### Changes / improvements
|
||||||
- Support `alias foo = module std::io` module aliasing.
|
- Support `alias foo = module std::io` module aliasing.
|
||||||
|
- Add compile-time `@intlog2` macro to math.
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
- List.remove_at would incorrectly trigger ASAN.
|
- List.remove_at would incorrectly trigger ASAN.
|
||||||
|
|||||||
@@ -457,6 +457,24 @@ fn void test_log() @test
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn void test_ct_intlog2() @test @if($feature(SLOW_TESTS))
|
||||||
|
{
|
||||||
|
uint128 actual, expected;
|
||||||
|
$for var $x = 0; $x <= 128; ++$x :
|
||||||
|
expected = (uint128)math::floor(math::log2($x));
|
||||||
|
actual = (uint128)math::@intlog2($x);
|
||||||
|
assert(expected == actual, "input %d: floor(log2($x)) -> %d is not equal to @intlog2($x) -> %d", $x, expected, actual);
|
||||||
|
$endfor
|
||||||
|
|
||||||
|
var $logme = (uint128)1;
|
||||||
|
$for var $x = 0; $x < 8192; ++$x :
|
||||||
|
$logme *= 13;
|
||||||
|
expected = (uint128)math::floor(math::log2((uint128)$logme));
|
||||||
|
actual = (uint128)math::@intlog2((uint128)$logme);
|
||||||
|
assert(expected == actual, "input %d (idx %d): floor(log2(|$logme|)) -> %d is not equal to @intlog2(|$logme|) -> %d", $logme, $x, expected, actual);
|
||||||
|
$endfor
|
||||||
|
}
|
||||||
|
|
||||||
fn void test_pow() @test
|
fn void test_pow() @test
|
||||||
{
|
{
|
||||||
int[<10>] e = { 2, 1, 0, -1, -2, 2, 1, 0, -1, -2 };
|
int[<10>] e = { 2, 1, 0, -1, -2, 2, 1, 0, -1, -2 };
|
||||||
|
|||||||
Reference in New Issue
Block a user