• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[JASS] [Snippet] Bitwise

Level 7
Joined
Dec 28, 2014
Messages
83
This code is written by @d07.RiV and was posted in WC3Campaigns.net (This site is already gone). Good thing, I have a backup copy of this snippet in my computer.

Besides preserving this treasure in Hive, JASS purists who aren't interested upgrading to newer versions of Warcraft III might find this snippet useful.

JASS:
// Bitwise by d07.RiV
// http://www.wc3c.net/showthread.php?p=1027546
// https://www.hiveworkshop.com/threads/snippet-bitwise.331760/

// Required global variables
// integer array bintable

// just hope it gets inlined in future
constant function NOT takes integer a returns integer
  return -1 - a
endfunction

// binary operations use lookup tables for 4-bit blocks
constant function AND takes integer a, integer b returns integer
  local integer ta = a / 16
  local integer tb = b / 16
  local integer x = udg_bintable[0x100 + (a - ta * 16) + (b - tb * 16) * 16]
  set a = ta / 16
  set b = tb / 16
  set x = x + udg_bintable[0x100 + (ta - a * 16) + (tb - b * 16) * 16] * 0x00000010
  set ta = a / 16
  set tb = b / 16
  set x = x + udg_bintable[0x100 + (a - ta * 16) + (b - tb * 16) * 16] * 0x00000100
  set a = ta / 16
  set b = tb / 16
  set x = x + udg_bintable[0x100 + (ta - a * 16) + (tb - b * 16) * 16] * 0x00001000
  set ta = a / 16
  set tb = b / 16
  set x = x + udg_bintable[0x100 + (a - ta * 16) + (b - tb * 16) * 16] * 0x00010000
  set a = ta / 16
  set b = tb / 16
  set x = x + udg_bintable[0x100 + (ta - a * 16) + (tb - b * 16) * 16] * 0x00100000
  set ta = a / 16
  set tb = b / 16
  set x = x + udg_bintable[0x100 + (a - ta * 16) + (b - tb * 16) * 16] * 0x01000000
  set a = ta / 16
  set b = tb / 16
  return x + udg_bintable[0x100 + (ta - a * 16) + (tb - b * 16) * 16] * 0x10000000
endfunction

constant function OR takes integer a, integer b returns integer
  local integer ta = a / 16
  local integer tb = b / 16
  local integer x = udg_bintable[0x200 + (a - ta * 16) + (b - tb * 16) * 16]
  set a = ta / 16
  set b = tb / 16
  set x = x + udg_bintable[0x200 + (ta - a * 16) + (tb - b * 16) * 16] * 0x00000010
  set ta = a / 16
  set tb = b / 16
  set x = x + udg_bintable[0x200 + (a - ta * 16) + (b - tb * 16) * 16] * 0x00000100
  set a = ta / 16
  set b = tb / 16
  set x = x + udg_bintable[0x200 + (ta - a * 16) + (tb - b * 16) * 16] * 0x00001000
  set ta = a / 16
  set tb = b / 16
  set x = x + udg_bintable[0x200 + (a - ta * 16) + (b - tb * 16) * 16] * 0x00010000
  set a = ta / 16
  set b = tb / 16
  set x = x + udg_bintable[0x200 + (ta - a * 16) + (tb - b * 16) * 16] * 0x00100000
  set ta = a / 16
  set tb = b / 16
  set x = x + udg_bintable[0x200 + (a - ta * 16) + (b - tb * 16) * 16] * 0x01000000
  set a = ta / 16
  set b = tb / 16
  return x + udg_bintable[0x200 + (ta - a * 16) + (tb - b * 16) * 16] * 0x10000000
endfunction

constant function XOR takes integer a, integer b returns integer
  local integer ta = a / 16
  local integer tb = b / 16
  local integer x = udg_bintable[0x300 + (a - ta * 16) + (b - tb * 16) * 16]
  set a = ta / 16
  set b = tb / 16
  set x = x + udg_bintable[0x300 + (ta - a * 16) + (tb - b * 16) * 16] * 0x00000010
  set ta = a / 16
  set tb = b / 16
  set x = x + udg_bintable[0x300 + (a - ta * 16) + (b - tb * 16) * 16] * 0x00000100
  set a = ta / 16
  set b = tb / 16
  set x = x + udg_bintable[0x300 + (ta - a * 16) + (tb - b * 16) * 16] * 0x00001000
  set ta = a / 16
  set tb = b / 16
  set x = x + udg_bintable[0x300 + (a - ta * 16) + (b - tb * 16) * 16] * 0x00010000
  set a = ta / 16
  set b = tb / 16
  set x = x + udg_bintable[0x300 + (ta - a * 16) + (tb - b * 16) * 16] * 0x00100000
  set ta = a / 16
  set tb = b / 16
  set x = x + udg_bintable[0x300 + (a - ta * 16) + (b - tb * 16) * 16] * 0x01000000
  set a = ta / 16
  set b = tb / 16
  return x + udg_bintable[0x300 + (ta - a * 16) + (tb - b * 16) * 16] * 0x10000000
