# Internal methods

CliffordNumbers.HammingModule
CliffordNumbers.Hamming

A submodule containing methods for working with the sum of binary digits contained in an integer. This is essential to representing the basis blades of a geometric algebra, as the presence or absence of each possible basis vector in a blade can be represented by a binary 1 or 0. Operations that require knowledge of the grade of a basis blade will need the operations in this submodule.

CliffordNumbers.Hamming.isevilFunction
CliffordNumbers.Hamming.isevil(i::Integer) -> Bool

Determines whether a number is evil, meaning that its Hamming weight (sum of its binary digits) is even.

CliffordNumbers.Hamming.isodiousFunction
CliffordNumbers.Hamming.isodious(i::Integer) -> Bool

Determines whether a number is odious, meaning that its Hamming weight (sum of its binary digits) is odd.

CliffordNumbers.Hamming.number_of_parityFunction
CliffordNumbers.Hamming.number_of_parity(n::Integer, modulo::Bool)

Returns the nth number whose Hamming weight is even (for modulo = false) or odd (for modulo = true).

CliffordNumbers.Hamming.evil_numberFunction
CliffordNumbers.Hamming.evil_number(n::Integer)

Returns the nth evil number, with the first evil number (n == 1) defined to be 0.

Evil numbers are numbers which have an even Hamming weight (sum of its binary digits).

CliffordNumbers.Hamming.odious_numberFunction
CliffordNumbers.Hamming.odious_number(n::Integer)

Returns the nth odious number, with the first odious number (n == 1) defined to be 1.

Odious numbers are numbers which have an odd Hamming weight (sum of its binary digits).

CliffordNumbers.Hamming.hamming_numberFunction
CliffordNumbers.Hamming.hamming_number(w::Integer, n::Integer)

Gets the nth number with Hamming weight w. The first number with this Hamming weight (n = 1) is 2^w - 1.

Example

julia> CliffordNumbers.hamming_number(3, 2)
11

## Indexing

CliffordNumbers.signmaskFunction
CliffordNumbers.signmask([T::Type{<:Integer} = UInt], [signbit::Bool = true]) -> T

Generates a signmask, or a string of bits where the only 1 bit is the sign bit. If signbit is set to false, this returns zero (or whatever value is represented by all bits being 0).

CliffordNumbers._sort_with_parity!Function
CliffordNumbers._sort_with_parity!(v::AbstractVector{<:Real}) -> Tuple{typeof(v),Bool}

Performs a parity-tracking insertion sort of v, which modifies v in place. The function returns a tuple containing v and the parity, which is true for an odd permutation and false for an even permutation. This is implemented with a modified insertion sort algorithm.

CliffordNumbers.bitindices_typeFunction
CliffordNumbers.bitindices_type(C::Type{<:AbstractCliffordNumber{Q,T}})

Removes extraneous type parameters from C, converting it to the least parameterized type that can be used to parameterize an AbstractBitIndices{Q,C} object. This is to avoid issues with the proliferation of type parameters that would construct identical BitIndices objects otherwise: for instance, BitIndices{VGA(3),EvenCliffordNumber{VGA(3),Float32,4}}() and BitIndices{VGA(3),EvenCliffordNumber{VGA(3),Int}}() have identical elements, and are equal when compared with ==, but are not the same object.

For types defined in this package, this strips the scalar type parameter T and any length parameters present.

Examples

julia> CliffordNumbers.bitindices_type(CliffordNumber{VGA(3),Float32,8})
CliffordNumber{VGA(3)}

julia> CliffordNumbers.bitindices_type(KVector{2,STA,Bool})
KVector{2,STA}

## Construction

CliffordNumbers.zero_tupleFunction
CliffordNumbers.zero_tuple(::Type{T}, ::Val{L}) -> NTuple{L,T}

Generates a Tuple of length L with all elements being zero(T).

CliffordNumbers.zero_tuple(::Type{C<:AbstractCliffordNumber})
-> NTuple{nblades(C),scalar_type(C)}

Generates a Tuple that can be used to construct zero(C).

CliffordNumbers.check_element_countFunction
CliffordNumbers.check_element_count(sz, [L], data)

Ensures that the number of elements in data is the same as the result of f(Q), where f is a function that generates the expected number of elements for the type. This function is used in the inner constructors of subtypes of AbstractCliffordNumber{Q} to ensure that the input has the correct length.

If provided, the length type parameter L can be included as an argument, and it will be checked for type (must be an Int) and value (must be equal to sz).

This function returns nothing, but throws an AssertionError for failed checks.

