mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
sys/div: Add div_u64_by_15625div512
64-bit version of div_u32_by_15625div512 also updated tests-div to use correct order for expected and actual values in unit tests (embUnit)
This commit is contained in:
parent
3d3efc3492
commit
94da9c2975
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
|
||||
* Copyright (C) 2016 Eistec AB
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -14,7 +15,8 @@
|
||||
*
|
||||
* @file
|
||||
* @ingroup sys_util
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
||||
* @{
|
||||
*/
|
||||
|
||||
@ -39,7 +41,7 @@ extern "C" {
|
||||
static inline uint64_t div_u64_by_15625(uint64_t val)
|
||||
{
|
||||
/* a higher value would overflow 2^64 in the multiplication that follows */
|
||||
assert(val <= 16383999997LLU);
|
||||
assert(val <= 16383999997ull);
|
||||
|
||||
return (val * 0x431bde83UL) >> (12 + 32);
|
||||
}
|
||||
@ -55,7 +57,7 @@ static inline uint64_t div_u64_by_15625(uint64_t val)
|
||||
static inline uint64_t div_u64_by_1000000(uint64_t val)
|
||||
{
|
||||
/* a higher value would overflow 2^64 in the multiplication that follows */
|
||||
assert(val <= 1048575999808LLU);
|
||||
assert(val <= 1048575999808ull);
|
||||
|
||||
return div_u64_by_15625(val>>6);
|
||||
}
|
||||
@ -77,6 +79,31 @@ static inline uint32_t div_u32_by_15625div512(uint32_t val)
|
||||
return ((uint64_t)(val) * 0x431bde83ul) >> (12 + 32 - 9);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Divide val by (15625/512)
|
||||
*
|
||||
* This is used to quantize a 1MHz value to the closest 32768Hz value,
|
||||
* e.g., for timers.
|
||||
*
|
||||
* The algorithm actually multiplies by 512 first, then divides by 15625,
|
||||
* keeping the result closer to a floored floating point division.
|
||||
*
|
||||
* @pre val <= 16383999997
|
||||
*
|
||||
* @param[in] val dividend
|
||||
* @return (val / (15625/512))
|
||||
*/
|
||||
static inline uint64_t div_u64_by_15625div512(uint64_t val)
|
||||
{
|
||||
/* a higher value would overflow 2^64 in the multiplication that follows */
|
||||
assert(val <= 16383999997ull);
|
||||
/*
|
||||
* This saves around 1400 bytes of ROM on Cortex-M platforms (both ARMv6 and
|
||||
* ARMv7) from avoiding linking against __aeabi_uldivmod and related helpers
|
||||
*/
|
||||
return ((uint64_t)(val) * 0x431bde83ul) >> (12 + 32 - 9);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Integer divide val by 44488
|
||||
*
|
||||
|
@ -25,11 +25,13 @@ static uint32_t u32_test_values[] = {
|
||||
(15625LU*5)+1,
|
||||
0xffff,
|
||||
0xffff<<10,
|
||||
0xffffffff
|
||||
0xffffffff,
|
||||
};
|
||||
|
||||
static uint64_t u64_test_values[] = {
|
||||
0xffffffffULL+1
|
||||
16383999997ull,
|
||||
11111111111ull,
|
||||
0xffffffffull+1,
|
||||
};
|
||||
|
||||
#define N_U32_VALS (sizeof(u32_test_values)/sizeof(uint32_t))
|
||||
@ -40,15 +42,15 @@ static void test_div_u64_by_15625(void)
|
||||
for (unsigned i = 0; i < N_U32_VALS; i++) {
|
||||
DEBUG("Dividing %"PRIu32" by 15625...\n", u32_test_values[i]);
|
||||
TEST_ASSERT_EQUAL_INT(
|
||||
div_u64_by_15625(u32_test_values[i]),
|
||||
u32_test_values[i]/15625);
|
||||
u32_test_values[i] / 15625,
|
||||
div_u64_by_15625(u32_test_values[i]));
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < N_U64_VALS; i++) {
|
||||
DEBUG("Dividing %"PRIu64" by 15625...\n", u64_test_values[i]);
|
||||
TEST_ASSERT_EQUAL_INT(
|
||||
div_u64_by_15625(u64_test_values[i]),
|
||||
u64_test_values[i]/15625);
|
||||
(uint64_t)u64_test_values[i] / 15625,
|
||||
div_u64_by_15625(u64_test_values[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,8 +59,8 @@ static void test_div_u32_by_15625div512(void)
|
||||
for (unsigned i = 0; i < N_U32_VALS; i++) {
|
||||
DEBUG("Dividing %"PRIu32" by (15625/512)...\n", u32_test_values[i]);
|
||||
TEST_ASSERT_EQUAL_INT(
|
||||
div_u32_by_15625div512(u32_test_values[i]),
|
||||
(uint64_t)u32_test_values[i]*512LU/15625);
|
||||
(uint64_t)u32_test_values[i] * 512lu / 15625,
|
||||
div_u32_by_15625div512(u32_test_values[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,15 +69,32 @@ static void test_div_u64_by_1000000(void)
|
||||
for (unsigned i = 0; i < N_U32_VALS; i++) {
|
||||
DEBUG("Dividing %"PRIu32" by 1000000...\n", u32_test_values[i]);
|
||||
TEST_ASSERT_EQUAL_INT(
|
||||
div_u64_by_1000000(u32_test_values[i]),
|
||||
u32_test_values[i]/1000000);
|
||||
u32_test_values[i] / 1000000lu,
|
||||
div_u64_by_1000000(u32_test_values[i]));
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < N_U64_VALS; i++) {
|
||||
DEBUG("Dividing %"PRIu64" by 1000000...\n", u64_test_values[i]);
|
||||
TEST_ASSERT_EQUAL_INT(
|
||||
div_u64_by_1000000(u64_test_values[i]),
|
||||
u64_test_values[i]/1000000U);
|
||||
u64_test_values[i] / 1000000lu,
|
||||
div_u64_by_1000000(u64_test_values[i]));
|
||||
}
|
||||
}
|
||||
|
||||
static void test_div_u64_by_15625div512(void)
|
||||
{
|
||||
for (unsigned i = 0; i < N_U32_VALS; i++) {
|
||||
DEBUG("Dividing %"PRIu32" by (15625/512)...\n", u32_test_values[i]);
|
||||
TEST_ASSERT_EQUAL_INT(
|
||||
(uint64_t)u32_test_values[i] * 512lu / 15625,
|
||||
div_u64_by_15625div512(u32_test_values[i]));
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < N_U64_VALS; i++) {
|
||||
DEBUG("Dividing %"PRIu64" by (15625/512)...\n", u64_test_values[i]);
|
||||
TEST_ASSERT_EQUAL_INT(
|
||||
(uint64_t)u64_test_values[i] * 512lu / 15625,
|
||||
div_u64_by_15625div512(u64_test_values[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,6 +103,7 @@ Test *tests_div_tests(void)
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_div_u64_by_15625),
|
||||
new_TestFixture(test_div_u32_by_15625div512),
|
||||
new_TestFixture(test_div_u64_by_15625div512),
|
||||
new_TestFixture(test_div_u64_by_1000000),
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user