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:
parent
4fd78583f7
commit
ca39dc2e74
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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
|
||||
****************************************************************************/
|
||||
|
|
|
@ -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,8 +41,7 @@
|
|||
#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)
|
||||
#define IS_ALIGNED(x, a) (((x) & ((a) - 1)) == 0)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,10 +182,10 @@ 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,
|
||||
* uint64_t n, bool bias);
|
||||
* Prototype: uint64_t umul64_const(uint64_t retval, uint64_t m,
|
||||
* uint64_t n, bool bias);
|
||||
* Semantic: retval = ((bias ? m : 0) + m * n) >> 64
|
||||
*
|
||||
* The product is a 128-bit value, scaled down to 64 bits.
|
||||
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue