Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Bitwise Functions #1724

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions addons/bitwise/$PBOPREFIX$
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x\cba\addons\bitwise
20 changes: 20 additions & 0 deletions addons/bitwise/CfgFunctions.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
class CfgFunctions {
class CBA {
class Bitwise {
PATHTO_FNC(bitflagsCheck);
PATHTO_FNC(bitflagsCheckBool);
PATHTO_FNC(bitflagsFlip);
PATHTO_FNC(bitflagsSet);
PATHTO_FNC(bitflagsUnset);
PATHTO_FNC(bitwiseAND);
PATHTO_FNC(bitwiseLROT);
PATHTO_FNC(bitwiseLSHFT);
PATHTO_FNC(bitwiseNOT);
PATHTO_FNC(bitwiseOR);
PATHTO_FNC(bitwiseRROT);
PATHTO_FNC(bitwiseRSHFT);
PATHTO_FNC(bitwiseXOR);
PATHTO_FNC(logBase2);
};
};
};
17 changes: 17 additions & 0 deletions addons/bitwise/config.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "script_component.hpp"

class CfgPatches {
class ADDON {
name = CSTRING(component);
units[] = {};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"cba_common"};
author = "$STR_CBA_Author";
authors[] = {"Daisy"};
url = "$STR_CBA_URL";
VERSION_CONFIG;
};
};

#include "CfgFunctions.hpp"
41 changes: 41 additions & 0 deletions addons/bitwise/fnc_bitflagsCheck.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* ----------------------------------------------------------------------------
Function: CBA_fnc_bitflagsCheck

Description:
Checks if a given flagset has the specified flags set.

* Values above 2^24 suffer inaccuracy at the hands of the Virtual Reality Engine. Inputs exceeding this value will error.

Parameters:
_flagset - flagset to check for flags within <NUMBER>
_flags - flags to check for <NUMBER>

Returns:
The sum of not-set bits on success, -1 on error. <NUMBER>

Examples:
(begin example)
[47,22] call CBA_fnc_bitflagsCheck // returns 16
// 47's set bits = 101111 (32,8,4,2,1)
// 22's set bits = 010110 (16,4,2)
// common set bits = 000110 (4,2)
// 22's unique bits = 010000 (16)
// sum of 22's unique bits = 16

[47,6] call CBA_fnc_bitflagsCheck // returns 0
// 47's set bits = 101111 (32,8,4,2,1)
// 6's set bits = 000110 (4,2)
// common set bits = 000110 (4,2)
// 6's unique bits = 000000 (0)
// sum of 6's unique bits = 0
(end)

Author:
Daisy
---------------------------------------------------------------------------- */
#define BASE2LOG(num) ((ln num)*1.44269502162933349609)
#define BITQUANT(num) floor BASE2LOG(num) + 1

params ["_flagset","_flags"];
_flagset = [_flagset,BITQUANT(_flagset max _flags)] call CBA_fnc_bitwiseNOT;
[_flagset,_flags] call CBA_fnc_bitwiseAND;
30 changes: 30 additions & 0 deletions addons/bitwise/fnc_bitflagsCheckBool.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* ----------------------------------------------------------------------------
Function: CBA_fnc_bitflagsCheckBool

Description:
Checks if a given flagset has the specified flags set.

* Values above 2^24 suffer inaccuracy at the hands of the Virtual Reality Engine. Inputs exceeding this value will error.

Parameters:
_flagset - flagset to check for flags within <NUMBER>
_flags - flags to check for <NUMBER>

Returns:
True on success, false otherwise. <BOOLEAN>

Examples:
(begin example)
[70,47] call CBA_fnc_bitflagsCheckBool // returns false:
// 70's set bits = 1000110 (64,4,2)
// 47's set bits = 0101111 (32,8,4,2,1)
// common set bits = 0000110 (4,2)
// 47's unique bits = 0101001 (32,8,1)
// sum of 47's unique bits = 41
// 41 != 0 so return false
(end)

Author:
Daisy
---------------------------------------------------------------------------- */
(_this call CBA_fnc_bitflagsCheck) isEqualTo 0
29 changes: 29 additions & 0 deletions addons/bitwise/fnc_bitflagsFlip.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* ----------------------------------------------------------------------------
Function: CBA_fnc_bitflagsFlip

Description:
Flips the flags' specified bits in the flagset.

* Values above 2^24 suffer inaccuracy at the hands of the Virtual Reality Engine. Inputs exceeding this value will error.

