Path: utzoo!attcan!uunet!mcvax!philmds!leo From: leo@philmds.UUCP (Leo de Wit) Newsgroups: comp.lang.c Subject: Re: Ceiling of the Logarthim Base Two Message-ID: <540@philmds.UUCP> Date: 1 Jul 88 08:16:09 GMT References: <1802@loral.UUCP> <690009@hpfelg.HP.COM> <10978@sol.ARPA> Reply-To: leo@philmds.UUCP (Leo de Wit) Organization: Philips I&E DTS Eindhoven Lines: 62 In article <10978@sol.ARPA> crowl@cs.rochester.edu (Lawrence Crowl) writes: [introducory stuff for exponent calculating macro deleted].... >#define CEILOG2_U( n ) ((n) > 0x40000000 ? 31 : (n) > 0x20000000 ? 30 : \ >(n) > 0x10000000 ? 29 : (n) > 0x08000000 ? 28 : (n) > 0x04000000 ? 27 : \ >(n) > 0x02000000 ? 26 : (n) > 0x01000000 ? 25 : (n) > 0x00800000 ? 24 : \ >(n) > 0x00400000 ? 23 : (n) > 0x00200000 ? 22 : (n) > 0x00100000 ? 21 : \ >(n) > 0x00080000 ? 20 : (n) > 0x00040000 ? 19 : (n) > 0x00020000 ? 18 : \ >(n) > 0x00010000 ? 17 : (n) > 0x00008000 ? 16 : (n) > 0x00004000 ? 15 : \ >(n) > 0x00002000 ? 14 : (n) > 0x00001000 ? 13 : (n) > 0x00000800 ? 12 : \ >(n) > 0x00000400 ? 11 : (n) > 0x00000200 ? 10 : (n) > 0x00000100 ? 9 : \ >(n) > 0x00000080 ? 8 : (n) > 0x00000040 ? 7 : (n) > 0x00000020 ? 6 : \ >(n) > 0x00000010 ? 5 : (n) > 0x00000008 ? 4 : (n) > 0x00000004 ? 3 : \ >(n) > 0x00000002 ? 2 : (n) > 0x00000001 ? 1 : (n) > 0x00000000 ? 0 : \ >abort( ) ) [second symmetric solution for search up deleted]... Let's take for granted (as the author does) that n is at most a simple expression (an optimizer could keep it in a register for instance), otherwise simply shifting should be preferred. This macro is easily adapted for a binary search (in fact the 32 bit integers scream for it 8-); note I used a somewhat different layout to make things clearer for this macro (b.t.w. the 1<1<<15 ? (n) > 1<<23 ? (n) > 1<<27 ? (n) > 1<<29 ? (n) > 1<<30 ? 31 : 30\ : (n) > 1<<28 ? 29 : 28\ : (n) > 1<<25 ? (n) > 1<<26 ? 27 : 26\ : (n) > 1<<24 ? 25 : 24\ : (n) > 1<<19 ? (n) > 1<<21 ? (n) > 1<<22 ? 23 : 22\ : (n) > 1<<20 ? 21 : 20\ : (n) > 1<<17 ? (n) > 1<<18 ? 19 : 18\ : (n) > 1<<16 ? 17 : 16\ : (n) > 1<<7 ? (n) > 1<<11 ? (n) > 1<<13 ? (n) > 1<<14 ? 15 : 14\ : (n) > 1<<12 ? 13 : 12\ : (n) > 1<<9 ? (n) > 1<<10 ? 11 : 10\ : (n) > 1<<8 ? 9 : 8\ : (n) > 1<<3 ? (n) > 1<<5 ? (n) > 1<<6 ? 7 : 6\ : (n) > 1<<4 ? 5 : 4\ : (n) > 1<<1 ? (n) > 1<<2 ? 3 : 2\ : (n) > 1<<0 ? 1 : 0) The average search is 5 steps, while the linear search averages to 16 steps. Another approach is to assign the value to a float (double) and use the exponent. This could even prove faster. For example: #include int expo; frexp((double)n,&expo); If frexp is builtin this just could be faster. Otherwise the bits of (double)n can be manipulated (non-portable). Enjoy! Leo.