endfunction

constant function NAND takes integer a, integer b returns integer
    return NOT(AND(a, b))
endfunction

constant function NOR takes integer a, integer b returns integer
    return NOT(OR(a, b))
endfunction

// shift left/right. DO NOT use negative values, this should get inlined as well
constant function SHL takes integer a, integer b returns integer
    return a * udg_bintable[b]
endfunction

constant function SHR takes integer a, integer b returns integer
    return a / udg_bintable[b]
endfunction

function InitBintable takes nothing returns nothing
  local integer i = 0
  local integer a
  local integer b
  local integer ta
  local integer tb
  loop
    exitwhen i >= 256
    set a = i / 16
    set b = i - a * 16
    set ta = a - (a / 2) * 2
    set tb = b - (b / 2) * 2
    set udg_bintable[0x100 + i] = ta * tb
    set udg_bintable[0x200 + i] = ta + tb - ta * tb
    set udg_bintable[0x300 + i] = ta + tb - 2 * ta * tb
    set a = a / 2
    set b = b / 2
    set ta = a - (a / 2) * 2
    set tb = b - (b / 2) * 2
    set udg_bintable[0x100 + i] = udg_bintable[0x100 + i] + 2 * (ta * tb)
    set udg_bintable[0x200 + i] = udg_bintable[0x200 + i] + 2 * (ta + tb - ta * tb)
    set udg_bintable[0x300 + i] = udg_bintable[0x300 + i] + 2 * (ta + tb - 2 * ta * tb)
    set a = a / 2
    set b = b / 2
    set ta = a - (a / 2) * 2
    set tb = b - (b / 2) * 2
    set udg_bintable[0x100 + i] = udg_bintable[0x100 + i] + 4 * (ta * tb)
    set udg_bintable[0x200 + i] = udg_bintable[0x200 + i] + 4 * (ta + tb - ta * tb)
    set udg_bintable[0x300 + i] = udg_bintable[0x300 + i] + 4 * (ta + tb - 2 * ta * tb)
    set ta = a / 2
    set tb = b / 2
    set udg_bintable[0x100 + i] = udg_bintable[0x100 + i] + 8 * (ta * tb)
    set udg_bintable[0x200 + i] = udg_bintable[0x200 + i] + 8 * (ta + tb - ta * tb)
    set udg_bintable[0x300 + i] = udg_bintable[0x300 + i] + 8 * (ta + tb - 2 * ta * tb)
    set i = i + 1
  endloop
  set i = 1
  set udg_bintable[0] = 1
  loop
    exitwhen i > 31
    set udg_bintable[i] = udg_bintable[i - 1] * 2
    set i = i + 1
  endloop
endfunction
 
Level 7
Joined
Sep 16, 2016
Messages
185
Bitwise is a way to manipulate the bits of an integer. It can be used for many things like boolean flags, compressing/decompressing, encryption/decryption, graphics, etc.

The latest versions of Warcraft III already have the Bitwise functions BlzBitAnd, BlzBitOr, and BlzBitXor.
Thanks for this information!
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
What is the valid input range? Does it only work with positive numbers?
I tried the three operators and they only gave correct results for positive inputs.
You should either document limitations or try to fix them.

Resources that are deprecated by new patches will be put in the graveyard and marked as legacy. It would still be useful to have this improved for those that use older versions.
 
Level 7
Joined
Dec 28, 2014
Messages
83
What is the valid input range? Does it only work with positive numbers?
I tried the three operators and they only gave correct results for positive inputs.
You should either document limitations or try to fix them.

I just tested AND(-1, -1), expected result is -1 but the result is 0.

I never realized this snippet cannot handle negative values but I won't fix it or amend the source code since I wanted it to be original as what d07.RiV written.

I will still try to check the valid input range and document all the possible limitations once I have free time.

Resources that are deprecated by new patches will be put in the graveyard and marked as legacy. It would still be useful to have this improved for those that use older versions.

I'm fine this snippet to be put in the graveyard and marked as legacy, as long as it is preserved in Hive.

If someone stumble upon this snippet and interested to improve it, that would be awesome.
 
Top