AlternateVectors.jl

Peculiar Vector Patterns.
View on GitHub Star

About this Package

AlternateVectors.jl is a Julia package containing some useful array representation for peculiar one dimensional arrays patterns.
It currently contains the following immutable types:

  • AlternateVector: convenient representation for vectors of the form:

[a,b,a,b,a,b...]
  • AlternatePaddedVector: convenient representation for vectors of the form:

[x,a,b,a,b,a,b...,y]

The module is standalone.

Getting Started

AlternateVector

To build a AlternateVector one needs to provide:

  • the value for odd indices

  • the value for even indices

  • the length.

The various values must be of the same type and the length must be greater than one. The way to build an AlternateVector is the following:

using AlternateVectors
value_odd=0.2
value_even=2.3
length_av=7
x_av=AlternateVector(value_odd,value_even,length_av)
7-element AlternateVector{Float64}:
 0.2
 2.3
 0.2
 2.3
 0.2
 2.3
 0.2

AlternatePaddedVector

To build a AlternatePaddedVector one needs to provide:

  • the initial value

  • the value for even indices

  • the value for odd indices

  • the final value

  • the length

The various values must be of the same type and the length must be greater than three. The way to build an AlternatePaddedVector is the following:

using AlternateVectors
initial_value=0.2
value_odd=-0.2
value_even=2.3
final_value=1.3
length_av=7
x_av=AlternatePaddedVector(initial_value,value_even,value_odd,final_value,length_av)
7-element AlternatePaddedVector{Float64}:
  0.2
  2.3
 -0.2
  2.3
 -0.2
  2.3
  1.3

Operation on Alternate Vectors

The following applies:

  • AlternateVector/AlternatePaddedVector is closed under getindex for range of integers.

using AlternateVectors
apv=AlternatePaddedVector(0.2,-2.0,4.0,2.3,70)
z_small=apv[1:7:50]
z_small
8-element AlternatePaddedVector{Float64}:
  0.2
 -2.0
  4.0
 -2.0
  4.0
 -2.0
  4.0
 -2.0
  • Any scalar unary function applied directly to AlternateVectors/AlternatePaddedVector will produce an array of the same type.

using AlternateVectors
av=AlternateVector(0.2,-2.0,10)
z_sin=@. sin(av)
z_sin
10-element AlternateVector{Float64}:
  0.19866933079506122
 -0.9092974268256817
  0.19866933079506122
 -0.9092974268256817
  0.19866933079506122
 -0.9092974268256817
  0.19866933079506122
 -0.9092974268256817
  0.19866933079506122
 -0.9092974268256817

Operation between Alternate Vectors

The following applies:

  • Binary scalar functions between AlternateVector and AlternateVector will produce AlternateVector.

  • Binary scalar functions between AlternatePaddedVector and AlternatePaddedVector will produce AlternatePaddedVector.

  • Binary scalar functions between AlternatePaddedVector and AlternateVector will produce AlternatePaddedVector.

  • Binary scalar functions between AlternatePaddedVector/AlternateVector and any other type deriving from AbstractArray will produce an array of the other type.

using AlternateVectors
x=AlternateVector(0.2,2.3,10)
y=randn(10)
z=AlternatePaddedVector(0.2,-2.0,4.0,2.3,10)
@. sin(x)*y+z
10-element Vector{Float64}:
  0.19888893604862723
 -1.5733118717852563
  4.279736164544295
 -2.047749549765119
  4.089784303301104
 -1.9959892035016813
  4.0333358435156965
 -1.7851575575187602
  4.063226722535128
  1.5689732519190769

Performances Comparison

Here the common usages of the package are tested.

Simple multiplication

using AlternateVectors, BenchmarkTools
n=10_000
x=AlternateVector(0.2,2.3,n)
y=randn(n)
x_c=collect(x)
@btime @. $x*$y;
@btime @. $x_c*$y;
  2.108 μs (3 allocations: 78.19 KiB)
  2.845 μs (3 allocations: 78.19 KiB)

