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的冪
貌似很高效。留記錄。
