You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

224 lines
6.7 KiB

/*
* Copyright : (C) 2023 Phytium Information Technology, Inc.
* All Rights Reserved.
*
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
* either version 1.0 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the Phytium Public License for more details.
*
*
* FilePath: fbitmap.c
* Created Date: 2023-10-31 18:09:12
* Last Modified: 2023-11-15 09:47:07
* Description: This file is for bitmap
*
* Modify History:
* Ver Who Date Changes
* ----- ---------- -------- ---------------------------------
* 1.0 huanghe 2023/11/10 first release
*/
#include <stdio.h>
#include <string.h>
#include "fbitmap.h"
#include "fcompiler.h"
#define FBIT_MASK ((sizeof(FBitPerWordType) * 8) - 1)
#define FBIT_WORD_MASK ~0UL
#define FBITMAP_BITS_PER_WORD (sizeof(FBitPerWordType) * 8)
#define FBITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % FBITMAP_BITS_PER_WORD))
#define FBITMAP_LAST_WORD_MASK(nbits) \
(((nbits) % FBITMAP_BITS_PER_WORD) ? (1UL << ((nbits) % FBITMAP_BITS_PER_WORD)) - 1 : ~0UL)
#define FBITMAP_WORD(x) ((x) / FBITMAP_BITS_PER_WORD)
#define FBITMAP_NUM_WORDS(x) (((x) + FBITMAP_BITS_PER_WORD - 1) / FBITMAP_BITS_PER_WORD)
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
/* find first zero bit starting from LSB */
static INLINE u16 Ffz(FBitPerWordType x)
{
return __builtin_ffs(~x) - 1;
}
/**
* @name: FBitMapSet
* @msg: Sets a bit at the specified position in a bitmap.
* @param {FBitPerWordType *} bitmap - Pointer to the bitmap.
* @param {u16} pos - The bit position to set.
*/
void FBitMapSet(FBitPerWordType *bitmap,u16 pos)
{
if (bitmap == NULL) {
return;
}
*bitmap |= 1U << (pos & FBIT_MASK);
}
/**
* @name: FBitMapClear
* @msg: Clears a bit at the specified position in a bitmap.
* @param {FBitPerWordType*} bitmap - Pointer to the bitmap.
* @param {u16} pos - The bit position to clear.
*/
void FBitMapClear(FBitPerWordType *bitmap,u16 pos)
{
if (bitmap == NULL) {
return;
}
*bitmap &= ~(1U << (pos & FBIT_MASK));
}
/**
* @name: FBitMapHighGet
* @msg: Gets the position of the highest set bit in a bitmap.
* @param {FBitPerWordType} bitmap - The bitmap to check.
* @return {u16} The position of the highest set bit or FBIT_INVALID_BIT_INDEX if none.
*/
u16 FBitMapHighGet(FBitPerWordType bitmap)
{
if (bitmap == 0)
{
return FBIT_INVALID_BIT_INDEX;
}
return (FBIT_MASK - CLZL(bitmap));
}
/**
* @name: FBitMapLowGet
* @msg: Gets the position of the lowest set bit in a bitmap.
* @param {FBitPerWordType} bitmap - The bitmap to check.
* @return {u16} The position of the lowest set bit or FBIT_INVALID_BIT_INDEX if none.
*/
u16 FBitMapLowGet(FBitPerWordType bitmap)
{
if (bitmap == 0) {
return FBIT_INVALID_BIT_INDEX;
}
return CTZL(bitmap);
}
/**
* @name: FBitMapSetNBits
* @msg: Sets a number of consecutive bits starting from a given position in a bitmap.
* @param {FBitPerWordType*} bitmap - Pointer to the bitmap.
* @param {u32} start - The starting bit position.
* @param {u32} nums_set - The number of bits to set.
*/
void FBitMapSetNBits(FBitPerWordType *bitmap, u32 start, u32 nums_set)
{
FBitPerWordType *p = bitmap + FBITMAP_WORD(start); /* 向下取整 */
const u32 size = start + nums_set;
u16 bits_toset = FBITMAP_BITS_PER_WORD - (start % FBITMAP_BITS_PER_WORD);
FBitPerWordType mask_toset = FBITMAP_FIRST_WORD_MASK(start);
while (nums_set > bits_toset) {
*p |= mask_toset;
nums_set -= bits_toset;
bits_toset = FBITMAP_BITS_PER_WORD;
mask_toset = FBIT_WORD_MASK;
p++;
}
if (nums_set) {
mask_toset &= FBITMAP_LAST_WORD_MASK(size);
*p |= mask_toset;
}
}
/**
* @name: FBitMapClrNBits
* @msg: Clears a number of consecutive bits starting from a given position in a bitmap.
* @param {FBitPerWordType*} bitmap - Pointer to the bitmap.
* @param {u32} start - The starting bit position.
* @param {u32} nums_clear - The number of bits to clear.
*/
void FBitMapClrNBits(FBitPerWordType *bitmap, u32 start, u32 nums_clear)
{
FBitPerWordType *p = bitmap + FBITMAP_WORD(start);
const u32 size = start + nums_clear;
u16 bits_toclear = FBITMAP_BITS_PER_WORD - (start % FBITMAP_BITS_PER_WORD);
FBitPerWordType mask_toclear = FBITMAP_FIRST_WORD_MASK(start);
while (nums_clear >= bits_toclear) {
*p &= ~mask_toclear;
nums_clear -= bits_toclear;
bits_toclear = FBITMAP_BITS_PER_WORD;
mask_toclear = FBIT_WORD_MASK;
p++;
}
if (nums_clear) {
mask_toclear &= FBITMAP_LAST_WORD_MASK(size);
*p &= ~mask_toclear;
}
}
/**
* @name: FBitMapFfz
* @msg: Finds the first zero bit in a bitmap within a given number of bits.
* @param {FBitPerWordType*} bitmap - Pointer to the bitmap.
* @param {u32} num_bits - The number of bits to check.
* @return {s32} The position of the first zero bit or -1 if not found.
*/
s32 FBitMapFfz(FBitPerWordType *bitmap, u32 num_bits)
{
s32 bit, i;
for (i = 0; i < FBITMAP_NUM_WORDS(num_bits); i++) {
if (bitmap[i] == FBIT_WORD_MASK) {
continue;
}
bit = i * FBITMAP_BITS_PER_WORD + Ffz(bitmap[i]);
if (bit < num_bits) {
return bit;
}
return -1;
}
return -1;
}
/**
* @name: FBitMapCopy
* @msg: Copies the content of one bitmap to another.
* @param {FBitPerWordType*} dst - Pointer to the destination bitmap.
* @param {const FBitPerWordType*} src - Pointer to the source bitmap.
* @param {u32} nbits - The number of bits to copy.
* @return {void}
*/
static void FBitMapCopy(FBitPerWordType *dst,const FBitPerWordType *src ,u32 nbits)
{
unsigned int len = DIV_ROUND_UP(nbits,FBITMAP_BITS_PER_WORD) * sizeof(FBitPerWordType);
memcpy(dst, src, len);
}
/**
* @name: FBitMapCopyClearTail
* @msg: Copies the content of one bitmap to another and clears the trailing bits of the last word if they are outside the specified range.
* @param {FBitPerWordType*} dst - Pointer to the destination bitmap.
* @param {const FBitPerWordType*} src - Pointer to the source bitmap.
* @param {u32} nbits - The number of bits to copy.
* @return {void}
*/
void FBitMapCopyClearTail(FBitPerWordType *dst,const FBitPerWordType *src ,u32 nbits)
{
FBitMapCopy(dst,src ,nbits) ;
if (nbits % FBITMAP_BITS_PER_WORD)
{
dst[nbits / FBITMAP_BITS_PER_WORD] &= FBITMAP_LAST_WORD_MASK(nbits);
}
}