Flipping sign based on index and sum

using AlternateVectors, BenchmarkTools, LinearAlgebra
n=10_000
function f_std_scalar(f_x)
	N=length(f_x)
	sum_z=zero(eltype(f_x))
	for i in 1:N
		w=ifelse(isodd(i),1,-1)
		sum_z+=@views @inbounds w*f_x[i]
	end
	return sum_z
end

function f_std_scalar_2(f_x)
	N=length(f_x)
	sum_z=zero(eltype(f_x))
	for i in 1:N
		if(isodd(i))
			sum_z+=@views @inbounds f_x[i]
		else
			sum_z-=@views @inbounds f_x[i]
		end
	end
	return sum_z
end

function f_std_vec(f_x)
	N=length(f_x)
	idx=1:N
	W=@. ifelse(isodd(idx),1,-1)
	return sum(W.*f_x)
end

function f_std_vec_linear_algebra(f_x)
	N=length(f_x)
	idx=1:N
	W=@. ifelse(isodd(idx),1,-1)
	return dot(W,f_x)
end

function f_apv(f_x)
	N=length(f_x)
	W=AlternateVector(1,-1,N)
	return sum(W.*f_x)
end
x=randn(n)
f_x=@. sin(x)+x*cos(x)
@btime f_std_scalar($f_x);
@btime f_std_scalar_2($f_x);
@btime f_std_vec($f_x);
@btime f_std_vec_linear_algebra($f_x);
@btime f_apv($f_x);
  9.267 μs (0 allocations: 0 bytes)
  9.267 μs (0 allocations: 0 bytes)
  5.827 μs (6 allocations: 156.38 KiB)
  11.751 μs (2 allocations: 78.16 KiB)
  3.460 μs (3 allocations: 78.19 KiB)

Simpson Integration

using AlternateVectors, BenchmarkTools,LinearAlgebra
n2=10_000
function f_simpson_std_scalar(f_x)
	N=length(f_x)
	sum_z=zero(eltype(f_x))
	for i in 1:N
		w=ifelse(i==1,1/3,ifelse(i==N,1/3,4/3))
		sum_z+=@views @inbounds w*f_x[i]
	end
	return sum_z
end

function f_simpson_std_vec(f_x)
	N=length(f_x)
	idx=1:N
	W=@. ifelse(idx==1,1/3,ifelse(idx==N,1/3,4/3))
	return sum(W.*f_x)
end

function f_simpson_std_vec_linear_algebra(f_x)
	N=length(f_x)
	idx=1:N
	W=@. ifelse(idx==1,1/3,ifelse(idx==N,1/3,4/3))
	return dot(W,f_x)
end

function f_simpson_apv(f_x)
	N=length(f_x)
	W=AlternatePaddedVector(1/3,4/3,4/3,1/3,N)
	return sum(W.*f_x)
end

function f_simpson_apv_linear_algebra(f_x)
	N=length(f_x)
	W=AlternatePaddedVector(1/3,4/3,4/3,1/3,N)
	return dot(W,f_x)
end

x2=randn(n2)
f_x2=@. sin(x2)+x2*cos(x2)
@btime f_simpson_std_scalar($f_x2);
@btime f_simpson_std_vec($f_x2);
@btime f_simpson_std_vec_linear_algebra($f_x2);
@btime f_simpson_apv($f_x2);
@btime f_simpson_apv_linear_algebra($f_x2);
  9.267 μs (0 allocations: 0 bytes)
  5.631 μs (6 allocations: 156.38 KiB)
  3.460 μs (3 allocations: 78.19 KiB)
  3.924 μs (3 allocations: 78.19 KiB)
  9.287 μs (0 allocations: 0 bytes)

To be noticed the performance improvements thanks to the usage of AlternatePaddedVector, and to be noticed that the first function proposed is not compatible with the CUDA.jl stack.