RosettaCodeData/Task/Bitwise-operations/AppleScript/bitwise-operations-3.apples...

83 lines
3.0 KiB
AppleScript

on bitwiseAND(n1, n2, registerSize)
set out to 0
-- Multiplying equivalent bit values by each other gives 1 where they're both 1 and 0 otherwise.
repeat with i from 0 to registerSize - 1
tell (2 ^ i) to set out to out + (n1 div it) * (n2 div it) mod 2 * it
end repeat
return out div 1
end bitwiseAND
on bitwiseOR(n1, n2, registerSize)
set out to 0
-- Adding bit values plus a further 1 gives a carry of 1 if either or both values are 1, but not if they're both 0.
repeat with i from 0 to registerSize - 1
tell (2 ^ i) to set out to out + (n1 div it mod 2 + n2 div it mod 2 + 1) div 2 * it
end repeat
return out div 1
end bitwiseOR
on bitwiseXOR(n1, n2, registerSize)
set out to 0
-- Adding bit values gives 1 if they're different and 0 (with or without a carry) if they're both the same.
repeat with i from 0 to registerSize - 1
tell (2 ^ i) to set out to out + (n1 div it + n2 div it) mod 2 * it
end repeat
return out div 1
end bitwiseXOR
on bitwiseNOT(n, registerSize)
-- Subtract n from an all-1s value (ie. from 1 less than 2 ^ registerSize).
tell (2 ^ registerSize) to return (it - 1 - n mod it) div 1
end bitwiseNOT
on leftShift(n, shift, registerSize)
-- Multiply by 2 ^ shift and lose any bits beyond the left of the register.
return n * (2 ^ shift) mod (2 ^ registerSize) div 1
end leftShift
on rightShift(n, shift, registerSize)
-- Divide by 2 ^ shift and lose any bits beyond the right of the register.
return n mod (2 ^ registerSize) div (2 ^ shift)
end rightShift
on arithmeticRightShift(n, shift, registerSize)
set n to n mod (2 ^ registerSize)
-- If the number's positive and notionally sets the sign bit, reinterpret it as a negative.
tell (2 ^ (registerSize - 1)) to if (n it) then set n to n mod it - it
-- Right shift by the appropriate amount
set out to n div (2 ^ shift)
-- If the result for a negative is 0, change it to -1.
if ((n < 0) and (out is 0)) then set out to -1
return out
end arithmeticRightShift
on leftRotate(n, shift, registerSize)
-- Cut the register at the appropriate point, left shift the right side and right shift the left by the appropriate amounts.
set shift to shift mod (registerSize)
return leftShift(n, shift, registerSize) + rightShift(n, registerSize - shift, registerSize)
end leftRotate
on rightRotate(n, shift, registerSize)
-- As left rotate, but applying the shift amounts to the opposite sides.
set shift to shift mod registerSize
return rightShift(n, shift, registerSize) + leftShift(n, registerSize - shift, registerSize)
end rightRotate
bitwiseAND(92, 7, 16) --> 4
bitwiseOR(92, 7, 16) --> 95
bitwiseXOR(92, 7, 16) --> 91
bitwiseNOT(92, 16) --> 64453
bitwiseNOT(92, 8) --> 163
bitwiseNOT(92, 32) --> 4.294967203E+9
leftShift(92, 7, 16) --> 11776
leftShift(92, 7, 8) --> 0
rightShift(92, 7, 16) --> 0
arithmeticRightShift(92, 7, 16) --> 0
arithmeticRightShift(-92, 7, 16) --> -1
leftRotate(92, 7, 8) --> 46
rightRotate(92, 7, 8) --> 184
rightRotate(92, 7, 16) --> 47104