I erred. Based on @lmiq and @pjentsch0 proposals I have
using Random, BenchmarkTools
function expandgrid(vectors) # Cartesian product
cp = Iterators.product(ntuple(i -> vectors[i], length(vectors))...)
return hcat(map(collect, collect(cp))...)
end
function changesOfSign(vectors)
vvv = [[ifelse(x==0, [0.0], [-x, x]) for x=v] for v=vectors]
mats = [expandgrid(vv) for vv=vvv]
mat = hcat(mats...)
return [mat[:, i] for i=1:size(mat, 2)]
end
function signs1(vecs, ::Val{N}) where {N}
list = eltype(vecs)[]
signs = Iterators.product(ntuple(i -> -1:2:1, N)...)
for v in vecs
for sign in signs
push!(list, [v[i] == 0 ? 0.0 : sign[i] * v[i] for i in 1:length(v)])
end
end
return unique(list)
end
function signs2(vecs)
M = length(vecs)
N = length(vecs[1])
nsigns = 2^N
list = [similar(vecs[1]) for i in 1:nsigns*M]
for (i, v) in enumerate(vecs)
for j in 1:nsigns
ctr = copy(j - 1)
ind = j + (i - 1) * nsigns
for k in 1:N
if v[k] != 0.0 && ctr & 0b1 == 1
list[ind][k] = v[k]
else
list[ind][k] = -v[k]
end
ctr = ctr >> 1
end
end
end
unique!(list)
return list
end
function signs3(vecs)
N = length(vecs[1])
signs = Iterators.product(ntuple( i -> (-1, 1), N)...)
return [[sign[i] * vec[i] for i in 1:N]
for vec in vecs for sign in signs
if all(vec[i] != 0 || sign[i] == 1 for i in eachindex(vec))]
end
vctrs = [[0.4; 0.3; 0.2], [0.5; 0.0; -0.0]]
result1 = changesOfSign(vctrs)
@show result1
result2 = signs1(vctrs, Val(length(vctrs[1])))
@show result2
@assert result1 == result2
result2 = signs2(vctrs)
@show result2
@assert result2 == result1
result2 = signs3(vctrs)
@show result2
@assert result2 == result1
@btime changesOfSign(vctrs) setup=(Random.seed!(42); vctrs = [rand(10) for i in 1:10])
@btime signs1(vctrs, Val(length(vctrs[1]))) setup=(Random.seed!(42); vctrs = [rand(10) for i in 1:10])
@btime signs2(vctrs) setup=(Random.seed!(42); vctrs = [rand(10) for i in 1:10])
@btime signs3(vctrs) setup=(Random.seed!(42); vctrs = [rand(10) for i in 1:10])
println()
yielding
result1 = [[-0.4, -0.3, -0.2], [0.4, -0.3, -0.2], [-0.4, 0.3, -0.2], [0.4, 0.3, -0.2], [-0.4, -0.3, 0.2], [0.4, -0.3, 0.2], [-0.4, 0.3, 0.2], [0.4, 0.3, 0.2], [-0.5, 0.0, 0.0], [0.5,
0.0, 0.0]]
result2 = [[-0.4, -0.3, -0.2], [0.4, -0.3, -0.2], [-0.4, 0.3, -0.2], [0.4, 0.3, -0.2], [-0.4, -0.3, 0.2], [0.4, -0.3, 0.2], [-0.4, 0.3, 0.2], [0.4, 0.3, 0.2], [-0.5, 0.0, 0.0], [0.5,
0.0, 0.0]]
result2 = [[-0.4, -0.3, -0.2], [0.4, -0.3, -0.2], [-0.4, 0.3, -0.2], [0.4, 0.3, -0.2], [-0.4, -0.3, 0.2], [0.4, -0.3, 0.2], [-0.4, 0.3, 0.2], [0.4, 0.3, 0.2], [-0.5, -0.0, 0.0], [0.5, -0.0, 0.0]]
result2 = [[-0.4, -0.3, -0.2], [0.4, -0.3, -0.2], [-0.4, 0.3, -0.2], [0.4, 0.3, -0.2], [-0.4, -0.3, 0.2], [0.4, -0.3, 0.2], [-0.4, 0.3, 0.2], [0.4, 0.3, 0.2], [-0.5, 0.0, -0.0], [0.5, 0.0, -0.0]]
1.146 ms (20864 allocations: 5.65 MiB)
3.055 ms (10280 allocations: 2.23 MiB)
3.159 ms (10264 allocations: 1.67 MiB)
803.500 μs (10265 allocations: 1.73 MiB)