## Multiplication kernels

CliffordNumbers.mulFunction
CliffordNumbers.mul(
x::AbstractCliffordNumber{Q},
y::AbstractCliffordNumber{Q},
)

A fast geometric product implementation using generated functions for specific cases, and generic methods which either convert the arguments or fall back to other methods.

The arguments to this function should all agree in scalar type T. The * function, which exposes the fast geometric product implementation, promotes the scalar types of the arguments before utilizing this kernel. The scalar multiplication operations are implemented using muladd, allowing for hardware fma operations to be used when available.

The GradeFilter F allows for some blade multiplications to be excluded if they meet certain criteria. This is useful for implementing products besides the geometric product, such as the wedge product, which excludes multiplications between blades with shared vectors. Without a filter, this kernel just returns the geometric product.

CliffordNumbers.GradeFilterType
CliffordNumbers.GradeFilter{S}

A type that can be used to filter certain products of blades in a geometric product multiplication. The type parameter S must be a Symbol. The single instance of GradeFilter{S} is a callable object which implements a function that takes two or more BitIndex{Q} objects a and b and returns false if the product of the blades indexed is zero.

To implement a grade filter for a product function f, define the following method: (::GradeFilter{:f})(::BitIndex{Q}, ::BitIndex{Q}) # Or if the definition allows for more arguments (::GradeFilter{:f})(::BitIndex{Q}...) where Q

CliffordNumbers.nondegenerate_maskFunction
CliffordNumbers.nondegenerate_mask(a::BitIndex{Q}, B::NTuple{L,BitIndex{Q}})

Constructs a Boolean mask which is false for any multiplication that squares a degenerate blade; true otherwise.

CliffordNumbers.mul_maskFunction
CliffordNumbers.mul_mask(F::GradeFilter, a::BitIndex{Q}, B::NTuple{L,BitIndices{Q}})

CliffordNumbers.mul_mask(F::GradeFilter, B::BitIndices{Q}, a::BitIndex{Q})

Generates a NTuple{L,Bool} which is true whenever the multiplication of the blade indexed by a and blades indexed by B is nonzero. false is returned if the grades multiply to zero due to the squaring of a degenerate component, or if they are filtered by F.

CliffordNumbers.mul_signsFunction
CliffordNumbers.mul_signs(F::GradeFilter, a::BitIndex{Q}, B::NTuple{L,BitIndices{Q}})

CliffordNumbers.mul_signs(F::GradeFilter, B::BitIndices{Q}, a::BitIndex{Q})

Generates an NTuple{L,Int8} which represents the sign associated with the multiplication needed to calculate components of a multiplication result.

This is equivalent to sign.(B) unless F === CliffordNumbers.GradeFilter{:dot}().

CliffordNumbers.bitindex_shuffleFunction
CliffordNumbers.bitindex_shuffle(a::BitIndex{Q}, B::NTuple{L,BitIndex{Q}})
CliffordNumbers.bitindex_shuffle(a::BitIndex{Q}, B::BitIndices{Q})

CliffordNumbers.bitindex_shuffle(B::NTuple{L,BitIndex{Q}}, a::BitIndex{Q})
CliffordNumbers.bitindex_shuffle(B::BitIndices{Q}, a::BitIndex{Q})

Performs the multiplication -a * b for each element of B for the above ordering, or -b * a for the below ordering, generating a reordered NTuple of BitIndex{Q} objects suitable for implementing a geometric product.

## Taylor series exponential

CliffordNumbers.exp_taylorFunction
CliffordNumbers.exp_taylor(x::AbstractCliffordNumber, order = Val(16))

Calculates the exponential of x using a Taylor expansion up to the specified order. In most cases, 12 is as sufficient number.

Notes

16 iterations is currently used because the number of loop iterations is not currently a performance bottleneck.

## Return types for operations

CliffordNumbers.product_return_typeFunction
CliffordNumbers.product_return_type(::Type{X}, ::Type{Y}, [::GradeFilter{S}])

Returns a suitable type for representing the product of Clifford numbers of types X and Y. The GradeFilter{S} argument allows for the return type to be changed depending on the type of product. Without specialization on S, a type suitable for the geometric product is returned.

CliffordNumbers.exponential_typeFunction
CliffordNumbers.exponential_type(::Type{<:AbstractCliffordNumber})
CliffordNumbers.exponential_type(x::AbstractCliffordNumber)

Returns the type expected when exponentiating a Clifford number. This is an EvenCliffordNumber if the nonzero grades of the input are even, a CliffordNumber otherwise.