flat assembler
Message board for the users of flat assembler.
  
|  Index
      > Assembly > Division by multiplication - revisited Goto page Previous 1, 2 | 
| Author | 
 | 
| Furs 10 Mar 2018, 16:31 Ok, the thing I gathered together works great (with all that I got from here, including your first method if the 0xFFFF...FF value is possible, I bet nobody else uses it   ). Now I can feel at peace knowing the stupid thing can spit out the most optimal constants/method. Thanks   A related question. What's the best (fastest, in general) way to check if a number is divisible by a constant? Sure, I can use the division here, and see if the result multiplied with the divisor is equal to the original value... but that's 2 muls. So I found this here: https://math.stackexchange.com/questions/1251327/is-there-a-fast-divisibility-check-for-a-fixed-divisor For odd divisors it's fantastic, one mul and one cmp, literally. But it needs two branches if the divisor is even, which sucks (or a lot of extra overhead code/registers usage, unless you can find a better way, problem is the ZF can't be used except with cmov, no adc/sbb tricks). Any better way for even divisors? (I'm not a math guru so I don't really understand how it works, lol) I did implement them both in C++ with constexpr (compile-time) forcing, and it works fine, but it'd be nice to have a better way for even divisors. (by "better way" I mean in the resulting asm of course, not having two branches is a good win unless I need 3-4 extra instructions, then it's not so good) (well I have them in C++ so far for HLL usage, which I just use it to compile a simple function if I want the constants for asm usage by looking at the output... like what I was originally doing, except GCC's optimizer sucks, though it's a bit ugly since I had to use internal constexpr functions to force it at compile-time, GCC is too dumb with loops otherwise; I don't know if anyone is interested in my C++ code with them) For example, let's say checking if number is divisible by 6. So far my code spits this out: Code: test al, 1 jnz .no imul eax, eax, 0xAAAAAAAB cmp eax, 0x55555555 ja .no | |||
|  10 Mar 2018, 16:31 | 
 | 
| l4m2 24 Jan 2019, 02:24 Tomasz Grysztar wrote: 
 Code: imul ecx,edx,19h | |||
|  24 Jan 2019, 02:24 | 
 | 
| Tomasz Grysztar 24 Jan 2019, 07:29 l4m2 wrote: 
 | |||
|  24 Jan 2019, 07:29 | 
 | 
| bitRAKE 25 Jan 2019, 05:03 Furs wrote: A related question. What's the best (fastest, in general) way to check if a number is divisible by a constant? Sure, I can use the division here, and see if the result multiplied with the divisor is equal to the original value... but that's 2 muls. So I found this here: https://math.stackexchange.com/questions/1251327/is-there-a-fast-divisibility-check-for-a-fixed-divisor Code: MACRO DisplayNumber in LOCAL number number = in scale 0 IF number < 0 DISPLAY '-' number = -number END IF REPEAT 1, n:number DISPLAY `n END REPEAT END MACRO virtual at 0 HexDigits:: db '0123456789ABCDEF' end virtual macro DisplayHex val*,bytes:0 local chars if bytes chars = 2*bytes else chars = 2 + 2*((bsr (val))/8) end if repeat chars load digit:byte from HexDigits: ((val) shr ((%%-%) shl 2)) and 0Fh display digit end repeat end macro struc egcd: a,b local t if a = 0 .gcd = b .x = 0 .y = 1 else . egcd (b mod a),a t := .x .x = (.y - (b / a) * .x) .y = t end if end struc macro fast_div d*,w* local m,j, _d,t m = 1 shl w j = bsf d _d = d shr j if j > 0 display 'n << ' DisplayNumber w-j display ' == 0',13,10 end if if _d > 1 t egcd _d,m display 'n * ' DisplayHex t.x mod m, w shr 3 display ' <= ' DisplayHex m / _d, w shr 3 display 13,10 end if end macro fast_div 76,64 https://www.youtube.com/watch?v=yi-s-TTpLxY _________________ ¯\(°_o)/¯ AI may [not] have aided with the above reply. | |||
|  25 Jan 2019, 05:03 | 
 | 
| Furs 29 Jan 2019, 12:46 bitRAKE thank you for that, really helpful.   | |||
|  29 Jan 2019, 12:46 | 
 | 
| Tomasz Grysztar 07 Feb 2019, 09:27 I'm adding a link to the other thread, where I discuss 2-adic approach in detail. It nicely complements this one. | |||
|  07 Feb 2019, 09:27 | 
 | 
| Tomasz Grysztar 04 Jun 2020, 16:34 Furs wrote: A related question. What's the best (fastest, in general) way to check if a number is divisible by a constant? Sure, I can use the division here, and see if the result multiplied with the divisor is equal to the original value... but that's 2 muls. So I found this here: https://math.stackexchange.com/questions/1251327/is-there-a-fast-divisibility-check-for-a-fixed-divisor And today I found a publication about an even better method of divisibility checking: https://lemire.me/blog/2019/02/08/faster-remainders-when-the-divisor-is-a-constant-beating-compilers-and-libdivide/ The "lkk_divisible" method from the paper works for even divisors as well as for the odd ones. | |||
|  04 Jun 2020, 16:34 | 
 | 
| revolution 05 Jun 2020, 00:05 Tomasz Grysztar wrote: And today I found a publication about an even better method of divisibility checking: I don't understand why this: Code: return n * c <= c - 1; Code: return n * c < c; | |||
|  05 Jun 2020, 00:05 | 
 | 
| tthsqe 05 Jun 2020, 13:39 revolution, transforming n * c <= c - 1 to n*c < c has problems when c = 0. Apparently the code is supposed to work in the very important case of testing divisibility by 1     In seriousness, if c a compile time constant, compilers can figure out the validity of the transformation and apply it. | |||
|  05 Jun 2020, 13:39 | 
 | 
| revolution 05 Jun 2020, 13:49 tthsqe wrote: revolution, transforming n * c <= c - 1 to n*c < c has problems when c = 0. Apparently the code is supposed to work in the very important case of testing divisibility by 1   let c = 0 then n * 0 <= 0 - 1 ---> false and n * 0 < 0 ---> false And the only way c = 0 is if 0xFFF...FFF/d = 0. So d is larger than the maximum integer. If d = 1 then c = 0xFFF....FFF    | |||
|  05 Jun 2020, 13:49 | 
 | 
| tthsqe 05 Jun 2020, 13:53 Keep in mind that the types are unsigned. Everything is mod 2^64 or 2^32. When d = 1, the addition wraps around to give c = 0, and now everything is <= c - 1 because this is the max uint. | |||
|  05 Jun 2020, 13:53 | 
 | 
| Goto page  Previous  1, 2 < Last Thread | Next Thread > | 
| Forum Rules: 
 | 
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.