lno_encode Module Function

module function lno_encode(input, poles, num_inputs, num_modes) result(c)

Encode input through the Laplace basis built from learnable poles.

Forward: y = E(mu) @ u [M, batch] E[m,j] = exp(-mu_m * t_j), t_j = (j-1)/(n_in-1)

left_operand → input u [n_in, batch] right_operand → poles mu [M, 1] output → encoded [M, batch]

Arguments

Type IntentOptional Attributes Name
class(array_type), intent(in), target :: input

Input signal tensor [n_in, batch]

class(array_type), intent(in), target :: poles

Learnable poles [M, 1]

integer, intent(in) :: num_inputs

Input dimension and number of modes

integer, intent(in) :: num_modes

Input dimension and number of modes

Return Value type(array_type), pointer

Encoded output tensor


Source Code

  module function lno_encode( &
       input, poles, num_inputs, num_modes &
  ) result(c)
    !! Encode input through the Laplace basis built from learnable poles.
    !!
    !! Forward:  y = E(mu) @ u   [M, batch]
    !!   E[m,j] = exp(-mu_m * t_j),  t_j = (j-1)/(n_in-1)
    !!
    !! left_operand  → input u  [n_in, batch]
    !! right_operand → poles mu [M, 1]
    !! output        → encoded  [M, batch]
    implicit none

    ! Arguments
    class(array_type), intent(in), target :: input
    !! Input signal tensor [n_in, batch]
    class(array_type), intent(in), target :: poles
    !! Learnable poles [M, 1]
    integer, intent(in) :: num_inputs, num_modes
    !! Input dimension and number of modes
    type(array_type), pointer :: c
    !! Encoded output tensor

    ! Local variables
    integer :: num_samples, m, j
    !! Batch and loop indices
    real(real32) :: t, s
    !! Normalised coordinate and current pole value
    real(real32), allocatable :: E(:,:)  ! [M, n_in]
    !! Encoder basis matrix

    num_samples = size(input%val, 2)

    ! Build encoder basis E [M x n_in]
    allocate(E(num_modes, num_inputs))
    do j = 1, num_inputs
       if(num_inputs .gt. 1)then
          t = real(j-1, real32) / real(num_inputs-1, real32)
       else
          t = 0.0_real32
       end if
       do m = 1, num_modes
          s = poles%val(m, 1)
          E(m, j) = exp(-s * t)
       end do
    end do

    ! Forward: y = E @ u
    c => input%create_result(array_shape=[num_modes, num_samples])
    c%val = matmul(E, input%val)

    deallocate(E)

    ! Store metadata for backward
    allocate(c%indices(2))
    c%indices = [num_inputs, num_modes]

    c%get_partial_left     => get_partial_lno_encode_input
    c%get_partial_right    => get_partial_lno_encode_poles
    c%get_partial_left_val => get_partial_lno_encode_input_val
    c%get_partial_right_val => get_partial_lno_encode_poles_val
    if(input%requires_grad .or. poles%requires_grad)then
       c%requires_grad    = .true.
       c%is_forward       = input%is_forward .or. poles%is_forward
       c%operation        = 'lno_encode'
       c%left_operand     => input
       c%right_operand    => poles
       c%owns_left_operand  = input%is_temporary
       c%owns_right_operand = poles%is_temporary
    end if

  end function lno_encode