vec4_class.f90 Source File


Source Code

Module vec4_class
!! Vector4 class module. Defines a vector4 type (x, y, z, p) and associated operations on vectors and other types.
    use constants, only : wp

    implicit none

    !> not fully implmented vec4 class
    type :: vec4
        !> vec4 components
        real(kind=wp) :: x, y, z, p
        contains

        procedure :: magnitude         => magnitude_fn
        procedure :: length            => length
        !> .dot. operator
        generic   :: operator(.dot.) => vec_dot_vec
        !> Overloaded Division operator
        generic   :: operator(/)     => vec_div_scal_r4, vec_div_scal_r8, vec_div_scal_int
        !> Overloaded Mulitiplication operator
        generic   :: operator(*)     => vec_mult_vec, vec_mult_scal, scal_mult_vec
        !> Overloaded Addition operator
        generic   :: operator(+)     => vec_add_vec, vec_add_scal, scal_add_vec
        !> Overloaded Subtraction operator
        generic   :: operator(-)     => vec_minus_vec, vec_minus_scal, scal_minus_vec

        procedure, pass(a), private :: vec_dot_vec

        procedure, pass(a), private :: vec_div_scal_r4
        procedure, pass(a), private :: vec_div_scal_r8
        procedure, pass(a), private :: vec_div_scal_int

        procedure, pass(a), private :: vec_mult_vec
        procedure, pass(a), private :: vec_mult_scal
        procedure, pass(b), private :: scal_mult_vec

        procedure, pass(a), private :: vec_add_vec
        procedure, pass(a), private :: vec_add_scal
        procedure, pass(b), private :: scal_add_vec

        procedure, pass(a), private :: vec_minus_vec
        procedure, pass(a), private :: vec_minus_scal
        procedure, pass(b), private :: scal_minus_vec

    end type vec4

    interface sin
        !! Vec4 overload of the sin intrinsic 
        module procedure sin_vec
    end interface sin

    interface vec4
        !! Initalise a vec4 from a vec3 and a scalar
        module procedure init_vec4_vector_real
    end interface vec4

    private
    public :: vec4, sin

    contains
        type(vec4) function init_vec4_vector_real(vec, val) result(out)
            !! Initalise vec4 from a vec3 and Scalar
            !! e.g vec4 = [vec3%x, vec3%y, vec3%z, scalar]
            use vector_class
            !> Input vec3
            type(vector),  intent(in) :: vec
            !> Input Scalar
            real(kind=wp), intent(in) :: val

            out%x = vec%x
            out%y = vec%y
            out%z = vec%z
            out%p = val

        end function init_vec4_vector_real

        type(vec4) pure elemental function sin_vec(p)
            !! Sine of a vec4, elementwise
            !> Input vec4
            type(vec4), intent(IN) :: p

            sin_vec = vec4(sin(p%x), sin(p%y), sin(p%z), sin(p%p))

        end function sin_vec

        type(vec4) pure elemental function vec_minus_vec(a, b)
            !! Elementwise vec4 - vec4
            !> Input vec4
            class(vec4), intent(IN) :: a
            !> vec4 to subtract
            type(vec4),  intent(IN) :: b

            vec_minus_vec = vec4(a%x - b%x, a%y - b%y, a%z - b%z, a%p - b%p)

        end function vec_minus_vec

        type(vec4) pure elemental function vec_add_scal(a, b)
            !! Elementwise vec4 + scalar
            !> Input vec4
            class(vec4),     intent(IN) :: a
            !> Scalar to add
            real(kind=wp),   intent(IN) :: b

            vec_add_scal = vec4(a%x + b, a%y + b, a%z + b, a%p + b)

        end function vec_add_scal

        type(vec4) pure elemental function scal_add_vec(a, b)
            !! Elementwise scalar + vec4
            !> Input vec4
            class(vec4),   intent(IN) :: b
            !> Scalar to add
            real(kind=wp), intent(IN) :: a

            scal_add_vec = vec4(b%x + a, b%y + a, b%z + a,  b%p + a)

        end function scal_add_vec

        type(vec4) pure elemental function vec_minus_scal(a, b)
            !! Elementwise vec4 - scalar
            !> Input vec4
            class(vec4),   intent(IN) :: a
            !> Scalar to subtract
            real(kind=wp), intent(IN) :: b

            vec_minus_scal = vec4(a%x - b, a%y - b, a%z - b, a%p - b)

        end function vec_minus_scal

        type(vec4) pure elemental function scal_minus_vec(a, b)
            !! Elementwise Scalar - vec4
            !> Input vec4
            class(vec4),   intent(IN) :: b
            !> Scalar to subtract
            real(kind=wp), intent(IN) :: a

            scal_minus_vec = vec4(a - b%x, a - b%y, a - b%z, a - b%p)

        end function scal_minus_vec

        type(vec4) pure elemental function vec_add_vec(a, b)
            !! Elementwise vec4 + vec4
            !> Input vec4
            class(vec4), intent(IN) :: a
            !> vec4 to add
            type(vec4),  intent(IN) :: b

            vec_add_vec = vec4(a%x + b%x, a%y + b%y, a%z + b%z, a%p + b%p)

        end function vec_add_vec

        pure elemental function vec_dot_vec(a, b) result (dot)
            !! dot product between two vec4s
            !> Input vec4
            class(vec4), intent(IN) :: a
            !> vec4 to dot with
            type(vec4),  intent(IN) :: b

            real(kind=wp) :: dot

            dot = (a%x * b%x) + (a%y * b%y) + (a%z * b%z) + (a%p * b%p)

        end function vec_dot_vec

        type(vec4) pure elemental function vec_mult_vec(a, b)
            !! Elementwise vec4 * vec4
            !> Input vec4
            class(vec4), intent(IN) :: a
            !> vec4 to multiply by
            type(vec4),  intent(IN) :: b

            vec_mult_vec = vec4(a%x * b%x, a%y * b%y, a%z * b%z, a%p * b%p)

        end function vec_mult_vec

        type(vec4) pure elemental function vec_mult_scal(a, b)
            !! Elementwise vec4 * Scalar
            !> Input vec4
            class(vec4),   intent(IN) :: a
            !> Scalar to multiply by
            real(kind=wp), intent(IN) :: b

            vec_mult_scal = vec4(a%x * b, a%y * b, a%z * b, a%p * b)

        end function vec_mult_scal

        type(vec4) pure elemental function scal_mult_vec(a, b)
            !! Elementwise Scalar * vec4
            !> Input vec4
            class(vec4),   intent(IN) :: b
            !> Scalar to multiply by
            real(kind=wp), intent(IN) :: a

            scal_mult_vec = vec4(a * b%x, a * b%y, a * b%z, a * b%p)

        end function scal_mult_vec

        type(vec4) pure elemental function vec_div_scal_r4(a, b)
            !! Elementwise vec4 / Scalar. Scalar is 32-bit float
            use constants, only : sp
        
            !> Input vec4
            class(vec4),   intent(IN) :: a
            !> Scalar to divide by
            real(kind=sp), intent(IN) :: b

            vec_div_scal_r4 = vec4(a%x / b, a%y / b, a%z / b, a%p / b)

        end function vec_div_scal_r4

        type(vec4) pure elemental function vec_div_scal_r8(a, b)
            !! Elementwise vec4 / Scalar. Scalar is 32-bit float
            use constants, only : dp
        
            !> Input vec4
            class(vec4),   intent(IN) :: a
            !> Scalar to divide by
            real(kind=dp), intent(IN) :: b

            vec_div_scal_r8 = vec4(a%x / b, a%y / b, a%z / b, a%p / b)

        end function vec_div_scal_r8

        type(vec4) pure elemental function vec_div_scal_int(a, b)
            !! Elementwise vec4 / Scalar. Scalar is an integer

            !> Input vec4
            class(vec4),   intent(IN) :: a
            !> Scalar to divide by
            integer,     intent(IN) :: b

            vec_div_scal_int = vec4(a%x / real(b, kind=wp), a%y / real(b, kind=wp), a%z / real(b, kind=wp), a%p / real(b, kind=wp))

        end function vec_div_scal_int

        type(vec4) pure elemental function magnitude_fn(this)
            !! Returns the magnitude of a vec4
            class(vec4), intent(in) :: this

            magnitude_fn = this / this%length()

        end function magnitude_fn

        real(kind=wp) pure elemental function length(this)
            !! Returns the length of a vec4
            class(vec4), intent(in) :: this

            length = sqrt(this%x**2 + this%y**2 + this%z**2 + this%p**2)

        end function length
end Module vec4_class