math: Optimize the implementation of log2ceil and log2floor

and move common math funtions to math32.h:
div_round_up
div_round_closest
is_power_of_2
roundup_pow_of_two
rounddown_pow_of_two

Signed-off-by: lipengfei28 <lipengfei28@xiaomi.com>
This commit is contained in:
lipengfei28 2024-06-21 15:47:59 +08:00 committed by Alin Jerpelea
parent 4fd78583f7
commit ca39dc2e74
11 changed files with 90 additions and 192 deletions

View File

@ -30,7 +30,9 @@
#include <stdint.h>
#include <strings.h>
#include <sys/param.h>
#include <nuttx/bits.h>
#include <nuttx/lib/math32.h>
#ifdef CONFIG_CLK
@ -40,9 +42,6 @@
#define MASK(width) (BIT(width) - 1)
#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
#define DIV_ROUND_CLOSEST(n, d) ((((n) < 0) ^ ((d) < 0)) ? \
(((n) - (d)/2)/(d)) : (((n) + (d)/2)/(d)))
/****************************************************************************
* Inline Functions
@ -84,21 +83,6 @@ static inline uint32_t gcd(uint32_t a, uint32_t b)
return b;
}
static inline int is_power_of_2(uint32_t n)
{
return (n != 0 && ((n & (n - 1)) == 0));
}
static inline uint32_t roundup_pow_of_two(uint32_t n)
{
return 1 << fls(n - 1);
}
static inline uint32_t rounddown_pow_of_two(uint32_t n)
{
return 1 << (fls(n) - 1);
}
static inline uint32_t roundup_double(double n)
{
uint32_t intn = (uint32_t)n;

View File

@ -107,7 +107,7 @@ static uint32_t divider_recalc_rate(uint32_t parent_rate,
return parent_rate;
}
return DIV_ROUND_UP(parent_rate, div);
return div_round_up(parent_rate, div);
}
static uint32_t clk_divider_recalc_rate(FAR struct clk_s *clk,
@ -125,7 +125,7 @@ static uint32_t clk_divider_recalc_rate(FAR struct clk_s *clk,
static uint32_t _div_round_up(uint32_t parent_rate, uint32_t rate,
uint16_t flags)
{
uint32_t div = DIV_ROUND_UP(parent_rate, rate);
uint32_t div = div_round_up(parent_rate, rate);
if (flags & CLK_DIVIDER_POWER_OF_TWO)
{
@ -143,7 +143,7 @@ static uint32_t _div_round_closest(uint32_t parent_rate,
uint32_t up_rate;
uint32_t down_rate;
up = DIV_ROUND_UP(parent_rate, rate);
up = div_round_up(parent_rate, rate);
down = parent_rate / rate;
if (flags & CLK_DIVIDER_POWER_OF_TWO)
@ -152,8 +152,8 @@ static uint32_t _div_round_closest(uint32_t parent_rate,
down = rounddown_pow_of_two(down);
}
up_rate = DIV_ROUND_UP(parent_rate, up);
down_rate = DIV_ROUND_UP(parent_rate, down);
up_rate = div_round_up(parent_rate, up);
down_rate = div_round_up(parent_rate, down);
return (rate - up_rate) <= (down_rate - rate) ? up : down;
}
@ -255,7 +255,7 @@ static uint32_t clk_divider_bestdiv(FAR struct clk_s *clk, uint32_t rate,
{
parent_rate = clk_round_rate(clk_get_parent(clk),
rate * i);
now = DIV_ROUND_UP(parent_rate, i);
now = div_round_up(parent_rate, i);
if (_is_best_div(rate, now, best, divider->flags))
{
bestdiv = i;
@ -280,7 +280,7 @@ static uint32_t divider_round_rate(FAR struct clk_s *clk, uint32_t rate,
div = clk_divider_bestdiv(clk, rate, prate, width);
return DIV_ROUND_UP(*prate, div);
return div_round_up(*prate, div);
}
static uint32_t clk_divider_round_rate(FAR struct clk_s *clk, uint32_t rate,
@ -302,7 +302,7 @@ static int32_t divider_get_val(uint32_t rate, uint32_t parent_rate,
return -EINVAL;
}
div = DIV_ROUND_UP(parent_rate, rate);
div = div_round_up(parent_rate, rate);
if ((flags & CLK_DIVIDER_POWER_OF_TWO) && !is_power_of_2(div))
{

View File

@ -42,7 +42,7 @@ static int clk_phase_get_phase(FAR struct clk_s *clk)
uint32_t val;
val = (clk_read(phase->reg) >> phase->shift) & MASK(phase->width);
return DIV_ROUND_CLOSEST(360 * val, MASK(phase->width) + 1);
return div_round_closest(360 * val, MASK(phase->width) + 1);
}
static int clk_phase_set_phase(FAR struct clk_s *clk, int degrees)
@ -51,7 +51,7 @@ static int clk_phase_set_phase(FAR struct clk_s *clk, int degrees)
uint32_t pha;
uint32_t val;
pha = DIV_ROUND_CLOSEST((MASK(phase->width) + 1) * degrees, 360);
pha = div_round_closest((MASK(phase->width) + 1) * degrees, 360);
if (pha > MASK(phase->width))
{

View File

@ -26,6 +26,7 @@
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/list.h>
#include <nuttx/lib/math32.h>
#include <nuttx/bits.h>
#include <nuttx/coresight/coresight_stm.h>
@ -92,10 +93,6 @@
#define STM_NO_MARKED BIT(4)
#define STM_NO_GUARANTEED BIT(7)
/* Bit operation */
#define rounddown_pow_of_two(n) (1 << (fls(n) - 1))
/****************************************************************************
* Private Types
****************************************************************************/