Parameters:
_flagset - flagset to flip flags within <NUMBER>
_flags - flags to flip <NUMBER>

Returns:
Sum of set bits on success, -1 otherwise. <NUMBER or BOOLEAN>

Examples:
(begin example)
[62,23] call CBA_fnc_bitflagsFlip; // returns 41
// 62's set bits = 111110 (32,16,8,4,2)
// 23's set bits = 010111 (16,4,2,1)
// common set bits = 010110 (16,4,2,1)
// unique set bits = 101001 (32,8,1)
// sum of unique bits = 41
(end)

Author:
Daisy
---------------------------------------------------------------------------- */
_this call CBA_fnc_bitwiseXOR;
28 changes: 28 additions & 0 deletions addons/bitwise/fnc_bitflagsSet.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* ----------------------------------------------------------------------------
Function: CBA_fnc_bitflagsSet

Description:
Sets the flags' specified bits in the flagset. Has no effect if the bits are already set.

* Values above 2^24 suffer inaccuracy at the hands of the Virtual Reality Engine. Inputs exceeding this value will error.

Parameters:
_flagset - flagset to set flags within <NUMBER>
_flags - flags to set <NUMBER>

Returns:
Sum of set bits on success, false otherwise. <NUMBER or BOOLEAN>

Examples:
(begin example)
[55,12] call CBA_fnc_bitflagsSet; // returns 63
// 55's set bits = 110111 (32,16,4,2,1)
// 12's set bits = 001100 (8,4)
// all set bits = 111111 (32,16,8,4,2,1)
// sum of all set bits = 63
(end)

Author:
Daisy
---------------------------------------------------------------------------- */
_this call CBA_fnc_bitwiseOR;
32 changes: 32 additions & 0 deletions addons/bitwise/fnc_bitflagsUnset.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* ----------------------------------------------------------------------------
Function: CBA_fnc_bitflagsUnset

Description:
Unsets the flags' specified bits in the flagset. Has no effect if the bits are already unset.

* Values above 2^24 suffer inaccuracy at the hands of the Virtual Reality Engine. Inputs exceeding this value will error.

Parameters:
_flagset - flagset to set flags within <NUMBER>
_flags - the flags to unset <NUMBER>

Returns:
Sum of set bits on success, -1 otherwise. <NUMBER>

Examples:
(begin example)
[55,14] call CBA_fnc_bitflagsUnset; // returns 49
// 55's set bits = 110111 (32,16,4,2,1)
// 14's set bits = 001110 (8,4,2)
// common set bits = 000110 (4,2)
// 55's unique bits = 110001 (32,16,1)
// sum of unique bits = 49
(end)

Author:
Daisy
---------------------------------------------------------------------------- */
params [["_flagset",0,[0]],"_flags"];
private _andReturn = [_flagset,_flags] call CBA_fnc_bitwiseAND;
if (_andReturn < 0) exitWith {-1};
(floor abs _flagset) - _andReturn
50 changes: 50 additions & 0 deletions addons/bitwise/fnc_bitwiseAND.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* ----------------------------------------------------------------------------
Function: CBA_fnc_bitwiseAND

Description:
Performs a bitwise AND operation between two numbers.

* This function converts all inputs into positive integers.
* This function also sorts the input array. Despite the naming of _min and _max, the input array does not have to be presorted.
* Values above 2^24 suffer inaccuracy at the hands of the Virtual Reality Engine. Inputs exceeding this value will error.

Parameters:
_min - a number <NUMBER>
_max - another number to compare to the first <NUMBER>

Returns:
Resulting number on success, -1 otherwise. <NUMBER>

Examples:
(begin example)
[55,25] call CBA_fnc_bitwiseAND; // returns 17
// 55's set bits = 110111 (32,16,4,2,1)
// 25's set bits = 011001 (16,8,1)
// common set bits = 010001 (16,1)
// sum of common bits = 17
(end)

Author:
Daisy
---------------------------------------------------------------------------- */
#define BITGRAB(num,pow) ((floor (num / pow)) mod 2)
#define BASE2LOG(num) ((ln num)*1.44269502162933349609)

private _input = _this;
_input resize 2;
_input = _input apply {floor abs _x};
_input sort true;
_input params [["_min",0,[0]],["_max",1,[1]]];

private _end = floor BASE2LOG(_min); //1/ln(2) = 1.44269502162933349609
if (_end >= 24) exitWith {-1}; // precision drop after 2^24 (16777216)

