Does a "MultiNumber" package exist?

I’m looking for a package with a struct like:

struct MultiNumber{N, T <: Real} <: Real
    data::NTuple{N, T}
end

Where all mathematical operations on a MultiNumber would just apply element-wise. I.e. it would mimic a regular number while actually being multiple numbers beneath. E.g. for a MultiNumber, x, it would allow calculating f(x) with full SIMD support on N inputs.

The Vec struct from SIMD.jl could be used but it has two drawbacks:

  1. It only wraps primitive types so can’t e.g. nest Vecs of Vecs
  2. It is not a <:Real and thus cannot be ForwardDiff’ed.

The StaticVector from StaticArrays.jl also comes quite close, except it is semantically an AbstractVector and not a Real. Hence all operations must be dotted.

Does something like this exist - or should I roll my own? And could it have broader applicability besides just my own narrow interests?

2 Likes

It’s an interesting question, but why do you need it to be semantically a number? Naively I would classify it as a tuple or array?

Well;

  1. Aesthetics - don’t want to dot all my operators.
  2. I might not even own the function, f. And doing f.(x) would lose SIMD.
  3. And there’s no double-dot operator like x ..* y - assuming x,y are vectors of vectors of floats.

Are you sure about that? I think dotting on things like tuples (and therefore StaticArrays) is SIMD-friendly?

Agree, sin.(x) is definitely SIMD-friendly, but some_big_complicated_function.(x) is not (I would assume?)

LoopVectorization.jl uses such things, from here:

julia> x = VectorizationBase.Vec(1.0, 2.0)
Vec{2, Float64}<1.0, 2.0>

julia> x^2 + 0.1
Vec{2, Float64}<1.1, 4.1>

julia> x isa Real
true
1 Like

See Add support for intrinsics for `NTuple{VecElement}` by oscardssmith · Pull Request #55118 · JuliaLang/julia · GitHub for a very WIP version of this in Base julia.

MonteCarloMeasurements.jl uses such a type to propagate uncertainties:

julia> x = StaticParticles([1.0, 2.0])
1.5 ± 0.707 StaticParticles{Float64, 2}

julia> x^2 + 0.1 |> Base.Fix2(getfield, :particles)
2-element StaticArraysCore.SVector{2, Float64} with indices SOneTo(2):
 1.1
 4.1

julia> x isa Real
true
2 Likes

Yes thx, a somewhat domain-specific package it seems - but the underlying concept is spot on what I had in mind.