View File

@ -25,6 +25,7 @@
#include <errno.h>
#include <nuttx/kmalloc.h>
#include <nuttx/lib/math32.h>
#include <nuttx/pci/pci.h>
#include <nuttx/pci/pci_ecam.h>
#include <nuttx/nuttx.h>
@ -40,7 +41,6 @@
#define readl(a) (*(FAR volatile uint32_t *)(a))
#define writel(v,a) (*(FAR volatile uint32_t *)(a) = (v))
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
#define IS_ALIGNED(x, a) (((x) & ((a) - 1)) == 0)
/****************************************************************************
@ -145,7 +145,7 @@ static bool pci_ecam_addr_valid(FAR const struct pci_bus_s *bus,
uint32_t devfn)
{
FAR struct pci_ecam_s *ecam = pci_ecam_from_controller(bus->ctrl);
int num_buses = DIV_ROUND_UP(pci_resource_size(&ecam->cfg), 1 << 20);
int num_buses = div_round_up(pci_resource_size(&ecam->cfg), 1 << 20);
return bus->number < num_buses;
}

View File

@ -29,11 +29,16 @@
#include <inttypes.h>
#include <stdint.h>
#include <strings.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define div_round_up(n, d) (((n) + (d) - 1) / (d))
#define div_round_closest(n, d) ((((n) < 0) ^ ((d) < 0)) ? \
(((n) - (d)/2)/(d)) : (((n) + (d)/2)/(d)))
/* Returns one plus the index of the most significant 1-bit of n,
* or if n is zero, returns zero.
*/
@ -107,6 +112,68 @@ extern "C"
* Public Function Prototypes
****************************************************************************/
#define is_power_of_2(n) IS_POWER_OF_2(n)
#define flsx(n) ((sizeof(n) <= sizeof(long)) ? flsl(n) : flsll(n))
/****************************************************************************
* Name: log2ceil
*
* Description:
* Calculate the up-rounded power-of-two for input.
*
* Input Parameters:
* x - Argument to calculate the power-of-two from.
*
* Returned Value:
* Power-of-two for argument, rounded up.
*
****************************************************************************/
#define log2ceil(n) (is_power_of_2(n) ? (flsx(n) - 1) : flsx(n))
/****************************************************************************
* Name: log2floor
*
* Description:
* Calculate the down-rounded (truncated) power-of-two for input.
*
* Input Parameters:
* x - Argument to calculate the power-of-two from.
*
* Returned Value:
* Power-of-two for argument, rounded (truncated) down.
*
****************************************************************************/
#define log2floor(n) (flsx(n) - 1)
/* roundup_pow_of_two() - Round up to nearest power of two
* n: value to round up
*/
#define roundup_pow_of_two(n) (((n) - (n) + 1) << flsx((n) - 1))
/* rounddown_pow_of_two() - Round down to nearest power of two
* n: value to round down
*/
#define rounddown_pow_of_two(n) (((n) - (n) + 1) << (flsx(n) - 1))
/* order_base_2 - Calculate the (rounded up) base 2 order of the argument
* n: parameter
*
* The first few values calculated by this routine:
* ob2(0) = 0
* ob2(1) = 0
* ob2(2) = 1
* ob2(3) = 2
* ob2(4) = 2
* ob2(5) = 3
* ... and so on.
*/
#define order_base_2(n) ((n) > 1 ? log2floor((n) - 1) + 1 : 0)
/* If the divisor happens to be constant, we determine the appropriate
* inverse at compile time to turn the division into a few inline
* multiplications which ought to be much faster.
@ -115,9 +182,9 @@ extern "C"
*/
#ifdef CONFIG_HAVE_LONG_LONG
/* Default C implementation for __umul64_const()
/* Default C implementation for umul64_const()
*
* Prototype: uint64_t __umul64_const(uint64_t retval, uint64_t m,
* Prototype: uint64_t umul64_const(uint64_t retval, uint64_t m,
* uint64_t n, bool bias);
* Semantic: retval = ((bias ? m : 0) + m * n) >> 64
*
@ -127,10 +194,10 @@ extern "C"
*/
# ifdef up_umul64_const
# define __umul64_const(res, m, n, bias) \
# define umul64_const(res, m, n, bias) \
(res) = up_umul64_const(m, n, bias)
# else
# define __umul64_const(res, m, n, bias) \
# define umul64_const(res, m, n, bias) \
do \
{ \
uint32_t __m_lo = (m) & 0xffffffff; \
@ -230,7 +297,7 @@ extern "C"
} \
___bias = 0; \
} \
__umul64_const(___res, ___m, ___n, ___bias); \
umul64_const(___res, ___m, ___n, ___bias); \
\
___res /= ___p; \
(n) = ___res; \
@ -419,38 +486,6 @@ void umul64(FAR const struct uint64_s *factor1,
FAR const struct uint64_s *factor2,
FAR struct uint64_s *product);
/****************************************************************************
* Name: log2ceil
*
* Description:
* Calculate the up-rounded power-of-two for input.
*
* Input Parameters:
* x - Argument to calculate the power-of-two from.
*
* Returned Value:
* Power-of-two for argument, rounded up.
*
****************************************************************************/
uintptr_t log2ceil(uintptr_t x);
/****************************************************************************
* Name: log2floor
*
* Description:
* Calculate the down-rounded (truncated) power-of-two for input.
*
* Input Parameters:
* x - Argument to calculate the power-of-two from.
*
* Returned Value:
* Power-of-two for argument, rounded (truncated) down.
*
****************************************************************************/
uintptr_t log2floor(uintptr_t x);
#undef EXTERN
#ifdef __cplusplus
}

