1. new new challenge
- Posted by rforno at tutopia.com Aug 18, 2001
- 497 views
This is a new and (I think) simpler challenge: Find the fastest algorithm to compute the largest power of 2 that exactly divides an integer from 1 to 2^31 - 1. The following is the test program I propose: function dummy(integer x) return x end function function best(integer x) -- ????????? return -- ????????? end function procedure test(integer iter, integer top) integer n, k atom sum, t0, t1 sum = 0 for i = 1 to top do for j = 0 to 31 do n = power(2, j) if remainder(i,n) != 0 then exit end if end for n = n / 2 t1 = time() for j = 1 to iter do k = dummy(i) end for t1 = time() - t1 t0 = time() for j = 1 to iter do k = best(i) end for sum += time() - t0 - t1 if n != k then printf(1, "%s %d %s %d \n", {"Error! ", n, "not equal", k}) end if end for printf(1, "%s %f \n", {"Time:", sum}) end procedure test(100000, 100) Of course, there is a trick I know.
2. Re: new new challenge
- Posted by rossboyd at ihug.com.au Aug 18, 2001
- 492 views
> This is a new and (I think) simpler challenge: > Find the fastest algorithm to compute the largest power of 2 that exactly > divides an integer from 1 to 2^31 - 1. Hi, The solution boils down to finding the value of the least significant bit. Here are two alternatives... unfortunately the ugly one is faster. Ross -- This solution is elegant but slower due to the divide by 2. -- If Euphoria had a bit shift operator or integer division -- this would probably be the fastest method. function best2(integer x) if and_bits(x,1) then -- quickly eliminate odd numbers return 1 end if return floor(xor_bits(x,x-1)/2) + 1 end function -- Cruder and faster solution... -- You could make it even faster by 'jumping' depending on the -- value of x and hence reduce the number of comparisons. -- But why bother... this method stinks already. function best(integer x) if and_bits(x,1) then return 1 end if if and_bits(x,2) then return 2 end if if and_bits(x,4) then return 4 end if if and_bits(x,8) then return 8 end if if and_bits(x,16) then return 16 end if if and_bits(x,32) then return 32 end if if and_bits(x,64) then return 64 end if if and_bits(x,128) then return 128 end if if and_bits(x,256) then return 256 end if if and_bits(x,512) then return 512 end if if and_bits(x,1024) then return 1024 end if if and_bits(x,2048) then return 2048 end if if and_bits(x,4096) then return 4096 end if if and_bits(x,8192) then return 8192 end if if and_bits(x,16384) then return 16384 end if if and_bits(x,32768) then return 32768 end if if and_bits(x,65536) then return 65536 end if if and_bits(x,131072) then return 131072 end if if and_bits(x,262144) then return 262144 end if if and_bits(x,524288) then return 524288 end if if and_bits(x,1048576) then return 1048576 end if if and_bits(x,2097152) then return 2097152 end if if and_bits(x,4194304) then return 4194304 end if if and_bits(x,8388608) then return 8388608 end if if and_bits(x,16777216) then return 16777216 end if if and_bits(x,33554432) then return 33554432 end if if and_bits(x,67108864) then return 67108864 end if if and_bits(x,134217728) then return 134217728 end if if and_bits(x,268435456) then return 268435456 end if if and_bits(x,536870912) then return 536870912 end if if and_bits(x,1073741824) then return 1073741824 end if return 0 end function procedure test(integer iter, integer top) integer n, k atom sum, t0, t1 sum = 0 for i = 1 to top do for j = 0 to 31 do n = power(2, j) if remainder(i,n) != 0 then exit end if end for n = n / 2 t1 = time() for j = 1 to iter do k = dummy(i) end for t1 = time() - t1 t0 = time() for j = 1 to iter do k = best(i) end for sum += time() - t0 - t1 if n != k then printf(1, "%s %d %s %d \n", {"Error! ", n, "not equal", k}) end if end for printf(1, "%s %f \n", {"Time:", sum}) end procedure test(100000, 100) if wait_key() then end if
3. Re: new new challenge
- Posted by rforno at tutopia.com Aug 20, 2001
- 462 views
You were really close to what I think is an unbeatable solution, namely: function best(integer x) return xor_bits(x, and_bits(x, x - 1)) end function The two functions may be reversed. ----- Original Message ----- From: <rossboyd at ihug.com.au> To: "EUforum" <EUforum at topica.com> Subject: Re: new new challenge > > > This is a new and (I think) simpler challenge: > > Find the fastest algorithm to compute the largest power of 2 that > exactly > > divides an integer from 1 to 2^31 - 1. > > Hi, > The solution boils down to finding the value of the least significant > bit. > Here are two alternatives... unfortunately the ugly one is faster. > Ross > > > -- This solution is elegant but slower due to the divide by 2. > -- If Euphoria had a bit shift operator or integer division > -- this would probably be the fastest method. > > function best2(integer x) > if and_bits(x,1) then -- quickly eliminate odd numbers > return 1 > end if > return floor(xor_bits(x,x-1)/2) + 1 > end function > > -- Cruder and faster solution... > -- You could make it even faster by 'jumping' depending on the > -- value of x and hence reduce the number of comparisons. > -- But why bother... this method stinks already. > function best(integer x) > if and_bits(x,1) then > return 1 > end if > if and_bits(x,2) then > return 2 > end if > if and_bits(x,4) then > return 4 > end if > if and_bits(x,8) then > return 8 > end if > if and_bits(x,16) then > return 16 > end if > if and_bits(x,32) then > return 32 > end if > if and_bits(x,64) then > return 64 > end if > if and_bits(x,128) then > return 128 > end if > if and_bits(x,256) then > return 256 > end if > if and_bits(x,512) then > return 512 > end if > if and_bits(x,1024) then > return 1024 > end if > if and_bits(x,2048) then > return 2048 > end if > if and_bits(x,4096) then > return 4096 > end if > if and_bits(x,8192) then > return 8192 > end if > if and_bits(x,16384) then > return 16384 > end if > if and_bits(x,32768) then > return 32768 > end if > if and_bits(x,65536) then > return 65536 > end if > if and_bits(x,131072) then > return 131072 > end if > if and_bits(x,262144) then > return 262144 > end if > if and_bits(x,524288) then > return 524288 > end if > if and_bits(x,1048576) then > return 1048576 > end if > if and_bits(x,2097152) then > return 2097152 > end if > if and_bits(x,4194304) then > return 4194304 > end if > if and_bits(x,8388608) then > return 8388608 > end if <snip> > >
4. Re: new new challenge
- Posted by rossboyd at ihug.com.au Aug 20, 2001
- 452 views
> You were really close to what I think is an unbeatable solution, namely: > > function best(integer x) > return xor_bits(x, and_bits(x, x - 1)) > end function > > The two functions may be reversed. That's a brilliant solution. In C or ASM it would be unbeatable. But strangely, in Euphoria my crude version is still ~50% faster. I ran a 1,000,000 iterations and halved the timing errors (by putting in 2 wait loops.) eg. ---------------------- t1 = time() while t1 = time() do end while t1 = time() -- insert code to test t1 = time() - t1 ---------------------- Your solution averaged 6.50 secs and my ugly one below was 3.85 secs on a P3-450. But I still much prefer your solution and will put it to use in my C programs. It will definitely be fastest in a compiled environment. Thanks for sharing your algorithm! Cheers, Ross ps. I tried the following using elsif 's and it was a LOT slower. Which might be of interest to the speed freaks out there. -- Crude but Fastest... function best(integer x) if and_bits(x,1) then return 1 end if if and_bits(x,2) then return 2 end if if and_bits(x,4) then return 4 end if if and_bits(x,8) then return 8 end if if and_bits(x,16) then return 16 end if if and_bits(x,32) then return 32 end if if and_bits(x,64) then return 64 end if if and_bits(x,128) then return 128 end if if and_bits(x,256) then return 256 end if if and_bits(x,512) then return 512 end if if and_bits(x,1024) then return 1024 end if if and_bits(x,2048) then return 2048 end if if and_bits(x,4096) then return 4096 end if if and_bits(x,8192) then return 8192 end if if and_bits(x,16384) then return 16384 end if if and_bits(x,32768) then return 32768 end if if and_bits(x,65536) then return 65536 end if if and_bits(x,131072) then return 131072 end if if and_bits(x,262144) then return 262144 end if if and_bits(x,524288) then return 524288 end if if and_bits(x,1048576) then return 1048576 end if if and_bits(x,2097152) then return 2097152 end if if and_bits(x,4194304) then return 4194304 end if if and_bits(x,8388608) then return 8388608 end if if and_bits(x,16777216) then return 16777216 end if if and_bits(x,33554432) then return 33554432 end if if and_bits(x,67108864) then return 67108864 end if if and_bits(x,134217728) then return 134217728 end if if and_bits(x,268435456) then return 268435456 end if if and_bits(x,536870912) then return 536870912 end if if and_bits(x,1073741824) then return 1073741824 end if return 0 end function
5. Re: new new challenge
- Posted by Robert Craig <rds at RapidEuphoria.com> Aug 20, 2001
- 465 views
Ross Boyd writes: >Your solution averaged 6.50 secs and > my ugly one below was 3.85 secs on a P3-450. It depends on the distribution of numbers that you feed in. I find the two functions are about equal, given a series of numbers 1 to 100,000,000. (To be really fair you might go to 1.07 billion, but that takes too long). The long chain of if's looks bad until you realize that 50% of the time you will quit after just one and_bits() test, 75% after just two, 87.5% after three etc. The simple function *always* does one and_bits(), one xor_bits(), and one subtraction. Regards, Rob Craig Rapid Deployment Software http://www.RapidEuphoria.com
6. Re: new new challenge
- Posted by rossboyd at ihug.com.au Aug 21, 2001
- 443 views
> Ross Boyd writes: > >Your solution averaged 6.50 secs and > > my ugly one below was 3.85 secs on a P3-450. Rob Craig wrote: > It depends on the distribution of numbers that you feed in. > I find the two functions are about equal, > given a series of numbers 1 to 100,000,000. (To be really > fair you might go to 1.07 billion, but that takes too long). You're quite right. The performance really slows down on the ugly multi-if solution when you apply a #7F000000 mask to the input. It degrades when processing large numbers. I just timed the 3 algorithms in C using 1,000,000,000 iterations These are the times not including the loop and function call overhead. (16.65 secs) 4.89 secs ..... "return x ^ (x & (x - 1));" 11.91 secs ..... "return ((x ^ (x-1)) >> 1) + 1 ;" 12.20 secs ..... "if (x & ?) return ?;" etc. etc. So, "nforno"s algorithm is by far the best....
7. Re: new new challenge
- Posted by rossboyd at ihug.com.au Aug 21, 2001
- 456 views
Ross Boyd writes: >Your solution averaged 6.50 secs and > my ugly one below was 3.85 secs on a P3-450. Rob Craig wrote: It depends on the distribution of numbers that you feed in. I find the two functions are about equal, given a series of numbers 1 to 100,000,000. (To be really fair you might go to 1.07 billion, but that takes too long). You're quite right. The performance really slows down on the ugly multi-if solution when you apply a #7F000000 mask to the input. It degrades when processing large numbers. I just timed the 3 algorithms in C using 1,000,000,000 iterations These are the times not including the loop and function call overhead. (16.65 secs) 4.89 secs ..... "return x ^ (x & (x - 1));" 11.91 secs ..... "return ((x ^ (x-1)) >> 1) + 1 ;" 12.20 secs ..... "if (x & ?) return ?;" etc. etc. So, "nforno"s algorithm is by far the best....
8. Re: new new challenge
- Posted by rossboyd at ihug.com.au Aug 21, 2001
- 455 views
Ross Boyd writes: >Your solution averaged 6.50 secs and > my ugly one below was 3.85 secs on a P3-450. Rob Craig wrote: It depends on the distribution of numbers that you feed in. I find the two functions are about equal, given a series of numbers 1 to 100,000,000. (To be really fair you might go to 1.07 billion, but that takes too long). You're quite right. The performance really slows down on the ugly multi-if solution when you apply a #7F000000 mask to the input. It degrades when processing large numbers. I just timed the 3 algorithms in C using 1,000,000,000 iterations These are the times not including the loop and function call overhead. (16.65 secs) 4.89 secs ..... "return x ^ (x & (x - 1));" 11.91 secs ..... "return ((x ^ (x-1)) >> 1) + 1 ;" 12.20 secs ..... "if (x & ?) return ?;" etc. etc. So, "nforno"s algorithm is by far the best....
9. Re: new new challenge
- Posted by rossboyd at ihug.com.au Aug 21, 2001
- 480 views
Ross Boyd writes: >Your solution averaged 6.50 secs and > my ugly one below was 3.85 secs on a P3-450. Rob Craig wrote: It depends on the distribution of numbers that you feed in. I find the two functions are about equal, given a series of numbers 1 to 100,000,000. (To be really fair you might go to 1.07 billion, but that takes too long). You're quite right. The performance really slows down on the ugly multi-if solution when you apply a #7F000000 mask to the input. It degrades when processing large numbers. I just timed the 3 algorithms in C using 1,000,000,000 iterations These are the times not including the loop and function call overhead. (16.65 secs) 4.89 secs ..... "return x ^ (x & (x - 1));" 11.91 secs ..... "return ((x ^ (x-1)) >> 1) + 1 ;" 12.20 secs ..... "if (x & ?) return ?;" etc. etc. So, "nforno"s algorithm is by far the best....