private _power = 0;
private _return = 0;

for "_i" from 0 to _end do {
_power = 2^_i;
_return = _return + (_power * (BITGRAB(_max,_power) * BITGRAB(_min,_power)));
};

_return
73 changes: 73 additions & 0 deletions addons/bitwise/fnc_bitwiseLROT.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* ----------------------------------------------------------------------------
Function: CBA_fnc_bitwiseLROT

Description:
Performs a bitwise LEFT-ROTATE-NO-CARRY operation on a given number. Bits that are both 1 are summed.

* This function converts all inputs into positive integers.
* Values above 2^24 suffer inaccuracy at the hands of the Virtual Reality Engine. Inputs exceeding this value will error.

Parameters:
_num - the number to rotate <NUMBER>
_numRot - the number of rotations to perform <NUMBER>
_numBits - the number of bits this number should occupy (optional) <NUMBER>

Returns:
Rotated number on success, -1 otherwise. <NUMBER>

Examples:
(begin example)
25 call CBA_fnc_bitwiseLROT; // returns 19
// 25's set bits = 11001 (16,8,1)
// shift left by 1 = 11001_
// move leftmost bit to back = 10011 (16,2,1)
// sum of rotated bits = 19

[25,2] call CBA_fnc_bitwiseLROT; // returns 7
// rotates once to 10011 (19)
// rotates twice to 00111 (7)

[25,2,6] call CBA_fnc_bitwiseLROT; // returns 37
// 25's set bits 011001
// rotates once to 110010 (50)
// rotates twice to 100101 (37)
(end)

Author:
Daisy
---------------------------------------------------------------------------- */
#define BITGRAB(num,pow) ((floor (num / pow)) mod 2)
#define BASE2LOG(num) ((ln num)*1.44269502162933349609)
#define BITQUANT(num) floor BASE2LOG(num) + 1

params [["_num",0,[0]],["_numRot",0,[0]],"_numBits"];

_num = floor abs _num;
_numRot = floor abs _numRot;

private _bitCount = BITQUANT(_num);
if (!isNil "_numBits" && {_numBits isEqualType 0 && {_numBits > _bitCount}}) then {_bitCount = (floor abs _numBits)};
if (_bitCount > 24) exitWith {-1};
if (_numRot > _bitCount) then {_numRot = _numRot % _bitCount;}; // trim excess rotations

private _power = 0;
private _amend = 0;

if (_numRot > (_bitCount / 2)) exitWith {
_numRot = _numRot - (floor (_bitCount / 2));

for "_i" from 0 to _numRot-1 do {
_power = 2^_i;
_amend = _amend + (BITGRAB(_num,_power) * (_power * 2^_numBits)); // _pow * 2^_numBits == 2^(_i + _numBits)
};

floor ((_num + _amend) / 2^_numRot) // sum and bitshift right
};

_num = 2^_numRot * _num; // bitshift left by numRot
for "_i" from _bitCount to (_bitCount + _numRot) do { // check bits over limit
_power = 2^_i;
_amend = _amend + (BITGRAB(_num,_power) * (_power - 2^(_i - _bitCount)));
};

_num - _amend
35 changes: 35 additions & 0 deletions addons/bitwise/fnc_bitwiseLSHFT.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/* ----------------------------------------------------------------------------
Function: CBA_fnc_bitwiseLSHFT

Description:
Performs a bitwise LEFT-SHIFT operation on a given number.

* This function converts all inputs into positive integers.
* Values above 2^24 suffer inaccuracy at the hands of the Virtual Reality Engine. Inputs exceeding this value will cause unexpected behavior.

Parameters:
_num - the number to shift <NUMBER>
_numShift - the number of shifts to perform <NUMBER>

Returns:
Shifted number <NUMBER>

Examples:
(begin example)
25 call CBA_fnc_bitwiseLSHFT; // returns 50
// 25's set bits = 11001 (16,8,1)
// shift bits left by 1, fill one's place with 0 = 110010 (32,16,2)
// sum of shifted bits = 50
[25,3] call CBA_fnc_bitwiseLSHFT; // returns 200
// 25's set bits = 11001 (16,8,1)
// shift bits left by 3, fill blank places with 0 = 11001000 (128,64,8)
// sum of shifted bits = 200
(end)

Author:
Daisy
---------------------------------------------------------------------------- */
params [["_num",1,[0]],["_numShift",0,[0]]];
_num = floor _num;
_numShift = floor _numShift;
_num * 2^_numShift
Loading