# Category:Jq/bitwise.jq

```module {
"name": "bitwise",
"description": "bit arrays, bit streams, and integers",
"version": "2024.04.04",
"homepage": "https://rosettacode.org/w/index.php?title=Category:Jq/bitwise.jq",
"author": "pkoppstein at gmail dot com",
};

# This jq module defines functions for bit-wise operations on integers,
# together with an integer-divsion function, div/1, which is defined
# to take advantage of gojq's support for ininite-precision integer arithmetic.

# To take advantage of gojq's infinite-precision integer arithmetic:
# if the input and \$j are integers, then the result will be an integer.
def div(\$j):
(. - (. % \$j)) / \$j;

# Convert the input integer to a stream of 0s and 1s, least significant bit first
def bitwise:
recurse( if . >= 2 then div(2) else empty end) | . % 2;

# Input is normally an integer but could be a number
def rightshift(\$n):
reduce range(0;\$n) as \$i (.; div(2));

# Input is normally an integer but could be a number
def leftshift(\$n):
reduce range(0;\$n) as \$i (.; . * 2);

# Flip 0 and 1 and leave everything else as is
def flipbits(stream):
stream | if . == 0 then 1 elif . == 1 then 0 else . end;

# The inverse of `bitwise`
def stream_to_integer(stream):
reduce stream as \$c ( {power:1 , ans: 0};
.ans += (\$c * .power) | .power *= 2 )
| .ans;

# If the input is a number, emit its round value (because jaq uses `round` to convert real to integer);
# otherwise, the input should be a a bit-array interpreted as having the least-significant bit first
def to_int:
if type == "number" then round
else stream_to_integer(.[])
end ;

# If the input is null, then the bitwise bits of the integer \$x are simply flipped;
# otherwise, the input integer determines the width for padding or truncation
def flip(\$x):
if . == null then stream_to_integer(flipbits(\$x|bitwise))
else . as \$n
| [limit(\$n; \$x|bitwise)] as \$bits
| stream_to_integer(flipbits( \$bits[], range(0; \$n - (\$bits|length)) | 0))
end;

# Emit an array of the \$n least-significant bits of the input non-negative integer;
# the length of the array will thus be less than or equal to \$n
def lsbits(\$n): [limit(\$n; bitwise)];

# \$x and \$y should be two non-negative integers or arrays as produced by [bitwise].
# Emit the integer corresponding to the bitwise-or of \$x and \$y
def bitwise_or(\$x;\$y):
def tobitarray: if type == "number" then [bitwise] else . end;
def lor(\$a;\$b):
if \$a==1 or \$b==1 then 1
else 0
end;
if   \$x == 0 or \$x == [0] then \$y | to_int
elif \$y == 0 or \$y == [0] then \$x | to_int
else (\$x|tobitarray) as \$s
| (\$y|tobitarray) as \$t
| stream_to_integer(
range(0; [(\$s|length), (\$t|length)] | max) as \$i
| lor(\$s[\$i]; \$t[\$i]) )
end;

# Emit the integer corresponding to `\$x bitwise-and \$y`,
# assuming these are non-negative integers or bitarrays
def bitwise_xor(\$x;\$y):
def tobitarray: if type == "number" then [bitwise] else . end;
def lxor(\$a; \$b):
if (\$a==1 or \$b==1) and ((\$a==1 and \$b==1)|not) then 1
elif \$a == null then \$b
elif \$b == null then \$a
else 0
end;
if \$x == 0 or \$x == [0] then \$y | to_int
elif \$y == 0 or \$y == [0] then \$x | to_int
else
(\$x|tobitarray) as \$s
| (\$y|tobitarray) as \$t
| stream_to_integer(
range(0; [(\$s|length), (\$t|length)] | max) as \$i
| lxor(\$s[\$i]; \$t[\$i]) )
end ;

# Emit the integer corresponding to `\$x bitwise-and \$y`,
# assuming these are non-negative integers or bitarrays
def bitwise_and(\$x; \$y):
def tobitarray: if type == "number" then [bitwise] else . end;
def land(\$a;\$b):
if (\$a==1 and \$b==1) then 1 else 0 end;

if \$x == 0 or \$y == 0 or \$x == [0] or \$y == [0] then 0
else (\$x|tobitarray) as \$s
| (\$y|tobitarray) as \$t
| stream_to_integer(
range(0; [(\$s|length), (\$t|length)] | min) as \$i
| land(\$s[\$i]; \$t[\$i]) )
end ;

# A special case of \$x xor \$y where both are non-negative integers
# If the input is a number, it determines the maximum number of bits to consider
def xor(\$x;\$y):
(if type == "number" then round else null end) as \$n
| if \$n == null then bitwise_xor(\$x;\$y)
else bitwise_xor( \$x | lsbits(\$n); \$y | lsbits(\$n) )
end ;```

This category currently contains no pages or media.