271 lines
4.5 KiB
Elixir
271 lines
4.5 KiB
Elixir
defmodule Bitwise do
|
|
@moduledoc """
|
|
A set of functions that perform calculations on bits.
|
|
|
|
All bitwise functions work only on integers, otherwise an
|
|
`ArithmeticError` is raised. The functions `band/2`,
|
|
`bor/2`, `bsl/2`, and `bsr/2` also have operators,
|
|
respectively: `&&&/2`, `|||/2`, `<<</2`, and `>>>/2`.
|
|
|
|
## Guards
|
|
|
|
All bitwise functions can be used in guards:
|
|
|
|
iex> odd? = fn
|
|
...> int when Bitwise.band(int, 1) == 1 -> true
|
|
...> _ -> false
|
|
...> end
|
|
iex> odd?.(1)
|
|
true
|
|
|
|
All functions in this module are inlined by the compiler.
|
|
"""
|
|
|
|
@doc false
|
|
@deprecated "import Bitwise instead"
|
|
defmacro __using__(options) do
|
|
except =
|
|
cond do
|
|
Keyword.get(options, :only_operators) ->
|
|
[bnot: 1, band: 2, bor: 2, bxor: 2, bsl: 2, bsr: 2]
|
|
|
|
Keyword.get(options, :skip_operators) ->
|
|
["~~~": 1, &&&: 2, |||: 2, "^^^": 2, <<<: 2, >>>: 2]
|
|
|
|
true ->
|
|
[]
|
|
end
|
|
|
|
quote do
|
|
import Bitwise, except: unquote(except)
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Calculates the bitwise NOT of the argument.
|
|
|
|
Allowed in guard tests. Inlined by the compiler.
|
|
|
|
## Examples
|
|
|
|
iex> bnot(2)
|
|
-3
|
|
|
|
iex> bnot(2) &&& 3
|
|
1
|
|
|
|
"""
|
|
@doc guard: true
|
|
@spec bnot(integer) :: integer
|
|
def bnot(expr) do
|
|
:erlang.bnot(expr)
|
|
end
|
|
|
|
@doc false
|
|
def unquote(:"~~~")(expr) do
|
|
:erlang.bnot(expr)
|
|
end
|
|
|
|
@doc """
|
|
Calculates the bitwise AND of its arguments.
|
|
|
|
Allowed in guard tests. Inlined by the compiler.
|
|
|
|
## Examples
|
|
|
|
iex> band(9, 3)
|
|
1
|
|
|
|
"""
|
|
@doc guard: true
|
|
@spec band(integer, integer) :: integer
|
|
def band(left, right) do
|
|
:erlang.band(left, right)
|
|
end
|
|
|
|
@doc """
|
|
Bitwise AND operator.
|
|
|
|
Calculates the bitwise AND of its arguments.
|
|
|
|
Allowed in guard tests. Inlined by the compiler.
|
|
|
|
## Examples
|
|
|
|
iex> 9 &&& 3
|
|
1
|
|
|
|
"""
|
|
@doc guard: true
|
|
@spec integer &&& integer :: integer
|
|
def left &&& right do
|
|
:erlang.band(left, right)
|
|
end
|
|
|
|
@doc """
|
|
Calculates the bitwise OR of its arguments.
|
|
|
|
Allowed in guard tests. Inlined by the compiler.
|
|
|
|
## Examples
|
|
|
|
iex> bor(9, 3)
|
|
11
|
|
|
|
"""
|
|
@doc guard: true
|
|
@spec bor(integer, integer) :: integer
|
|
def bor(left, right) do
|
|
:erlang.bor(left, right)
|
|
end
|
|
|
|
@doc """
|
|
Bitwise OR operator.
|
|
|
|
Calculates the bitwise OR of its arguments.
|
|
|
|
Allowed in guard tests. Inlined by the compiler.
|
|
|
|
## Examples
|
|
|
|
iex> 9 ||| 3
|
|
11
|
|
|
|
"""
|
|
@doc guard: true
|
|
@spec integer ||| integer :: integer
|
|
def left ||| right do
|
|
:erlang.bor(left, right)
|
|
end
|
|
|
|
@doc """
|
|
Calculates the bitwise XOR of its arguments.
|
|
|
|
Allowed in guard tests. Inlined by the compiler.
|
|
|
|
## Examples
|
|
|
|
iex> bxor(9, 3)
|
|
10
|
|
|
|
"""
|
|
@doc guard: true
|
|
@spec bxor(integer, integer) :: integer
|
|
def bxor(left, right) do
|
|
:erlang.bxor(left, right)
|
|
end
|
|
|
|
@doc false
|
|
def unquote(:"^^^")(left, right) do
|
|
:erlang.bxor(left, right)
|
|
end
|
|
|
|
@doc """
|
|
Calculates the result of an arithmetic left bitshift.
|
|
|
|
Allowed in guard tests. Inlined by the compiler.
|
|
|
|
## Examples
|
|
|
|
iex> bsl(1, 2)
|
|
4
|
|
|
|
iex> bsl(1, -2)
|
|
0
|
|
|
|
iex> bsl(-1, 2)
|
|
-4
|
|
|
|
iex> bsl(-1, -2)
|
|
-1
|
|
|
|
"""
|
|
@doc guard: true
|
|
@spec bsl(integer, integer) :: integer
|
|
def bsl(left, right) do
|
|
:erlang.bsl(left, right)
|
|
end
|
|
|
|
@doc """
|
|
Arithmetic left bitshift operator.
|
|
|
|
Calculates the result of an arithmetic left bitshift.
|
|
|
|
Allowed in guard tests. Inlined by the compiler.
|
|
|
|
## Examples
|
|
|
|
iex> 1 <<< 2
|
|
4
|
|
|
|
iex> 1 <<< -2
|
|
0
|
|
|
|
iex> -1 <<< 2
|
|
-4
|
|
|
|
iex> -1 <<< -2
|
|
-1
|
|
|
|
"""
|
|
@doc guard: true
|
|
@spec integer <<< integer :: integer
|
|
def left <<< right do
|
|
:erlang.bsl(left, right)
|
|
end
|
|
|
|
@doc """
|
|
Calculates the result of an arithmetic right bitshift.
|
|
|
|
Allowed in guard tests. Inlined by the compiler.
|
|
|
|
## Examples
|
|
|
|
iex> bsr(1, 2)
|
|
0
|
|
|
|
iex> bsr(1, -2)
|
|
4
|
|
|
|
iex> bsr(-1, 2)
|
|
-1
|
|
|
|
iex> bsr(-1, -2)
|
|
-4
|
|
|
|
"""
|
|
@doc guard: true
|
|
@spec bsr(integer, integer) :: integer
|
|
def bsr(left, right) do
|
|
:erlang.bsr(left, right)
|
|
end
|
|
|
|
@doc """
|
|
Arithmetic right bitshift operator.
|
|
|
|
Calculates the result of an arithmetic right bitshift.
|
|
|
|
Allowed in guard tests. Inlined by the compiler.
|
|
|
|
## Examples
|
|
|
|
iex> 1 >>> 2
|
|
0
|
|
|
|
iex> 1 >>> -2
|
|
4
|
|
|
|
iex> -1 >>> 2
|
|
-1
|
|
|
|
iex> -1 >>> -2
|
|
-4
|
|
|
|
"""
|
|
@doc guard: true
|
|
@spec integer >>> integer :: integer
|
|
def left >>> right do
|
|
:erlang.bsr(left, right)
|
|
end
|
|
end
|