View File

@ -2539,7 +2539,7 @@ ieee80211_he_ppe_size(uint8_t ppe_thres_hdr, FAR const uint8_t *phy_cap_info)
*/
n = (n * IEEE80211_PPE_THRES_INFO_PPET_SIZE * 2) + 7;
n = DIV_ROUND_UP(n, 8);
n = div_round_up(n, 8);
return n;
}

View File

@ -86,10 +86,6 @@ list(
lib_err.c
lib_instrument.c)
# Add generic integer math functions
list(APPEND SRCS lib_log2ceil.c lib_log2floor.c)
# Keyboard driver encoder/decoder
if(CONFIG_LIBC_KBDCODEC)

View File

@ -43,10 +43,6 @@ CSRCS += lib_crc64.c lib_crc32.c lib_crc16.c lib_crc16ccitt.c lib_crc8.c
CSRCS += lib_crc8ccitt.c lib_crc8table.c lib_glob.c lib_execinfo.c
CSRCS += lib_ftok.c lib_err.c lib_instrument.c
# Add generic integer math functions
CSRCS += lib_log2ceil.c lib_log2floor.c
# Keyboard driver encoder/decoder
ifeq ($(CONFIG_LIBC_KBDCODEC),y)

View File

@ -1,55 +0,0 @@
/****************************************************************************
* libs/libc/misc/lib_log2ceil.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/lib/math32.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: log2ceil
*
* Description:
* Calculate the up-rounded power-of-two for input.
*
* Input Parameters:
* x - Argument to calculate the power-of-two from.
*
* Returned Value:
* Power-of-two for argument, rounded up.
*
****************************************************************************/
uintptr_t log2ceil(uintptr_t x)
{
uintptr_t pot = 0;
for (x = x - 1; x; x >>= 1)
{
pot++;
}
return pot;
}

View File

@ -1,55 +0,0 @@
/****************************************************************************
* libs/libc/misc/lib_log2floor.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/lib/math32.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: log2floor
*
* Description:
* Calculate the down-rounded (truncated) power-of-two for input.
*
* Input Parameters:
* x - Argument to calculate the power-of-two from.
*
* Returned Value:
* Power-of-two for argument, rounded (truncated) down.
*
****************************************************************************/
uintptr_t log2floor(uintptr_t x)
{
uintptr_t pot = 0;
for (; x > 1; x >>= 1)
{
pot++;
}
return pot;
}