1.源自linux内核源码中的一段(有汇编的,不过摘抄的c实现的,并做了一点变形)
汇编的不做比较,记录下而已
Linux/arch/avr32/include/asm/page.h
/* Pure 2^n version of get_order */ static inline int get_order(unsigned long size) { unsigned lz; size = (size - 1) >> PAGE_SHIFT; asm("clz %0, %1" : "=r"(lz) : "r"(size)); return 32 - lz; }
内核中的原版
Linux/arch/mn10300/include/asm/page.h
#define PAGE_SHIFT 12 /* Pure 2^n version of get_order */ static inline int get_order(unsigned long size) __attribute__((const)); static inline int get_order(unsigned long size) { int order; size = (size - 1) >> (PAGE_SHIFT - 1); order = -1; do { size >>= 1; order++; } while (size); return order; }
小变更后的:
static inline int get_order(unsigned long size) { int order; size = (size - 1) >> (0); order = -1; do { size >>= 1; order++; } while (size); return order; }
2.源自lua源码中的一段
int luaO_log2 (unsigned int x) { static const unsigned char log_2[256] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 }; int l = -1; while (x >= 256) { l += 8; x >>= 8; } return l + log_2[x]; }
貌似纯C的话,还是lua的这个函数快吧。
最近的一个小需求是,根据size值,变更为接近2的幂的一个数(还多亏看了下lua源码。。。)。
1<<(luaO_log2(size)+1);
判断一个数是否为2的幂,为真则为2的幂:
#define is2power(a) (((a) & ((a)-1)) == 0)
才发现求余的位运算版。。。
#define dmod((a), (b)) ((a)&((b)-1)) 等于 a%b b要为2的幂
貌似很高效。留记录。