! This automatically generated Fortran wrapper file allows codes
! written in Fortran to be called directly from C and translates all
! C-style arguments into expected Fortran-style arguments (with
! assumed size, local type declarations, etc.).


MODULE C_MATRIX_OPERATIONS
USE ISO_FORTRAN_ENV , ONLY : RT => REAL32
USE IEEE_ARITHMETIC , ONLY : IS_NAN => IEEE_IS_NAN , IS_FINITE => IEEE_IS_FINITE
  IMPLICIT NONE


CONTAINS


  
  SUBROUTINE C_GEMM(OP_A, OP_B, OUT_ROWS, OUT_COLS, INNER_DIM, AB_MULT, A_DIM_1, A_DIM_2, A, A_ROWS, B_DIM_1, B_DIM_2, B, B_ROWS, C&
&_MULT, C_DIM_1, C_DIM_2, C, C_ROWS) BIND(C)
    USE MATRIX_OPERATIONS, ONLY: GEMM
    IMPLICIT NONE
    CHARACTER, INTENT(IN) :: OP_A
    CHARACTER, INTENT(IN) :: OP_B
    INTEGER, INTENT(IN) :: OUT_ROWS
    INTEGER, INTENT(IN) :: OUT_COLS
    INTEGER, INTENT(IN) :: INNER_DIM
    REAL(KIND=RT), INTENT(IN) :: AB_MULT
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: A_DIM_1
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: A_DIM_2
    REAL(KIND=RT), INTENT(IN), DIMENSION(A_DIM_1,A_DIM_2) :: A
    INTEGER, INTENT(IN) :: A_ROWS
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: B_DIM_1
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: B_DIM_2
    REAL(KIND=RT), INTENT(IN), DIMENSION(B_DIM_1,B_DIM_2) :: B
    INTEGER, INTENT(IN) :: B_ROWS
    REAL(KIND=RT), INTENT(IN) :: C_MULT
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: C_DIM_1
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: C_DIM_2
    REAL(KIND=RT), INTENT(OUT), DIMENSION(C_DIM_1,C_DIM_2) :: C
    INTEGER, INTENT(IN) :: C_ROWS
  
    CALL GEMM(OP_A, OP_B, OUT_ROWS, OUT_COLS, INNER_DIM, AB_MULT, A, A_ROWS, B, B_ROWS, C_MULT, C, C_ROWS)
  END SUBROUTINE C_GEMM
  

  
  SUBROUTINE C_RANDOM_UNIT_VECTORS(COLUMN_VECTORS_DIM_1, COLUMN_VECTORS_DIM_2, COLUMN_VECTORS) BIND(C)
    USE MATRIX_OPERATIONS, ONLY: RANDOM_UNIT_VECTORS
    IMPLICIT NONE
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: COLUMN_VECTORS_DIM_1
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: COLUMN_VECTORS_DIM_2
    REAL(KIND=RT), INTENT(OUT), DIMENSION(COLUMN_VECTORS_DIM_1,COLUMN_VECTORS_DIM_2) :: COLUMN_VECTORS
  
    CALL RANDOM_UNIT_VECTORS(COLUMN_VECTORS)
  END SUBROUTINE C_RANDOM_UNIT_VECTORS
  

  
  SUBROUTINE C_ORTHOGONALIZE(A_DIM_1, A_DIM_2, A, LENGTHS_DIM_1, LENGTHS, RANK_PRESENT, RANK, ORDER_PRESENT, ORDER_DIM_1, ORDER, MU&
&LTIPLIERS_PRESENT, MULTIPLIERS_DIM_1, MULTIPLIERS_DIM_2, MULTIPLIERS) BIND(C)
    USE MATRIX_OPERATIONS, ONLY: ORTHOGONALIZE
    IMPLICIT NONE
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: A_DIM_1
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: A_DIM_2
    REAL(KIND=RT), INTENT(INOUT), DIMENSION(A_DIM_1,A_DIM_2) :: A
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: LENGTHS_DIM_1
    REAL(KIND=RT), INTENT(OUT), DIMENSION(LENGTHS_DIM_1) :: LENGTHS
    LOGICAL, INTENT(IN) :: RANK_PRESENT
    INTEGER, INTENT(OUT) :: RANK
    LOGICAL, INTENT(IN) :: ORDER_PRESENT
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: ORDER_DIM_1
    INTEGER, INTENT(OUT), DIMENSION(ORDER_DIM_1) :: ORDER
    LOGICAL, INTENT(IN) :: MULTIPLIERS_PRESENT
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: MULTIPLIERS_DIM_1
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: MULTIPLIERS_DIM_2
    REAL(KIND=RT), INTENT(OUT), DIMENSION(MULTIPLIERS_DIM_1,MULTIPLIERS_DIM_2) :: MULTIPLIERS
  
    IF (RANK_PRESENT) THEN
      IF (ORDER_PRESENT) THEN
        IF (MULTIPLIERS_PRESENT) THEN
          CALL ORTHOGONALIZE(A=A, LENGTHS=LENGTHS, RANK=RANK, ORDER=ORDER, MULTIPLIERS=MULTIPLIERS)
        ELSE
          CALL ORTHOGONALIZE(A=A, LENGTHS=LENGTHS, RANK=RANK, ORDER=ORDER)
        END IF
      ELSE
        IF (MULTIPLIERS_PRESENT) THEN
          CALL ORTHOGONALIZE(A=A, LENGTHS=LENGTHS, RANK=RANK, MULTIPLIERS=MULTIPLIERS)
        ELSE
          CALL ORTHOGONALIZE(A=A, LENGTHS=LENGTHS, RANK=RANK)
        END IF
      END IF
    ELSE
      IF (ORDER_PRESENT) THEN
        IF (MULTIPLIERS_PRESENT) THEN
          CALL ORTHOGONALIZE(A=A, LENGTHS=LENGTHS, ORDER=ORDER, MULTIPLIERS=MULTIPLIERS)
        ELSE
          CALL ORTHOGONALIZE(A=A, LENGTHS=LENGTHS, ORDER=ORDER)
        END IF
      ELSE
        IF (MULTIPLIERS_PRESENT) THEN
          CALL ORTHOGONALIZE(A=A, LENGTHS=LENGTHS, MULTIPLIERS=MULTIPLIERS)
        ELSE
          CALL ORTHOGONALIZE(A=A, LENGTHS=LENGTHS)
        END IF
      END IF
    END IF
  END SUBROUTINE C_ORTHOGONALIZE
  

  
  SUBROUTINE C_SVD(A_DIM_1, A_DIM_2, A, S_DIM_1, S, VT_DIM_1, VT_DIM_2, VT, RANK_PRESENT, RANK, STEPS_PRESENT, STEPS, BIAS_PRESENT,&
& BIAS) BIND(C)
    USE MATRIX_OPERATIONS, ONLY: SVD
    IMPLICIT NONE
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: A_DIM_1
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: A_DIM_2
    REAL(KIND=RT), INTENT(IN), DIMENSION(A_DIM_1,A_DIM_2) :: A
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: S_DIM_1
    REAL(KIND=RT), INTENT(OUT), DIMENSION(S_DIM_1) :: S
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: VT_DIM_1
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: VT_DIM_2
    REAL(KIND=RT), INTENT(OUT), DIMENSION(VT_DIM_1,VT_DIM_2) :: VT
    LOGICAL, INTENT(IN) :: RANK_PRESENT
    INTEGER, INTENT(OUT) :: RANK
    LOGICAL, INTENT(IN) :: STEPS_PRESENT
    INTEGER, INTENT(IN) :: STEPS
    LOGICAL, INTENT(IN) :: BIAS_PRESENT
    REAL(KIND=RT), INTENT(IN) :: BIAS
  
    IF (RANK_PRESENT) THEN
      IF (STEPS_PRESENT) THEN
        IF (BIAS_PRESENT) THEN
          CALL SVD(A=A, S=S, VT=VT, RANK=RANK, STEPS=STEPS, BIAS=BIAS)
        ELSE
          CALL SVD(A=A, S=S, VT=VT, RANK=RANK, STEPS=STEPS)
        END IF
      ELSE
        IF (BIAS_PRESENT) THEN
          CALL SVD(A=A, S=S, VT=VT, RANK=RANK, BIAS=BIAS)
        ELSE
          CALL SVD(A=A, S=S, VT=VT, RANK=RANK)
        END IF
      END IF
    ELSE
      IF (STEPS_PRESENT) THEN
        IF (BIAS_PRESENT) THEN
          CALL SVD(A=A, S=S, VT=VT, STEPS=STEPS, BIAS=BIAS)
        ELSE
          CALL SVD(A=A, S=S, VT=VT, STEPS=STEPS)
        END IF
      ELSE
        IF (BIAS_PRESENT) THEN
          CALL SVD(A=A, S=S, VT=VT, BIAS=BIAS)
        ELSE
          CALL SVD(A=A, S=S, VT=VT)
        END IF
      END IF
    END IF
  END SUBROUTINE C_SVD
  

  
  SUBROUTINE C_RADIALIZE(X_DIM_1, X_DIM_2, X, SHIFT_DIM_1, SHIFT, VECS_DIM_1, VECS_DIM_2, VECS, INVERT_RESULT_PRESENT, INVERT_RESUL&
&T, FLATTEN_PRESENT, FLATTEN, STEPS_PRESENT, STEPS) BIND(C)
    USE MATRIX_OPERATIONS, ONLY: RADIALIZE
    IMPLICIT NONE
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: X_DIM_1
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: X_DIM_2
    REAL(KIND=RT), INTENT(INOUT), DIMENSION(X_DIM_1,X_DIM_2) :: X
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: SHIFT_DIM_1
    REAL(KIND=RT), INTENT(OUT), DIMENSION(SHIFT_DIM_1) :: SHIFT
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: VECS_DIM_1
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: VECS_DIM_2
    REAL(KIND=RT), INTENT(OUT), DIMENSION(VECS_DIM_1,VECS_DIM_2) :: VECS
    LOGICAL, INTENT(IN) :: INVERT_RESULT_PRESENT
    LOGICAL, INTENT(IN) :: INVERT_RESULT
    LOGICAL, INTENT(IN) :: FLATTEN_PRESENT
    LOGICAL, INTENT(IN) :: FLATTEN
    LOGICAL, INTENT(IN) :: STEPS_PRESENT
    INTEGER, INTENT(IN) :: STEPS
  
    IF (INVERT_RESULT_PRESENT) THEN
      IF (FLATTEN_PRESENT) THEN
        IF (STEPS_PRESENT) THEN
          CALL RADIALIZE(X=X, SHIFT=SHIFT, VECS=VECS, INVERT_RESULT=INVERT_RESULT, FLATTEN=FLATTEN, STEPS=STEPS)
        ELSE
          CALL RADIALIZE(X=X, SHIFT=SHIFT, VECS=VECS, INVERT_RESULT=INVERT_RESULT, FLATTEN=FLATTEN)
        END IF
      ELSE
        IF (STEPS_PRESENT) THEN
          CALL RADIALIZE(X=X, SHIFT=SHIFT, VECS=VECS, INVERT_RESULT=INVERT_RESULT, STEPS=STEPS)
        ELSE
          CALL RADIALIZE(X=X, SHIFT=SHIFT, VECS=VECS, INVERT_RESULT=INVERT_RESULT)
        END IF
      END IF
    ELSE
      IF (FLATTEN_PRESENT) THEN
        IF (STEPS_PRESENT) THEN
          CALL RADIALIZE(X=X, SHIFT=SHIFT, VECS=VECS, FLATTEN=FLATTEN, STEPS=STEPS)
        ELSE
          CALL RADIALIZE(X=X, SHIFT=SHIFT, VECS=VECS, FLATTEN=FLATTEN)
        END IF
      ELSE
        IF (STEPS_PRESENT) THEN
          CALL RADIALIZE(X=X, SHIFT=SHIFT, VECS=VECS, STEPS=STEPS)
        ELSE
          CALL RADIALIZE(X=X, SHIFT=SHIFT, VECS=VECS)
        END IF
      END IF
    END IF
  END SUBROUTINE C_RADIALIZE
  

  
  SUBROUTINE C_LEAST_SQUARES(TRANS, A_DIM_1, A_DIM_2, A, B_DIM_1, B_DIM_2, B, X_DIM_1, X_DIM_2, X) BIND(C)
    USE MATRIX_OPERATIONS, ONLY: LEAST_SQUARES
    IMPLICIT NONE
    CHARACTER, INTENT(IN) :: TRANS
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: A_DIM_1
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: A_DIM_2
    REAL(KIND=RT), INTENT(INOUT), DIMENSION(A_DIM_1,A_DIM_2) :: A
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: B_DIM_1
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: B_DIM_2
    REAL(KIND=RT), INTENT(INOUT), DIMENSION(B_DIM_1,B_DIM_2) :: B
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: X_DIM_1
    INTEGER(KIND=SELECTED_INT_KIND(18)), INTENT(IN) :: X_DIM_2
    REAL(KIND=RT), INTENT(OUT), DIMENSION(X_DIM_1,X_DIM_2) :: X
  
    CALL LEAST_SQUARES(TRANS, A, B, X)
  END SUBROUTINE C_LEAST_SQUARES
  
END MODULE C_MATRIX_OPERATIONS

