
#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/lib.c"
/*
  LAPACK wrapper for Ruby/Numo
    (C) Copyright 2017 by Masahiro TANAKA

  This program is free software.
  NO WARRANTY.
*/

#include <assert.h>
#include <ruby.h>
#include "numo/narray.h"
#include "numo/template.h"
#include "numo_lapack.h"

static ID id_axis;
static ID id_il;
static ID id_itype;
static ID id_iu;
static ID id_jobu;
static ID id_jobvl;
static ID id_jobvr;
static ID id_jobvt;
static ID id_jobz;
static ID id_keepdims;
static ID id_norm;
static ID id_order;
static ID id_range;
static ID id_rcond;
static ID id_trans;
static ID id_uplo;



#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/module.c"
/*
  module definition: Numo::Linalg
*/

#line 6 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/module.c"
static VALUE mLinalg;




#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/module.c"
/*
  module definition: Numo::Linalg::Lapack
*/

#line 6 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/module.c"
static VALUE mLapack;

static VALUE eLapackError;

#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/def_s.c"
#include "numo/types/sfloat.h"
#define CZ 0
#define IS_COMPLEX CZ

#ifndef m_real
#define m_real(x) (x)
#endif


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/lange.c"
#define args_t slange_args_t
#define func_p slange_p

typedef struct {
    int   order;
    char  norm;
} args_t;

static slange_t func_p = 0;

static void
iter_lapack_s_slange(na_loop_t * const lp)
{
    dtype *a;
    rtype *norm;
    int    m, n, lda, tmp;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
    norm = (rtype*)NDL_PTR(lp,1);
    g = (args_t*)(lp->opt_ptr);

    m = NDL_SHAPE(lp,0)[0];
    n = NDL_SHAPE(lp,0)[1];
    SWAP_IFCOL(g->order,m,n);
    lda = NDL_STEP(lp,0) / sizeof(dtype);

    //printf("order=%d norm=%c m=%d n=%d lda=%d\n",g->order,g->norm,m,n,lda);

    *norm = (*func_p)(g->order, g->norm, m, n, a, lda);
}

/*
  @overload slange(a, norm, [order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray).
  @param [String]  norm  Kind of norm: 'M',('1','O'),'I',('F','E')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [Numo::SFloat] returns slange.

SLANGE  returns the value of the one norm,  or the Frobenius norm, or
the  infinity norm,  or the  element of  largest absolute value  of a
real matrix A.

        SLANGE = ( max(abs(A(i,j))), NORM = 'M' or 'm'
                 (
                 ( norm1(A),         NORM = '1', 'O' or 'o'
                 (
                 ( normI(A),         NORM = 'I' or 'i'
                 (
                 ( normF(A),         NORM = 'F', 'f', 'E' or 'e'

where  norm1  denotes the  one norm of a matrix (maximum column sum),
normI  denotes the  infinity norm  of a matrix  (maximum row sum) and
normF  denotes the  Frobenius norm of a matrix (square root of sum of
squares).  Note that  max(abs(A(i,j)))  is not a consistent matrix norm.

*/
static VALUE
lapack_s_slange(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, norm, ans;
    narray_t *na1;
    ndfunc_arg_in_t ain[1] = {{cT,2}};
    ndfunc_arg_out_t aout[1] = {{cRT,0}};
    ndfunc_t ndf = {&iter_lapack_s_slange, NO_LOOP|NDF_EXTRACT, 1, 1, ain, aout};

    args_t g;
    VALUE opts[1] = {Qundef};
    ID kw_table[1] = {id_order};
    VALUE kw_hash = Qnil;

    CHECK_FUNC(func_p,"slange");

    rb_scan_args(argc, argv, "2:", &a, &norm, &kw_hash);
    rb_get_kwargs(kw_hash, kw_table, 0, 1, opts);
    g.order = option_order(opts[0]);
    g.norm  = option_job(norm,'F','F');
    //reduce = nary_reduce_options(Qnil, &opts[1], 1, &a, &ndf);
    //A is DOUBLE PRECISION array, dimension (LDA,N)
    //On entry, the M-by-N matrix A.
    //COPY_OR_CAST_TO(a,cT); // not overwrite
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);

    ans = na_ndloop3(&ndf, &g, 1, a);
    return ans;
}

#undef func_p
#undef args_t


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gesv.c"
/**/
#line 6 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gesv.c"
#define UPLO 0
#define IPIV 1
#define args_t sgesv_args_t
#define func_p sgesv_p

typedef struct {
    int order;
    char uplo;
} args_t;

static sgesv_t sgesv_p = 0;

static void
iter_lapack_s_sgesv(na_loop_t * const lp)
{
    dtype *a, *b;
    int   *info;
    int    n, nrhs;
    int    lda, ldb;
    args_t *g;
#if IPIV
    int *ipiv;
    ipiv = (int*)NDL_PTR(lp,2);
    info = (int*)NDL_PTR(lp,3);
#else
    info = (int*)NDL_PTR(lp,2);
#endif
    a = (dtype*)NDL_PTR(lp,0);
    b = (dtype*)NDL_PTR(lp,1);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[0];
    lda = NDL_STEP(lp,0) / sizeof(dtype);
    if (lp->args[1].ndim == 1) {
        nrhs = 1;
        ldb = (g->order==LAPACK_COL_MAJOR) ? n : 1;
    } else {
        nrhs = NDL_SHAPE(lp,1)[1];
        ldb = NDL_STEP(lp,1) / sizeof(dtype);
    }
    //printf("order=%d n=%d nrhs=%d lda=%d ldb=%d b.ndim=%d\n",
    //       g->order,n,nrhs,lda,ldb,lp->args[1].ndim);
    *info = (*func_p)( g->order, 
                       n, nrhs, a, lda, ipiv, b, ldb );
    CHECK_ERROR(*info);
}

/*
  @overload sgesv(a, b, [order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed, output: lu).
  @param b [Numo::SFloat]  vector (>=1-dimentional NArray, inplace allowed, output: x).
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, b, ipiv, info]] Array<Numo::SFloat, Numo::SFloat, Numo::Int, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the N-by-N coefficient matrix A.
           On exit, the factors L and U from the factorization
           A = P\*L\*U; the unit diagonal elements of L are not stored.

    - **b** -- 
           B is REAL array, dimension (LDB,NRHS)
           On entry, the N-by-NRHS matrix of right hand side matrix B.
           On exit, if INFO = 0, the N-by-NRHS solution matrix X.

    - **ipiv** -- 
           IPIV is INTEGER array, dimension (N)
           The pivot indices that define the permutation matrix P;
           row i of the matrix was interchanged with row IPIV(i).

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value
           > 0:  if INFO = i, U(i,i) is exactly zero.  The factorization
                 has been completed, but the factor U is exactly
                 singular, so the solution could not be computed.

SGESV computes the solution to a real system of linear equations

        A * X = B,

where A is an N-by-N matrix and X and B are N-by-NRHS matrices.
The LU decomposition with partial pivoting and row interchanges is
used to factor A as

        A = P * L * U,

where P is a permutation matrix, L is unit lower triangular, and U is
upper triangular.  The factored form of A is then used to solve the
system of equations A \* X = B.

*/
static VALUE
lapack_s_sgesv(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, b, ans;
    narray_t *na1, *na2;
    size_t n, nb, nrhs;
    ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{OVERWRITE,2}};
    size_t shape[2];
    ndfunc_arg_out_t aout[2] = {{cInt,1,shape},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sgesv, NO_LOOP|NDF_EXTRACT, 2,2, ain,aout};
    args_t g;
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};
    VALUE opts[2] = {Qundef,Qundef};

    CHECK_FUNC(func_p,"sgesv");

    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.order = option_order(opts[0]);
    g.uplo = option_uplo(opts[1]);

    COPY_OR_CAST_TO(a,cT);
    COPY_OR_CAST_TO(b,cT);
    GetNArray(a, na1);
    GetNArray(b, na2);
    CHECK_DIM_GE(na1, 2);
    CHECK_DIM_GE(na2, 1);
    CHECK_SQUARE("matrix a",na1);
    n = COL_SIZE(na1);
    if (NA_NDIM(na2) == 1) {
        ain[1].dim = 1;
        nb = COL_SIZE(na2);
        nrhs = 1;
    } else {
        nb = ROW_SIZE(na2);
        nrhs = COL_SIZE(na2);
    }
    if (n != nb) {
        rb_raise(nary_eShapeError, "matrix dimension mismatch: "
                 "a.col=a.row=%"SZF"u b.row=%"SZF"u", n, nb);
    }
    shape[0] = n;
    shape[1] = nrhs;
#if !IPIV
    ndf.aout++;
    ndf.nout--;
#endif

    ans = na_ndloop3(&ndf, &g, 2, a, b);

#if IPIV
    return rb_ary_concat(rb_assoc_new(a,b),ans);
#else
    return rb_ary_new3(3,a,b,ans);
#endif
}

#undef func_p
#undef args_t
#undef UPLO
#undef IPIV


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gesv.c"
/**/
#line 6 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gesv.c"
#define UPLO 1
#define IPIV 1
#define args_t ssysv_args_t
#define func_p ssysv_p

typedef struct {
    int order;
    char uplo;
} args_t;

static ssysv_t ssysv_p = 0;

static void
iter_lapack_s_ssysv(na_loop_t * const lp)
{
    dtype *a, *b;
    int   *info;
    int    n, nrhs;
    int    lda, ldb;
    args_t *g;
#if IPIV
    int *ipiv;
    ipiv = (int*)NDL_PTR(lp,2);
    info = (int*)NDL_PTR(lp,3);
#else
    info = (int*)NDL_PTR(lp,2);
#endif
    a = (dtype*)NDL_PTR(lp,0);
    b = (dtype*)NDL_PTR(lp,1);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[0];
    lda = NDL_STEP(lp,0) / sizeof(dtype);
    if (lp->args[1].ndim == 1) {
        nrhs = 1;
        ldb = (g->order==LAPACK_COL_MAJOR) ? n : 1;
    } else {
        nrhs = NDL_SHAPE(lp,1)[1];
        ldb = NDL_STEP(lp,1) / sizeof(dtype);
    }
    //printf("order=%d n=%d nrhs=%d lda=%d ldb=%d b.ndim=%d\n",
    //       g->order,n,nrhs,lda,ldb,lp->args[1].ndim);
    *info = (*func_p)( g->order, g->uplo,
                       n, nrhs, a, lda, ipiv, b, ldb );
    CHECK_ERROR(*info);
}

/*
  @overload ssysv(a, b, [uplo:'U', order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed, output: lu).
  @param b [Numo::SFloat]  vector (>=1-dimentional NArray, inplace allowed, output: x).
  @param uplo [String or Symbol]  if 'U': Upper triangle, if 'L': Lower triangle. (default='U')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, b, ipiv, info]] Array<Numo::SFloat, Numo::SFloat, Numo::Int, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the symmetric matrix A.  If UPLO = 'U', the leading
           N-by-N upper triangular part of A contains the upper
           triangular part of the matrix A, and the strictly lower
           triangular part of A is not referenced.  If UPLO = 'L', the
           leading N-by-N lower triangular part of A contains the lower
           triangular part of the matrix A, and the strictly upper
           triangular part of A is not referenced.
           On exit, if INFO = 0, the block diagonal matrix D and the
           multipliers used to obtain the factor U or L from the
           factorization A = U\*D\*U\*\*T or A = L\*D\*L\*\*T as computed by
           SSYTRF.

    - **b** -- 
           B is REAL array, dimension (LDB,NRHS)
           On entry, the N-by-NRHS right hand side matrix B.
           On exit, if INFO = 0, the N-by-NRHS solution matrix X.

    - **ipiv** -- 
           IPIV is INTEGER array, dimension (N)
           Details of the interchanges and the block structure of D, as
           determined by SSYTRF.  If IPIV(k) > 0, then rows and columns
           k and IPIV(k) were interchanged, and D(k,k) is a 1-by-1
           diagonal block.  If UPLO = 'U' and IPIV(k) = IPIV(k-1) < 0,
           then rows and columns k-1 and -IPIV(k) were interchanged and
           D(k-1:k,k-1:k) is a 2-by-2 diagonal block.  If UPLO = 'L' and
           IPIV(k) = IPIV(k+1) < 0, then rows and columns k+1 and
           -IPIV(k) were interchanged and D(k:k+1,k:k+1) is a 2-by-2
           diagonal block.

    - **info** -- 
           INFO is INTEGER
           = 0: successful exit
           < 0: if INFO = -i, the i-th argument had an illegal value
           > 0: if INFO = i, D(i,i) is exactly zero.  The factorization
                has been completed, but the block diagonal matrix D is
                exactly singular, so the solution could not be computed.

SSYSV computes the solution to a real system of linear equations

        A * X = B,

where A is an N-by-N symmetric matrix and X and B are N-by-NRHS
matrices.
The diagonal pivoting method is used to factor A as

        A = U * D * U**T,  if UPLO = 'U', or
        A = L * D * L**T,  if UPLO = 'L',

where U (or L) is a product of permutation and unit upper (lower)
triangular matrices, and D is symmetric and block diagonal with
1-by-1 and 2-by-2 diagonal blocks.  The factored form of A is then
used to solve the system of equations A \* X = B.

*/
static VALUE
lapack_s_ssysv(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, b, ans;
    narray_t *na1, *na2;
    size_t n, nb, nrhs;
    ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{OVERWRITE,2}};
    size_t shape[2];
    ndfunc_arg_out_t aout[2] = {{cInt,1,shape},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_ssysv, NO_LOOP|NDF_EXTRACT, 2,2, ain,aout};
    args_t g;
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};
    VALUE opts[2] = {Qundef,Qundef};

    CHECK_FUNC(func_p,"ssysv");

    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.order = option_order(opts[0]);
    g.uplo = option_uplo(opts[1]);

    COPY_OR_CAST_TO(a,cT);
    COPY_OR_CAST_TO(b,cT);
    GetNArray(a, na1);
    GetNArray(b, na2);
    CHECK_DIM_GE(na1, 2);
    CHECK_DIM_GE(na2, 1);
    CHECK_SQUARE("matrix a",na1);
    n = COL_SIZE(na1);
    if (NA_NDIM(na2) == 1) {
        ain[1].dim = 1;
        nb = COL_SIZE(na2);
        nrhs = 1;
    } else {
        nb = ROW_SIZE(na2);
        nrhs = COL_SIZE(na2);
    }
    if (n != nb) {
        rb_raise(nary_eShapeError, "matrix dimension mismatch: "
                 "a.col=a.row=%"SZF"u b.row=%"SZF"u", n, nb);
    }
    shape[0] = n;
    shape[1] = nrhs;
#if !IPIV
    ndf.aout++;
    ndf.nout--;
#endif

    ans = na_ndloop3(&ndf, &g, 2, a, b);

#if IPIV
    return rb_ary_concat(rb_assoc_new(a,b),ans);
#else
    return rb_ary_new3(3,a,b,ans);
#endif
}

#undef func_p
#undef args_t
#undef UPLO
#undef IPIV


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gesv.c"
/**/
#line 6 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gesv.c"
#define UPLO 1
#define IPIV 0
#define args_t sposv_args_t
#define func_p sposv_p

typedef struct {
    int order;
    char uplo;
} args_t;

static sposv_t sposv_p = 0;

static void
iter_lapack_s_sposv(na_loop_t * const lp)
{
    dtype *a, *b;
    int   *info;
    int    n, nrhs;
    int    lda, ldb;
    args_t *g;
#if IPIV
    int *ipiv;
    ipiv = (int*)NDL_PTR(lp,2);
    info = (int*)NDL_PTR(lp,3);
#else
    info = (int*)NDL_PTR(lp,2);
#endif
    a = (dtype*)NDL_PTR(lp,0);
    b = (dtype*)NDL_PTR(lp,1);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[0];
    lda = NDL_STEP(lp,0) / sizeof(dtype);
    if (lp->args[1].ndim == 1) {
        nrhs = 1;
        ldb = (g->order==LAPACK_COL_MAJOR) ? n : 1;
    } else {
        nrhs = NDL_SHAPE(lp,1)[1];
        ldb = NDL_STEP(lp,1) / sizeof(dtype);
    }
    //printf("order=%d n=%d nrhs=%d lda=%d ldb=%d b.ndim=%d\n",
    //       g->order,n,nrhs,lda,ldb,lp->args[1].ndim);
    *info = (*func_p)( g->order, g->uplo,
                       n, nrhs, a, lda,  b, ldb );
    CHECK_ERROR(*info);
}

/*
  @overload sposv(a, b, [uplo:'U', order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed, output: lu).
  @param b [Numo::SFloat]  vector (>=1-dimentional NArray, inplace allowed, output: x).
  @param uplo [String or Symbol]  if 'U': Upper triangle, if 'L': Lower triangle. (default='U')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, b, info]] Array<Numo::SFloat, Numo::SFloat, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the symmetric matrix A.  If UPLO = 'U', the leading
           N-by-N upper triangular part of A contains the upper
           triangular part of the matrix A, and the strictly lower
           triangular part of A is not referenced.  If UPLO = 'L', the
           leading N-by-N lower triangular part of A contains the lower
           triangular part of the matrix A, and the strictly upper
           triangular part of A is not referenced.
           On exit, if INFO = 0, the factor U or L from the Cholesky
           factorization A = U\*\*T\*U or A = L\*L\*\*T.

    - **b** -- 
           B is REAL array, dimension (LDB,NRHS)
           On entry, the N-by-NRHS right hand side matrix B.
           On exit, if INFO = 0, the N-by-NRHS solution matrix X.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value
           > 0:  if INFO = i, the leading minor of order i of A is not
                 positive definite, so the factorization could not be
                 completed, and the solution has not been computed.

SPOSV computes the solution to a real system of linear equations

        A * X = B,

where A is an N-by-N symmetric positive definite matrix and X and B
are N-by-NRHS matrices.
The Cholesky decomposition is used to factor A as

        A = U**T* U,  if UPLO = 'U', or
        A = L * L**T,  if UPLO = 'L',

where U is an upper triangular matrix and L is a lower triangular
matrix.  The factored form of A is then used to solve the system of
equations A \* X = B.

*/
static VALUE
lapack_s_sposv(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, b, ans;
    narray_t *na1, *na2;
    size_t n, nb, nrhs;
    ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{OVERWRITE,2}};
    size_t shape[2];
    ndfunc_arg_out_t aout[2] = {{cInt,1,shape},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sposv, NO_LOOP|NDF_EXTRACT, 2,2, ain,aout};
    args_t g;
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};
    VALUE opts[2] = {Qundef,Qundef};

    CHECK_FUNC(func_p,"sposv");

    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.order = option_order(opts[0]);
    g.uplo = option_uplo(opts[1]);

    COPY_OR_CAST_TO(a,cT);
    COPY_OR_CAST_TO(b,cT);
    GetNArray(a, na1);
    GetNArray(b, na2);
    CHECK_DIM_GE(na1, 2);
    CHECK_DIM_GE(na2, 1);
    CHECK_SQUARE("matrix a",na1);
    n = COL_SIZE(na1);
    if (NA_NDIM(na2) == 1) {
        ain[1].dim = 1;
        nb = COL_SIZE(na2);
        nrhs = 1;
    } else {
        nb = ROW_SIZE(na2);
        nrhs = COL_SIZE(na2);
    }
    if (n != nb) {
        rb_raise(nary_eShapeError, "matrix dimension mismatch: "
                 "a.col=a.row=%"SZF"u b.row=%"SZF"u", n, nb);
    }
    shape[0] = n;
    shape[1] = nrhs;
#if !IPIV
    ndf.aout++;
    ndf.nout--;
#endif

    ans = na_ndloop3(&ndf, &g, 2, a, b);

#if IPIV
    return rb_ary_concat(rb_assoc_new(a,b),ans);
#else
    return rb_ary_new3(3,a,b,ans);
#endif
}

#undef func_p
#undef args_t
#undef UPLO
#undef IPIV


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gesvd.c"
//
#define SDD 0
#define args_t sgesvd_args_t
#define func_p sgesvd_p

typedef struct {
    int order;
    char jobu, jobvt, jobz;
    rtype *superb;
} args_t;

static sgesvd_t func_p = 0;

static void
iter_lapack_s_sgesvd(na_loop_t * const lp)
{
    dtype *a, *u=0, *vt=0;
    rtype *s;
    int   *info;
    int    m, n, lda, ldu, ldvt, tmp;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
    s = (rtype*)NDL_PTR(lp,1);
    u = (dtype*)NDL_PTR(lp,2);
    vt = (dtype*)NDL_PTR(lp,3);
    info = (int*)NDL_PTR(lp,4);
    g = (args_t*)(lp->opt_ptr);

    m = NDL_SHAPE(lp,0)[0];
    n = NDL_SHAPE(lp,0)[1];
    SWAP_IFCOL(g->order,m,n);
    lda = NDL_STEP(lp,0) / sizeof(dtype);
    ldu = NDL_STEP(lp,2) / sizeof(dtype);
    if (ldu == 0) { ldu = m; } // jobu == 'O' or 'N'
    ldvt = NDL_STEP(lp,3) / sizeof(dtype);
    if (ldvt == 0) { ldvt = n; } // jobvt == 'O' or 'N'

    //printf("order=%d jobu=%c jobvt=%c jobz=%c m=%d n=%d lda=%d ldu=%d ldvt=%d\n",g->order,g->jobu, g->jobvt,g->jobz, m,n,lda,ldu,ldvt);

    /**/
    *info = (*func_p)( g->order, g->jobu, g->jobvt, m, n, a, lda, s,
                       u, ldu, vt, ldvt , g->superb );
    CHECK_ERROR(*info);
}

/*
  @overload sgesvd(a, [jobu:'A', jobvt:'A', order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed if job\*=='O').
  @param jobu [String or Symbol]  If 'A': all M columns of U are returned in array U, If 'S': the first min(m,n) columns of U (the left singular vectors) are returned in the array U, If 'O': the first min(m,n) columns of U (the left singular vectors) are overwritten on the array A, If 'N': no columns of U (no left singular vectors) are computed. (default='A')
  @param jobvt [String or Symbol]  If 'A': all N rows of V\*\*T are returned in the array VT;If 'S': the first min(m,n) rows of V\*\*T (the right singular vectors) are returned in the array VT;If 'O': the first min(m,n) rows of V\*\*T (the right singular vectors) are overwritten on the array A;If 'N': no rows of V\*\*T (no right singular vectors) are computed. (default='A')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[sigma, u, vt, info]] Array<Numo::SFloat, Numo::SFloat, Numo::SFloat, Integer>


    - **u** -- 
           U is REAL array, dimension (LDU,UCOL)
           (LDU,M) if JOBU = 'A' or (LDU,min(M,N)) if JOBU = 'S'.
           If JOBU = 'A', U contains the M-by-M orthogonal matrix U;
           if JOBU = 'S', U contains the first min(m,n) columns of U
           (the left singular vectors, stored columnwise);
           if JOBU = 'N' or 'O', U is not referenced.

    - **vt** -- 
           VT is REAL array, dimension (LDVT,N)
           If JOBVT = 'A', VT contains the N-by-N orthogonal matrix
           V\*\*T;
           if JOBVT = 'S', VT contains the first min(m,n) rows of
           V\*\*T (the right singular vectors, stored rowwise);
           if JOBVT = 'N' or 'O', VT is not referenced.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit.
           < 0:  if INFO = -i, the i-th argument had an illegal value.
           > 0:  if SBDSQR did not converge, INFO specifies how many
                 superdiagonals of an intermediate bidiagonal form B
                 did not converge to zero. See the description of WORK
                 above for details.

SGESVD computes the singular value decomposition (SVD) of a real
M-by-N matrix A, optionally computing the left and/or right singular
vectors. The SVD is written

        A = U * SIGMA * transpose(V)

where SIGMA is an M-by-N matrix which is zero except for its
min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
V is an N-by-N orthogonal matrix.  The diagonal elements of SIGMA
are the singular values of A; they are real and non-negative, and
are returned in descending order.  The first min(m,n) columns of
U and V are the left and right singular vectors of A.
Note that the routine returns V\*\*T, not V.

*/
static VALUE
lapack_s_sgesvd(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#if !SDD
    VALUE tmpbuf;
#endif
    VALUE a, ans;
    int   m, n, min_mn, tmp;
    narray_t *na1;
    size_t shape_s[1], shape_u[2], shape_vt[2];
    ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
    ndfunc_arg_out_t aout[4] = {{cRT,1,shape_s},{cT,2,shape_u},
                                {cT,2,shape_vt},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sgesvd, NO_LOOP|NDF_EXTRACT, 1, 4, ain, aout};

    args_t g;
    VALUE opts[4] = {Qundef,Qundef,Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[4] = {id_order,id_jobu,id_jobvt,id_jobz};

    CHECK_FUNC(func_p,"sgesvd");

    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
    rb_get_kwargs(kw_hash, kw_table, 0, 4, opts);
    g.order = option_order(opts[0]);
#if SDD
    g.jobz = option_job(opts[3],'A','N');
    g.jobu = g.jobvt = g.jobz;
#else
    g.jobu  = option_job(opts[1],'A','N');
    g.jobvt = option_job(opts[2],'A','N');
    if (g.jobu=='O' && g.jobvt=='O') {
        rb_raise(rb_eArgError,"JOBVT and JOBU cannot both be 'O'");
    }
#endif

    if (g.jobu=='O' || g.jobvt=='O') {
        if (CLASS_OF(a) != cT) {
            rb_raise(rb_eTypeError,"type of matrix a is invalid for overwrite");
        }
    } else {
        COPY_OR_CAST_TO(a,cT);
    }

    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
    m = ROW_SIZE(na1);
    n = COL_SIZE(na1);
    SWAP_IFCOL(g.order,m,n);

#if SDD
    if (g.jobz=='O') {
        if (m >= n) { g.jobvt='A';} else { g.jobu='A';}
    }
#endif

    // output S
    shape_s[0] = min_mn = min_(m,n);

    // output U
    switch(g.jobu){
    case 'A':
        shape_u[0] = m;
        shape_u[1] = m;
        break;
    case 'S':
        shape_u[0] = m;
        shape_u[1] = min_mn;
        SWAP_IFCOL(g.order,shape_u[0],shape_u[1]);
        break;
    case 'O':
    case 'N':
        aout[1].dim = 0; // dummy
        break;
    default:
        rb_raise(rb_eArgError,"invalid option: jobu='%c'",g.jobu);
    }
    // output VT
    switch(g.jobvt){
    case 'A':
        shape_vt[0] = n;
        shape_vt[1] = n;
        break;
    case 'S':
        shape_vt[0] = min_mn;
        shape_vt[1] = n;
        SWAP_IFCOL(g.order, shape_vt[0], shape_vt[1]);
        break;
    case 'O':
    case 'N':
        aout[2].dim = 0; // dummy
        break;
    default:
        rb_raise(rb_eArgError,"invalid option: jobvt='%c'",g.jobvt);
    }
#if !SDD
    g.superb = (rtype*)rb_alloc_tmp_buffer(&tmpbuf, min_mn*sizeof(rtype));
#endif

    ans = na_ndloop3(&ndf, &g, 1, a);

#if !SDD
    rb_free_tmp_buffer(&tmpbuf);
#endif

    if (g.jobu=='O')      { RARRAY_ASET(ans,1,a); } else
    if (aout[1].dim == 0) { RARRAY_ASET(ans,1,Qnil); }
    if (g.jobvt=='O')     { RARRAY_ASET(ans,2,a); } else
    if (aout[2].dim == 0) { RARRAY_ASET(ans,2,Qnil); }
    return ans;
}

#undef args_t
#undef func_p
#undef SDD


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gesvd.c"
//
#define SDD 1
#define args_t sgesdd_args_t
#define func_p sgesdd_p

typedef struct {
    int order;
    char jobu, jobvt, jobz;
    rtype *superb;
} args_t;

static sgesdd_t func_p = 0;

static void
iter_lapack_s_sgesdd(na_loop_t * const lp)
{
    dtype *a, *u=0, *vt=0;
    rtype *s;
    int   *info;
    int    m, n, lda, ldu, ldvt, tmp;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
    s = (rtype*)NDL_PTR(lp,1);
    u = (dtype*)NDL_PTR(lp,2);
    vt = (dtype*)NDL_PTR(lp,3);
    info = (int*)NDL_PTR(lp,4);
    g = (args_t*)(lp->opt_ptr);

    m = NDL_SHAPE(lp,0)[0];
    n = NDL_SHAPE(lp,0)[1];
    SWAP_IFCOL(g->order,m,n);
    lda = NDL_STEP(lp,0) / sizeof(dtype);
    ldu = NDL_STEP(lp,2) / sizeof(dtype);
    if (ldu == 0) { ldu = m; } // jobu == 'O' or 'N'
    ldvt = NDL_STEP(lp,3) / sizeof(dtype);
    if (ldvt == 0) { ldvt = n; } // jobvt == 'O' or 'N'

    //printf("order=%d jobu=%c jobvt=%c jobz=%c m=%d n=%d lda=%d ldu=%d ldvt=%d\n",g->order,g->jobu, g->jobvt,g->jobz, m,n,lda,ldu,ldvt);

    /**/
    *info = (*func_p)( g->order, g->jobz, m, n, a, lda, s,
                       u, ldu, vt, ldvt  );
    CHECK_ERROR(*info);
}

/*
  @overload sgesdd(a, [jobz:'A', order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed if job\*=='O').
  @param jobz [String or Symbol]  If 'A':  all M columns of U and all N rows of V\*\*H are returned in the arrays U and VT; If 'S':  the first min(M,N) columns of U and the first min(M,N) rows of V\*\*H are returned in the arrays U and VT;If 'O':  If M >= N, the first N columns of U are overwritten in the array A and all rows of V\*\*H are returned in the array VT; otherwise, all columns of U are returned in the array U and the first M rows of V\*\*H are overwritten in the array A;If 'N':  no columns of U or rows of V\*\*H are computed. (default='A')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[sigma, u, vt, info]] Array<Numo::SFloat, Numo::SFloat, Numo::SFloat, Integer>


    - **u** -- 
           U is REAL array, dimension (LDU,UCOL)
           UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M < N;
           UCOL = min(M,N) if JOBZ = 'S'.
           If JOBZ = 'A' or JOBZ = 'O' and M < N, U contains the M-by-M
           orthogonal matrix U;
           if JOBZ = 'S', U contains the first min(M,N) columns of U
           (the left singular vectors, stored columnwise);
           if JOBZ = 'O' and M >= N, or JOBZ = 'N', U is not referenced.

    - **vt** -- 
           VT is REAL array, dimension (LDVT,N)
           If JOBZ = 'A' or JOBZ = 'O' and M >= N, VT contains the
           N-by-N orthogonal matrix V\*\*T;
           if JOBZ = 'S', VT contains the first min(M,N) rows of
           V\*\*T (the right singular vectors, stored rowwise);
           if JOBZ = 'O' and M < N, or JOBZ = 'N', VT is not referenced.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit.
           < 0:  if INFO = -i, the i-th argument had an illegal value.
           > 0:  SBDSDC did not converge, updating process failed.

SGESDD computes the singular value decomposition (SVD) of a real
M-by-N matrix A, optionally computing the left and right singular
vectors.  If singular vectors are desired, it uses a
divide-and-conquer algorithm.
The SVD is written

        A = U * SIGMA * transpose(V)

where SIGMA is an M-by-N matrix which is zero except for its
min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
V is an N-by-N orthogonal matrix.  The diagonal elements of SIGMA
are the singular values of A; they are real and non-negative, and
are returned in descending order.  The first min(m,n) columns of
U and V are the left and right singular vectors of A.
Note that the routine returns VT = V\*\*T, not V.
The divide and conquer algorithm makes very mild assumptions about
floating point arithmetic. It will work on machines with a guard
digit in add/subtract, or on those binary machines without guard
digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
Cray-2. It could conceivably fail on hexadecimal or decimal machines
without guard digits, but we know of none.

*/
static VALUE
lapack_s_sgesdd(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#if !SDD
    VALUE tmpbuf;
#endif
    VALUE a, ans;
    int   m, n, min_mn, tmp;
    narray_t *na1;
    size_t shape_s[1], shape_u[2], shape_vt[2];
    ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
    ndfunc_arg_out_t aout[4] = {{cRT,1,shape_s},{cT,2,shape_u},
                                {cT,2,shape_vt},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sgesdd, NO_LOOP|NDF_EXTRACT, 1, 4, ain, aout};

    args_t g;
    VALUE opts[4] = {Qundef,Qundef,Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[4] = {id_order,id_jobu,id_jobvt,id_jobz};

    CHECK_FUNC(func_p,"sgesdd");

    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
    rb_get_kwargs(kw_hash, kw_table, 0, 4, opts);
    g.order = option_order(opts[0]);
#if SDD
    g.jobz = option_job(opts[3],'A','N');
    g.jobu = g.jobvt = g.jobz;
#else
    g.jobu  = option_job(opts[1],'A','N');
    g.jobvt = option_job(opts[2],'A','N');
    if (g.jobu=='O' && g.jobvt=='O') {
        rb_raise(rb_eArgError,"JOBVT and JOBU cannot both be 'O'");
    }
#endif

    if (g.jobu=='O' || g.jobvt=='O') {
        if (CLASS_OF(a) != cT) {
            rb_raise(rb_eTypeError,"type of matrix a is invalid for overwrite");
        }
    } else {
        COPY_OR_CAST_TO(a,cT);
    }

    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
    m = ROW_SIZE(na1);
    n = COL_SIZE(na1);
    SWAP_IFCOL(g.order,m,n);

#if SDD
    if (g.jobz=='O') {
        if (m >= n) { g.jobvt='A';} else { g.jobu='A';}
    }
#endif

    // output S
    shape_s[0] = min_mn = min_(m,n);

    // output U
    switch(g.jobu){
    case 'A':
        shape_u[0] = m;
        shape_u[1] = m;
        break;
    case 'S':
        shape_u[0] = m;
        shape_u[1] = min_mn;
        SWAP_IFCOL(g.order,shape_u[0],shape_u[1]);
        break;
    case 'O':
    case 'N':
        aout[1].dim = 0; // dummy
        break;
    default:
        rb_raise(rb_eArgError,"invalid option: jobu='%c'",g.jobu);
    }
    // output VT
    switch(g.jobvt){
    case 'A':
        shape_vt[0] = n;
        shape_vt[1] = n;
        break;
    case 'S':
        shape_vt[0] = min_mn;
        shape_vt[1] = n;
        SWAP_IFCOL(g.order, shape_vt[0], shape_vt[1]);
        break;
    case 'O':
    case 'N':
        aout[2].dim = 0; // dummy
        break;
    default:
        rb_raise(rb_eArgError,"invalid option: jobvt='%c'",g.jobvt);
    }
#if !SDD
    g.superb = (rtype*)rb_alloc_tmp_buffer(&tmpbuf, min_mn*sizeof(rtype));
#endif

    ans = na_ndloop3(&ndf, &g, 1, a);

#if !SDD
    rb_free_tmp_buffer(&tmpbuf);
#endif

    if (g.jobu=='O')      { RARRAY_ASET(ans,1,a); } else
    if (aout[1].dim == 0) { RARRAY_ASET(ans,1,Qnil); }
    if (g.jobvt=='O')     { RARRAY_ASET(ans,2,a); } else
    if (aout[2].dim == 0) { RARRAY_ASET(ans,2,Qnil); }
    return ans;
}

#undef args_t
#undef func_p
#undef SDD


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gels.c"
/**/
#line 7 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gels.c"
#define LSS 0
#define LSD 0
#define LSY 0
#define args_t sgels_args_t
#define func_p sgels_p

typedef struct {
    int   order;
    char  trans;
    rtype rcond;
} args_t;

static sgels_t func_p = 0;

static void
iter_lapack_s_sgels(na_loop_t * const lp)
{
    dtype *a, *b;
    int   *info;
    int    m, n, nb, nrhs, lda, ldb, tmp;
    args_t *g;
#if LSS
    
    rtype *s; // or jpvt
    int   *rank;
#endif

    a = (dtype*)NDL_PTR(lp,0);
    b = (dtype*)NDL_PTR(lp,1);
#if LSS
    s = (rtype*)NDL_PTR(lp,2);
    rank = (int*)NDL_PTR(lp,3);
#endif
    info = (int*)NDL_PTR(lp,2+LSS*2);
    g = (args_t*)(lp->opt_ptr);

    m = NDL_SHAPE(lp,0)[0];
    n = NDL_SHAPE(lp,0)[1];
    SWAP_IFCOL(g->order,m,n);
    lda = NDL_STEP(lp,0) / sizeof(dtype);

    if (lp->args[1].ndim == 1) {
        nrhs = 1;
        nb = NDL_SHAPE(lp,1)[0];
        ldb = (g->order==LAPACK_COL_MAJOR) ? nb : 1;
    } else {
        nb = NDL_SHAPE(lp,1)[0];
        nrhs = NDL_SHAPE(lp,1)[1];
        ldb = nrhs;
        SWAP_IFCOL(g->order,nb,nrhs);
    }

    //printf("order=%d trans=%c m=%d n=%d nb=%d nrhs=%d lda=%d ldb=%d\n",g->order,g->trans,m,n,nb,nrhs,lda,ldb);

#if LSS
    *info = (*func_p)(g->order, m, n, nrhs, a, lda, b, ldb, s, g->rcond, rank);
#else
    *info = (*func_p)(g->order, g->trans, m, n, nrhs, a, lda, b, ldb);
#endif
    CHECK_ERROR(*info);
}

/*

  @overload sgels(a, b, trans:'N', order:'R')
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param b [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, b, info]] Array<Numo::SFloat, Numo::SFloat, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the M-by-N matrix A.
           On exit,
             if M >= N, A is overwritten by details of its QR
                        factorization as returned by SGEQRF;
             if M <  N, A is overwritten by details of its LQ
                        factorization as returned by SGELQF.

    - **b** -- 
           B is REAL array, dimension (LDB,NRHS)
           On entry, the matrix B of right hand side vectors, stored
           columnwise; B is M-by-NRHS if TRANS = 'N', or N-by-NRHS
           if TRANS = 'T'.
           On exit, if INFO = 0, B is overwritten by the solution
           vectors, stored columnwise:
           if TRANS = 'N' and m >= n, rows 1 to n of B contain the least
           squares solution vectors; the residual sum of squares for the
           solution in each column is given by the sum of squares of
           elements N+1 to M in that column;
           if TRANS = 'N' and m < n, rows 1 to N of B contain the
           minimum norm solution vectors;
           if TRANS = 'T' and m >= n, rows 1 to M of B contain the
           minimum norm solution vectors;
           if TRANS = 'T' and m < n, rows 1 to M of B contain the
           least squares solution vectors; the residual sum of squares
           for the solution in each column is given by the sum of
           squares of elements M+1 to N in that column.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value
           > 0:  if INFO =  i, the i-th diagonal element of the
                 triangular factor of A is zero, so that A does not have
                 full rank; the least squares solution could not be
                 computed.

SGELS solves overdetermined or underdetermined real linear systems
involving an M-by-N matrix A, or its transpose, using a QR or LQ
factorization of A.  It is assumed that A has full rank.
The following options are provided:

1. If TRANS = 'N' and m >= n:  find the least squares solution of
   an overdetermined system, i.e., solve the least squares problem
                minimize || B - A*X ||.

2. If TRANS = 'N' and m < n:  find the minimum norm solution of
   an underdetermined system A \* X = B.

3. If TRANS = 'T' and m >= n:  find the minimum norm solution of
   an underdetermined system A\*\*T \* X = B.

4. If TRANS = 'T' and m < n:  find the least squares solution of
   an overdetermined system, i.e., solve the least squares problem
                minimize || B - A**T * X ||.

Several right hand side vectors b and solution vectors x can be
handled in a single call; they are stored as the columns of the
M-by-NRHS right hand side matrix B and the N-by-NRHS solution
matrix X.

*/
static VALUE
lapack_s_sgels(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, b, ans;
    int   m, n, nb, nrhs, tmp;
    int   max_mn;
    narray_t *na1, *na2;
#if LSY
    narray_t *na3;
    VALUE jpvt;
#endif
#if LSS
    size_t shape_s[1];
#endif
    /**/
    ndfunc_arg_in_t ain[2+LSS] = {{OVERWRITE,2},{OVERWRITE,2}};
    ndfunc_arg_out_t aout[1+LSS*2] = {{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sgels, NO_LOOP|NDF_EXTRACT, 2, 1+LSS*2, ain, aout};

    args_t g;
    VALUE opts[3] = {Qundef,Qundef,Qundef};
    ID kw_table[3] = {id_order,id_trans,id_rcond};
    VALUE kw_hash = Qnil;

    CHECK_FUNC(func_p,"sgels");

#if LSY
    rb_scan_args(argc, argv, "3:", &a, &b, &jpvt, &kw_hash);
#else
    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
#endif
    rb_get_kwargs(kw_hash, kw_table, 0, 3, opts);
    g.order = option_order(opts[0]);
#if LSS
    g.rcond = NUM2DBL(option_value(opts[2],DBL2NUM(-1)));
#else
    g.trans = option_trans(opts[1]);
#endif

    //A is DOUBLE PRECISION array, dimension (LDA,N)
    //On entry, the M-by-N matrix A.
    COPY_OR_CAST_TO(a,cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);

    //B is DOUBLE PRECISION array, dimension (LDB,NRHS)
    //B is M-by-NRHS if TRANS = 'N'
    //     N-by-NRHS if TRANS = 'T'
    COPY_OR_CAST_TO(b,cT);
    GetNArray(b, na2);
    CHECK_DIM_GE(na2, 1);

    //The number of rows of the matrix A.
    m = ROW_SIZE(na1);
    //The number of columns of the matrix A.
    n = COL_SIZE(na1);
    max_mn = (m > n) ? m : n;
    SWAP_IFCOL(g.order,m,n);

#if LSY
    ndf.nin++;
    ndf.nout--;
    ndf.aout++;
    COPY_OR_CAST_TO(jpvt,cInt);
    GetNArray(jpvt, na3);
    CHECK_DIM_GE(na3, 1);
    { int jpvt_sz = COL_SIZE(na3);
      CHECK_INT_EQ("jpvt_size",jpvt_sz,"n",n);
    }
#elif LSS
    shape_s[0] = (m < n) ? m : n;
#endif

    //The number of columns of the matrix B.
    if (na2->ndim == 1) {
        ain[1].dim = 1; // reduce dimension
        nb = COL_SIZE(na2);
        nrhs = 1;
    } else {
        //The number of rows of the matrix B.
        nb = ROW_SIZE(na2);
        nrhs = COL_SIZE(na2);
        SWAP_IFCOL(g.order,nb,nrhs);
    }
    if (nb < max_mn) {
        rb_raise(nary_eShapeError,
                 "ldb should be >= max(m,n): ldb=%d m=%d n=%d",nb,m,n);
    }

    // ndloop
#if LSY
    ans = na_ndloop3(&ndf, &g, 3, a, b, jpvt);
#else
    ans = na_ndloop3(&ndf, &g, 2, a, b);
#endif

    // return
#if LSY
    return rb_ary_concat(rb_ary_new3(3,a,b,jpvt),ans);
#elif LSD
    rb_ary_unshift(ans,b); return ans;
#elif LSS
    return rb_ary_concat(rb_ary_new3(2,a,b),ans);
#else
    return rb_ary_new3(3,a,b,ans);
#endif
}

#undef func_p
#undef args_t
#undef LSS
#undef LSD
#undef LSY


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gels.c"
/**/
#line 7 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gels.c"
#define LSS 1
#define LSD 0
#define LSY 0
#define args_t sgelss_args_t
#define func_p sgelss_p

typedef struct {
    int   order;
    char  trans;
    rtype rcond;
} args_t;

static sgelss_t func_p = 0;

static void
iter_lapack_s_sgelss(na_loop_t * const lp)
{
    dtype *a, *b;
    int   *info;
    int    m, n, nb, nrhs, lda, ldb, tmp;
    args_t *g;
#if LSS
    
    rtype *s; // or jpvt
    int   *rank;
#endif

    a = (dtype*)NDL_PTR(lp,0);
    b = (dtype*)NDL_PTR(lp,1);
#if LSS
    s = (rtype*)NDL_PTR(lp,2);
    rank = (int*)NDL_PTR(lp,3);
#endif
    info = (int*)NDL_PTR(lp,2+LSS*2);
    g = (args_t*)(lp->opt_ptr);

    m = NDL_SHAPE(lp,0)[0];
    n = NDL_SHAPE(lp,0)[1];
    SWAP_IFCOL(g->order,m,n);
    lda = NDL_STEP(lp,0) / sizeof(dtype);

    if (lp->args[1].ndim == 1) {
        nrhs = 1;
        nb = NDL_SHAPE(lp,1)[0];
        ldb = (g->order==LAPACK_COL_MAJOR) ? nb : 1;
    } else {
        nb = NDL_SHAPE(lp,1)[0];
        nrhs = NDL_SHAPE(lp,1)[1];
        ldb = nrhs;
        SWAP_IFCOL(g->order,nb,nrhs);
    }

    //printf("order=%d trans=%c m=%d n=%d nb=%d nrhs=%d lda=%d ldb=%d\n",g->order,g->trans,m,n,nb,nrhs,lda,ldb);

#if LSS
    *info = (*func_p)(g->order, m, n, nrhs, a, lda, b, ldb, s, g->rcond, rank);
#else
    *info = (*func_p)(g->order, g->trans, m, n, nrhs, a, lda, b, ldb);
#endif
    CHECK_ERROR(*info);
}

/*

  @overload sgelss(a, b, rcond:-1, order:'R')
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param b [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param [Float] rcond  RCOND is used to determine the effective rank of A. Singular values S(i) <= RCOND*S(1) are treated as zero. If RCOND < 0, machine precision is used instead.
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, b, s, rank, info]] Array<Numo::SFloat, Numo::SFloat, Numo::SFloat, Integer, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the M-by-N matrix A.
           On exit, the first min(m,n) rows of A are overwritten with
           its right singular vectors, stored rowwise.

    - **b** -- 
           B is REAL array, dimension (LDB,NRHS)
           On entry, the M-by-NRHS right hand side matrix B.
           On exit, B is overwritten by the N-by-NRHS solution
           matrix X.  If m >= n and RANK = n, the residual
           sum-of-squares for the solution in the i-th column is given
           by the sum of squares of elements n+1:m in that column.

    - **s** -- 
           S is REAL array, dimension (min(M,N))
           The singular values of A in decreasing order.
           The condition number of A in the 2-norm = S(1)/S(min(m,n)).

    - **rank** -- 
           RANK is INTEGER
           The effective rank of A, i.e., the number of singular values
           which are greater than RCOND\*S(1).

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value.
           > 0:  the algorithm for computing the SVD failed to converge;
                 if INFO = i, i off-diagonal elements of an intermediate
                 bidiagonal form did not converge to zero.

SGELSS computes the minimum norm solution to a real linear least
squares problem:
Minimize 2-norm(| b - A\*x |).
using the singular value decomposition (SVD) of A. A is an M-by-N
matrix which may be rank-deficient.
Several right hand side vectors b and solution vectors x can be
handled in a single call; they are stored as the columns of the
M-by-NRHS right hand side matrix B and the N-by-NRHS solution matrix
X.
The effective rank of A is determined by treating as zero those
singular values which are less than RCOND times the largest singular
value.

*/
static VALUE
lapack_s_sgelss(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, b, ans;
    int   m, n, nb, nrhs, tmp;
    int   max_mn;
    narray_t *na1, *na2;
#if LSY
    narray_t *na3;
    VALUE jpvt;
#endif
#if LSS
    size_t shape_s[1];
#endif
    /**/
    ndfunc_arg_in_t ain[2+LSS] = {{OVERWRITE,2},{OVERWRITE,2},{cInt,1}};
    ndfunc_arg_out_t aout[1+LSS*2] = {{cT,1,shape_s},{cInt,0},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sgelss, NO_LOOP|NDF_EXTRACT, 2, 1+LSS*2, ain, aout};

    args_t g;
    VALUE opts[3] = {Qundef,Qundef,Qundef};
    ID kw_table[3] = {id_order,id_trans,id_rcond};
    VALUE kw_hash = Qnil;

    CHECK_FUNC(func_p,"sgelss");

#if LSY
    rb_scan_args(argc, argv, "3:", &a, &b, &jpvt, &kw_hash);
#else
    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
#endif
    rb_get_kwargs(kw_hash, kw_table, 0, 3, opts);
    g.order = option_order(opts[0]);
#if LSS
    g.rcond = NUM2DBL(option_value(opts[2],DBL2NUM(-1)));
#else
    g.trans = option_trans(opts[1]);
#endif

    //A is DOUBLE PRECISION array, dimension (LDA,N)
    //On entry, the M-by-N matrix A.
    COPY_OR_CAST_TO(a,cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);

    //B is DOUBLE PRECISION array, dimension (LDB,NRHS)
    //B is M-by-NRHS if TRANS = 'N'
    //     N-by-NRHS if TRANS = 'T'
    COPY_OR_CAST_TO(b,cT);
    GetNArray(b, na2);
    CHECK_DIM_GE(na2, 1);

    //The number of rows of the matrix A.
    m = ROW_SIZE(na1);
    //The number of columns of the matrix A.
    n = COL_SIZE(na1);
    max_mn = (m > n) ? m : n;
    SWAP_IFCOL(g.order,m,n);

#if LSY
    ndf.nin++;
    ndf.nout--;
    ndf.aout++;
    COPY_OR_CAST_TO(jpvt,cInt);
    GetNArray(jpvt, na3);
    CHECK_DIM_GE(na3, 1);
    { int jpvt_sz = COL_SIZE(na3);
      CHECK_INT_EQ("jpvt_size",jpvt_sz,"n",n);
    }
#elif LSS
    shape_s[0] = (m < n) ? m : n;
#endif

    //The number of columns of the matrix B.
    if (na2->ndim == 1) {
        ain[1].dim = 1; // reduce dimension
        nb = COL_SIZE(na2);
        nrhs = 1;
    } else {
        //The number of rows of the matrix B.
        nb = ROW_SIZE(na2);
        nrhs = COL_SIZE(na2);
        SWAP_IFCOL(g.order,nb,nrhs);
    }
    if (nb < max_mn) {
        rb_raise(nary_eShapeError,
                 "ldb should be >= max(m,n): ldb=%d m=%d n=%d",nb,m,n);
    }

    // ndloop
#if LSY
    ans = na_ndloop3(&ndf, &g, 3, a, b, jpvt);
#else
    ans = na_ndloop3(&ndf, &g, 2, a, b);
#endif

    // return
#if LSY
    return rb_ary_concat(rb_ary_new3(3,a,b,jpvt),ans);
#elif LSD
    rb_ary_unshift(ans,b); return ans;
#elif LSS
    return rb_ary_concat(rb_ary_new3(2,a,b),ans);
#else
    return rb_ary_new3(3,a,b,ans);
#endif
}

#undef func_p
#undef args_t
#undef LSS
#undef LSD
#undef LSY


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gels.c"
/**/
#line 7 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gels.c"
#define LSS 1
#define LSD 1
#define LSY 0
#define args_t sgelsd_args_t
#define func_p sgelsd_p

typedef struct {
    int   order;
    char  trans;
    rtype rcond;
} args_t;

static sgelsd_t func_p = 0;

static void
iter_lapack_s_sgelsd(na_loop_t * const lp)
{
    dtype *a, *b;
    int   *info;
    int    m, n, nb, nrhs, lda, ldb, tmp;
    args_t *g;
#if LSS
    
    rtype *s; // or jpvt
    int   *rank;
#endif

    a = (dtype*)NDL_PTR(lp,0);
    b = (dtype*)NDL_PTR(lp,1);
#if LSS
    s = (rtype*)NDL_PTR(lp,2);
    rank = (int*)NDL_PTR(lp,3);
#endif
    info = (int*)NDL_PTR(lp,2+LSS*2);
    g = (args_t*)(lp->opt_ptr);

    m = NDL_SHAPE(lp,0)[0];
    n = NDL_SHAPE(lp,0)[1];
    SWAP_IFCOL(g->order,m,n);
    lda = NDL_STEP(lp,0) / sizeof(dtype);

    if (lp->args[1].ndim == 1) {
        nrhs = 1;
        nb = NDL_SHAPE(lp,1)[0];
        ldb = (g->order==LAPACK_COL_MAJOR) ? nb : 1;
    } else {
        nb = NDL_SHAPE(lp,1)[0];
        nrhs = NDL_SHAPE(lp,1)[1];
        ldb = nrhs;
        SWAP_IFCOL(g->order,nb,nrhs);
    }

    //printf("order=%d trans=%c m=%d n=%d nb=%d nrhs=%d lda=%d ldb=%d\n",g->order,g->trans,m,n,nb,nrhs,lda,ldb);

#if LSS
    *info = (*func_p)(g->order, m, n, nrhs, a, lda, b, ldb, s, g->rcond, rank);
#else
    *info = (*func_p)(g->order, g->trans, m, n, nrhs, a, lda, b, ldb);
#endif
    CHECK_ERROR(*info);
}

/*

  @overload sgelsd(a, b, rcond:-1, order:'R')
  @param b [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param [Float] rcond  RCOND is used to determine the effective rank of A. Singular values S(i) <= RCOND*S(1) are treated as zero. If RCOND < 0, machine precision is used instead.
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[b, s, rank, info]] Array<Numo::SFloat, Numo::SFloat, Integer, Integer>

    - **b** -- 
           B is REAL array, dimension (LDB,NRHS)
           On entry, the M-by-NRHS right hand side matrix B.
           On exit, B is overwritten by the N-by-NRHS solution
           matrix X.  If m >= n and RANK = n, the residual
           sum-of-squares for the solution in the i-th column is given
           by the sum of squares of elements n+1:m in that column.

    - **s** -- 
           S is REAL array, dimension (min(M,N))
           The singular values of A in decreasing order.
           The condition number of A in the 2-norm = S(1)/S(min(m,n)).

    - **rank** -- 
           RANK is INTEGER
           The effective rank of A, i.e., the number of singular values
           which are greater than RCOND\*S(1).

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value.
           > 0:  the algorithm for computing the SVD failed to converge;
                 if INFO = i, i off-diagonal elements of an intermediate
                 bidiagonal form did not converge to zero.

SGELSD computes the minimum-norm solution to a real linear least
squares problem:

        minimize 2-norm(| b - A*x |)

using the singular value decomposition (SVD) of A. A is an M-by-N
matrix which may be rank-deficient.
Several right hand side vectors b and solution vectors x can be
handled in a single call; they are stored as the columns of the
M-by-NRHS right hand side matrix B and the N-by-NRHS solution
matrix X.
The problem is solved in three steps:

(1) Reduce the coefficient matrix A to bidiagonal form with
    Householder transformations, reducing the original problem
    into a "bidiagonal least squares problem" (BLS)

(2) Solve the BLS using a divide and conquer approach.

(3) Apply back all the Householder transformations to solve
    the original least squares problem.

The effective rank of A is determined by treating as zero those
singular values which are less than RCOND times the largest singular
value.
The divide and conquer algorithm makes very mild assumptions about
floating point arithmetic. It will work on machines with a guard
digit in add/subtract, or on those binary machines without guard
digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
Cray-2. It could conceivably fail on hexadecimal or decimal machines
without guard digits, but we know of none.

*/
static VALUE
lapack_s_sgelsd(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, b, ans;
    int   m, n, nb, nrhs, tmp;
    int   max_mn;
    narray_t *na1, *na2;
#if LSY
    narray_t *na3;
    VALUE jpvt;
#endif
#if LSS
    size_t shape_s[1];
#endif
    /**/
    ndfunc_arg_in_t ain[2+LSS] = {{OVERWRITE,2},{OVERWRITE,2},{cInt,1}};
    ndfunc_arg_out_t aout[1+LSS*2] = {{cT,1,shape_s},{cInt,0},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sgelsd, NO_LOOP|NDF_EXTRACT, 2, 1+LSS*2, ain, aout};

    args_t g;
    VALUE opts[3] = {Qundef,Qundef,Qundef};
    ID kw_table[3] = {id_order,id_trans,id_rcond};
    VALUE kw_hash = Qnil;

    CHECK_FUNC(func_p,"sgelsd");

#if LSY
    rb_scan_args(argc, argv, "3:", &a, &b, &jpvt, &kw_hash);
#else
    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
#endif
    rb_get_kwargs(kw_hash, kw_table, 0, 3, opts);
    g.order = option_order(opts[0]);
#if LSS
    g.rcond = NUM2DBL(option_value(opts[2],DBL2NUM(-1)));
#else
    g.trans = option_trans(opts[1]);
#endif

    //A is DOUBLE PRECISION array, dimension (LDA,N)
    //On entry, the M-by-N matrix A.
    COPY_OR_CAST_TO(a,cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);

    //B is DOUBLE PRECISION array, dimension (LDB,NRHS)
    //B is M-by-NRHS if TRANS = 'N'
    //     N-by-NRHS if TRANS = 'T'
    COPY_OR_CAST_TO(b,cT);
    GetNArray(b, na2);
    CHECK_DIM_GE(na2, 1);

    //The number of rows of the matrix A.
    m = ROW_SIZE(na1);
    //The number of columns of the matrix A.
    n = COL_SIZE(na1);
    max_mn = (m > n) ? m : n;
    SWAP_IFCOL(g.order,m,n);

#if LSY
    ndf.nin++;
    ndf.nout--;
    ndf.aout++;
    COPY_OR_CAST_TO(jpvt,cInt);
    GetNArray(jpvt, na3);
    CHECK_DIM_GE(na3, 1);
    { int jpvt_sz = COL_SIZE(na3);
      CHECK_INT_EQ("jpvt_size",jpvt_sz,"n",n);
    }
#elif LSS
    shape_s[0] = (m < n) ? m : n;
#endif

    //The number of columns of the matrix B.
    if (na2->ndim == 1) {
        ain[1].dim = 1; // reduce dimension
        nb = COL_SIZE(na2);
        nrhs = 1;
    } else {
        //The number of rows of the matrix B.
        nb = ROW_SIZE(na2);
        nrhs = COL_SIZE(na2);
        SWAP_IFCOL(g.order,nb,nrhs);
    }
    if (nb < max_mn) {
        rb_raise(nary_eShapeError,
                 "ldb should be >= max(m,n): ldb=%d m=%d n=%d",nb,m,n);
    }

    // ndloop
#if LSY
    ans = na_ndloop3(&ndf, &g, 3, a, b, jpvt);
#else
    ans = na_ndloop3(&ndf, &g, 2, a, b);
#endif

    // return
#if LSY
    return rb_ary_concat(rb_ary_new3(3,a,b,jpvt),ans);
#elif LSD
    rb_ary_unshift(ans,b); return ans;
#elif LSS
    return rb_ary_concat(rb_ary_new3(2,a,b),ans);
#else
    return rb_ary_new3(3,a,b,ans);
#endif
}

#undef func_p
#undef args_t
#undef LSS
#undef LSD
#undef LSY


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gels.c"
/**/
#line 7 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gels.c"
#define LSS 1
#define LSD 0
#define LSY 1
#define args_t sgelsy_args_t
#define func_p sgelsy_p

typedef struct {
    int   order;
    char  trans;
    rtype rcond;
} args_t;

static sgelsy_t func_p = 0;

static void
iter_lapack_s_sgelsy(na_loop_t * const lp)
{
    dtype *a, *b;
    int   *info;
    int    m, n, nb, nrhs, lda, ldb, tmp;
    args_t *g;
#if LSS
    
    int *s; // or jpvt
    int   *rank;
#endif

    a = (dtype*)NDL_PTR(lp,0);
    b = (dtype*)NDL_PTR(lp,1);
#if LSS
    s = (int*)NDL_PTR(lp,2);
    rank = (int*)NDL_PTR(lp,3);
#endif
    info = (int*)NDL_PTR(lp,2+LSS*2);
    g = (args_t*)(lp->opt_ptr);

    m = NDL_SHAPE(lp,0)[0];
    n = NDL_SHAPE(lp,0)[1];
    SWAP_IFCOL(g->order,m,n);
    lda = NDL_STEP(lp,0) / sizeof(dtype);

    if (lp->args[1].ndim == 1) {
        nrhs = 1;
        nb = NDL_SHAPE(lp,1)[0];
        ldb = (g->order==LAPACK_COL_MAJOR) ? nb : 1;
    } else {
        nb = NDL_SHAPE(lp,1)[0];
        nrhs = NDL_SHAPE(lp,1)[1];
        ldb = nrhs;
        SWAP_IFCOL(g->order,nb,nrhs);
    }

    //printf("order=%d trans=%c m=%d n=%d nb=%d nrhs=%d lda=%d ldb=%d\n",g->order,g->trans,m,n,nb,nrhs,lda,ldb);

#if LSS
    *info = (*func_p)(g->order, m, n, nrhs, a, lda, b, ldb, s, g->rcond, rank);
#else
    *info = (*func_p)(g->order, g->trans, m, n, nrhs, a, lda, b, ldb);
#endif
    CHECK_ERROR(*info);
}

/*

  @overload sgelsy(a, b, jpvt, rcond:-1, order:'R')
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param b [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param jpvt [Numo::Int]  matrix (>=2-dimentional NArray).
  @param [Float] rcond  RCOND is used to determine the effective rank of A. Singular values S(i) <= RCOND*S(1) are treated as zero. If RCOND < 0, machine precision is used instead.
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, b, jpvt, rank, info]] Array<Numo::SFloat, Numo::SFloat, Numo::Int, Integer, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the M-by-N matrix A.
           On exit, A has been overwritten by details of its
           complete orthogonal factorization.

    - **b** -- 
           B is REAL array, dimension (LDB,NRHS)
           On entry, the M-by-NRHS right hand side matrix B.
           On exit, the N-by-NRHS solution matrix X.

    - **jpvt** -- 
           JPVT is INTEGER array, dimension (N)
           On entry, if JPVT(i) .ne. 0, the i-th column of A is permuted
           to the front of AP, otherwise column i is a free column.
           On exit, if JPVT(i) = k, then the i-th column of AP
           was the k-th column of A.

    - **rank** -- 
           RANK is INTEGER
           The effective rank of A, i.e., the order of the submatrix
           R11.  This is the same as the order of the submatrix T11
           in the complete orthogonal factorization of A.

    - **info** -- 
           INFO is INTEGER
           = 0: successful exit
           < 0: If INFO = -i, the i-th argument had an illegal value.

SGELSY computes the minimum-norm solution to a real linear least
squares problem:

        minimize || A * X - B ||

using a complete orthogonal factorization of A.  A is an M-by-N
matrix which may be rank-deficient.
Several right hand side vectors b and solution vectors x can be
handled in a single call; they are stored as the columns of the
M-by-NRHS right hand side matrix B and the N-by-NRHS solution
matrix X.
The routine first computes a QR factorization with column pivoting:

        A * P = Q * [ R11 R12 ]
                    [  0  R22 ]

with R11 defined as the largest leading submatrix whose estimated
condition number is less than 1/RCOND.  The order of R11, RANK,
is the effective rank of A.
Then, R22 is considered to be negligible, and R12 is annihilated
by orthogonal transformations from the right, arriving at the
complete orthogonal factorization:

        A * P = Q * [ T11 0 ] * Z
                    [  0  0 ]

The minimum-norm solution is then

        X = P * Z**T [ inv(T11)*Q1**T*B ]
                     [        0         ]

where Q1 consists of the first RANK columns of Q.
This routine is basically identical to the original xGELSX except
three differences:

        o The call to the subroutine xGEQPF has been substituted by the
          the call to the subroutine xGEQP3. This subroutine is a Blas-3
          version of the QR factorization with column pivoting.
        o Matrix B (the right hand side) is updated with Blas-3.
        o The permutation of matrix B (the right hand side) is faster and
          more simple.

*/
static VALUE
lapack_s_sgelsy(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, b, ans;
    int   m, n, nb, nrhs, tmp;
    int   max_mn;
    narray_t *na1, *na2;
#if LSY
    narray_t *na3;
    VALUE jpvt;
#endif
#if LSS
    size_t shape_s[1];
#endif
    /**/
    ndfunc_arg_in_t ain[2+LSS] = {{OVERWRITE,2},{OVERWRITE,2},{cInt,1}};
    ndfunc_arg_out_t aout[1+LSS*2] = {{cT,1,shape_s},{cInt,0},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sgelsy, NO_LOOP|NDF_EXTRACT, 2, 1+LSS*2, ain, aout};

    args_t g;
    VALUE opts[3] = {Qundef,Qundef,Qundef};
    ID kw_table[3] = {id_order,id_trans,id_rcond};
    VALUE kw_hash = Qnil;

    CHECK_FUNC(func_p,"sgelsy");

#if LSY
    rb_scan_args(argc, argv, "3:", &a, &b, &jpvt, &kw_hash);
#else
    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
#endif
    rb_get_kwargs(kw_hash, kw_table, 0, 3, opts);
    g.order = option_order(opts[0]);
#if LSS
    g.rcond = NUM2DBL(option_value(opts[2],DBL2NUM(-1)));
#else
    g.trans = option_trans(opts[1]);
#endif

    //A is DOUBLE PRECISION array, dimension (LDA,N)
    //On entry, the M-by-N matrix A.
    COPY_OR_CAST_TO(a,cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);

    //B is DOUBLE PRECISION array, dimension (LDB,NRHS)
    //B is M-by-NRHS if TRANS = 'N'
    //     N-by-NRHS if TRANS = 'T'
    COPY_OR_CAST_TO(b,cT);
    GetNArray(b, na2);
    CHECK_DIM_GE(na2, 1);

    //The number of rows of the matrix A.
    m = ROW_SIZE(na1);
    //The number of columns of the matrix A.
    n = COL_SIZE(na1);
    max_mn = (m > n) ? m : n;
    SWAP_IFCOL(g.order,m,n);

#if LSY
    ndf.nin++;
    ndf.nout--;
    ndf.aout++;
    COPY_OR_CAST_TO(jpvt,cInt);
    GetNArray(jpvt, na3);
    CHECK_DIM_GE(na3, 1);
    { int jpvt_sz = COL_SIZE(na3);
      CHECK_INT_EQ("jpvt_size",jpvt_sz,"n",n);
    }
#elif LSS
    shape_s[0] = (m < n) ? m : n;
#endif

    //The number of columns of the matrix B.
    if (na2->ndim == 1) {
        ain[1].dim = 1; // reduce dimension
        nb = COL_SIZE(na2);
        nrhs = 1;
    } else {
        //The number of rows of the matrix B.
        nb = ROW_SIZE(na2);
        nrhs = COL_SIZE(na2);
        SWAP_IFCOL(g.order,nb,nrhs);
    }
    if (nb < max_mn) {
        rb_raise(nary_eShapeError,
                 "ldb should be >= max(m,n): ldb=%d m=%d n=%d",nb,m,n);
    }

    // ndloop
#if LSY
    ans = na_ndloop3(&ndf, &g, 3, a, b, jpvt);
#else
    ans = na_ndloop3(&ndf, &g, 2, a, b);
#endif

    // return
#if LSY
    return rb_ary_concat(rb_ary_new3(3,a,b,jpvt),ans);
#elif LSD
    rb_ary_unshift(ans,b); return ans;
#elif LSS
    return rb_ary_concat(rb_ary_new3(2,a,b),ans);
#else
    return rb_ary_new3(3,a,b,ans);
#endif
}

#undef func_p
#undef args_t
#undef LSS
#undef LSD
#undef LSY


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/geev.c"
#define args_t sgeev_args_t
#define func_p sgeev_p

typedef struct {
    int order;
    char jobvl, jobvr;
} args_t;

static sgeev_t func_p = 0;

static void
iter_lapack_s_sgeev(na_loop_t * const lp)
{
    dtype *a, *vl, *vr;
#if IS_COMPLEX
    dtype *w;
#else
    dtype *wr, *wi;
#endif
    int   *info;
    int    n, lda, ldvl, ldvr;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
#if IS_COMPLEX
    w = (dtype*)NDL_PTR(lp,1);
#else
    wr = (dtype*)NDL_PTR(lp,1);
    wi = (dtype*)NDL_PTR(lp,2);
#endif
    vl = (dtype*)NDL_PTR(lp,3-CZ);
    vr = (dtype*)NDL_PTR(lp,4-CZ);
    info = (int*)NDL_PTR(lp,5-CZ);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[1];
    lda = NDL_STEP(lp,0) / sizeof(dtype);
    ldvl = NDL_STEP(lp,3-CZ) / sizeof(dtype);
    if (ldvl == 0) { ldvl = n; } // jobvt == 'N'
    ldvr = NDL_STEP(lp,4-CZ) / sizeof(dtype);
    if (ldvr == 0) { ldvr = n; } // jobvt == 'N'

    //printf("order=%d jobvl=%c jobvr=%c n=%d lda=%d ldvl=%d ldvr=%d\n",g->order,g->jobvl, g->jobvr, n, lda,ldvl,ldvr);

    /**/
    *info = (*func_p)(g->order, g->jobvl, g->jobvr, n, a, lda,wr, wi,vl, ldvl, vr, ldvr);
    CHECK_ERROR(*info);
}

/*
  @overload sgeev( a,, [jobvl:'V', jobvr:'V', order:'R'] )
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param jobvl [String or Symbol]  if 'V': Compute left eigenvectors, if 'N': Not compute left eigenvectors (default='V')
  @param jobvr [String or Symbol]  if 'V': Compute right eigenvectors, if 'N': Not compute right eigenvectors (default='V')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[wr, wi, vl, vr, info]] Array<Numo::SFloat, Numo::SFloat, Numo::SFloat, Numo::SFloat, Integer>

    - **wr** -- 
           WR is REAL array, dimension (N)

    - **wi** -- 
           WI is REAL array, dimension (N)
           WR and WI contain the real and imaginary parts,
           respectively, of the computed eigenvalues.  Complex
           conjugate pairs of eigenvalues appear consecutively
           with the eigenvalue having the positive imaginary part
           first.

    - **vl** -- 
           VL is REAL array, dimension (LDVL,N)
           If JOBVL = 'V', the left eigenvectors u(j) are stored one
           after another in the columns of VL, in the same order
           as their eigenvalues.
           If JOBVL = 'N', VL is not referenced.
           If the j-th eigenvalue is real, then u(j) = VL(:,j),
           the j-th column of VL.
           If the j-th and (j+1)-st eigenvalues form a complex
           conjugate pair, then u(j) = VL(:,j) + i\*VL(:,j+1) and
           u(j+1) = VL(:,j) - i\*VL(:,j+1).

    - **vr** -- 
           VR is REAL array, dimension (LDVR,N)
           If JOBVR = 'V', the right eigenvectors v(j) are stored one
           after another in the columns of VR, in the same order
           as their eigenvalues.
           If JOBVR = 'N', VR is not referenced.
           If the j-th eigenvalue is real, then v(j) = VR(:,j),
           the j-th column of VR.
           If the j-th and (j+1)-st eigenvalues form a complex
           conjugate pair, then v(j) = VR(:,j) + i\*VR(:,j+1) and
           v(j+1) = VR(:,j) - i\*VR(:,j+1).

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value.
           > 0:  if INFO = i, the QR algorithm failed to compute all the
                 eigenvalues, and no eigenvectors have been computed;
                 elements i+1:N of WR and WI contain eigenvalues which
                 have converged.

SGEEV computes for an N-by-N real nonsymmetric matrix A, the
eigenvalues and, optionally, the left and/or right eigenvectors.
The right eigenvector v(j) of A satisfies

                 A * v(j) = lambda(j) * v(j)

where lambda(j) is its eigenvalue.
The left eigenvector u(j) of A satisfies

              u(j)**H * A = lambda(j) * u(j)**H

where u(j)\*\*H denotes the conjugate-transpose of u(j).
The computed eigenvectors are normalized to have Euclidean norm
equal to 1 and largest component real.

*/
static VALUE
lapack_s_sgeev(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, ans;
    int   m, n;
    narray_t *na1;
    /**/
    size_t shape[2];
    ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
    ndfunc_arg_out_t aout[5-CZ] = {{cT,1,shape},{cT,1,shape},{cT,2,shape},{cT,2,shape},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sgeev, NO_LOOP|NDF_EXTRACT, 1, 5-CZ, ain, aout};

    args_t g = {0,0,0};
    VALUE opts[3] = {Qundef,Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[3] = {id_order,id_jobvl,id_jobvr};

    CHECK_FUNC(func_p,"sgeev");

    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
    rb_get_kwargs(kw_hash, kw_table, 0, 3, opts);
    g.order = option_order(opts[0]);
    g.jobvl = option_job(opts[1],'V','N');
    g.jobvr = option_job(opts[2],'V','N');

    COPY_OR_CAST_TO(a,cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
    m = ROW_SIZE(na1);
    n = COL_SIZE(na1);
    if (m != n) {
        rb_raise(nary_eShapeError,"matrix must be square");
    }
    shape[0] = shape[1] = n;
    if (g.jobvl=='N') { aout[2-CZ].dim = 0; }
    if (g.jobvr=='N') { aout[3-CZ].dim = 0; }

    ans = na_ndloop3(&ndf, &g, 1, a);

    if (aout[3-CZ].dim == 0) { RARRAY_ASET(ans,3-CZ,Qnil); }
    if (aout[2-CZ].dim == 0) { RARRAY_ASET(ans,2-CZ,Qnil); }
    return ans;
}

#undef args_t
#undef func_p


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/ggev.c"
#define args_t sggev_args_t
#define func_p sggev_p

typedef struct {
    int order;
    char jobvl, jobvr;
} args_t;

static sggev_t func_p = 0;

static void
iter_lapack_s_sggev(na_loop_t * const lp)
{
    dtype *a, *b, *beta, *vl, *vr;
#if IS_COMPLEX
    dtype *alpha;
#else
    dtype *alphar, *alphai;
#endif
    int   *info;
    int    n, lda, ldb, ldvl, ldvr;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
    b = (dtype*)NDL_PTR(lp,1);
#if IS_COMPLEX
    alpha = (dtype*)NDL_PTR(lp,2);
#else
    alphar = (dtype*)NDL_PTR(lp,2);
    alphai = (dtype*)NDL_PTR(lp,3);
#endif
    beta = (dtype*)NDL_PTR(lp,4-CZ);
    vl = (dtype*)NDL_PTR(lp,5-CZ);
    vr = (dtype*)NDL_PTR(lp,6-CZ);
    info = (int*)NDL_PTR(lp,7-CZ);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[1];
    lda = NDL_STEP(lp,0) / sizeof(dtype);
    ldb = NDL_STEP(lp,1) / sizeof(dtype);
    ldvl = NDL_STEP(lp,5-CZ) / sizeof(dtype);
    if (ldvl == 0) { ldvl = n; } // jobvl == 'N'
    ldvr = NDL_STEP(lp,6-CZ) / sizeof(dtype);
    if (ldvr == 0) { ldvr = n; } // jobvr == 'N'

    //printf("order=%d jobvl=%c jobvr=%c n=%d lda=%d ldb=%d ldvl=%d ldvr=%d\n",g->order,g->jobvl, g->jobvr, n, lda,ldb,ldvl,ldvr);

    /**/
    *info = (*func_p)(g->order, g->jobvl, g->jobvr, n, a, lda, b, ldb,alphar, alphai,beta, vl, ldvl, vr, ldvr);
    CHECK_ERROR(*info);
}

/*

  @overload sggev(a, b, [jobvl:'V', jobvr:'V', order:'R'] )
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param b [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param jobvl [String or Symbol]  if 'V': Compute left eigenvectors, if 'N': Not compute left eigenvectors (default='V')
  @param jobvr [String or Symbol]  if 'V': Compute right eigenvectors, if 'N': Not compute right eigenvectors (default='V')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[alphar, alphai, beta, vl, vr, info]] Array<Numo::SFloat, Numo::SFloat, Numo::SFloat, Numo::SFloat, Numo::SFloat, Integer>

    - **alphar** -- 
           ALPHAR is REAL array, dimension (N)

    - **alphai** -- 
           ALPHAI is REAL array, dimension (N)

    - **beta** -- 
           BETA is REAL array, dimension (N)
           On exit, (ALPHAR(j) + ALPHAI(j)\*i)/BETA(j), j=1,...,N, will
           be the generalized eigenvalues.  If ALPHAI(j) is zero, then
           the j-th eigenvalue is real; if positive, then the j-th and
           (j+1)-st eigenvalues are a complex conjugate pair, with
           ALPHAI(j+1) negative.
           Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j)
           may easily over- or underflow, and BETA(j) may even be zero.
           Thus, the user should avoid naively computing the ratio
           alpha/beta.  However, ALPHAR and ALPHAI will be always less
           than and usually comparable with norm(A) in magnitude, and
           BETA always less than and usually comparable with norm(B).

    - **vl** -- 
           VL is REAL array, dimension (LDVL,N)
           If JOBVL = 'V', the left eigenvectors u(j) are stored one
           after another in the columns of VL, in the same order as
           their eigenvalues. If the j-th eigenvalue is real, then
           u(j) = VL(:,j), the j-th column of VL. If the j-th and
           (j+1)-th eigenvalues form a complex conjugate pair, then
           u(j) = VL(:,j)+i\*VL(:,j+1) and u(j+1) = VL(:,j)-i\*VL(:,j+1).
           Each eigenvector is scaled so the largest component has
           abs(real part)+abs(imag. part)=1.
           Not referenced if JOBVL = 'N'.

    - **vr** -- 
           VR is REAL array, dimension (LDVR,N)
           If JOBVR = 'V', the right eigenvectors v(j) are stored one
           after another in the columns of VR, in the same order as
           their eigenvalues. If the j-th eigenvalue is real, then
           v(j) = VR(:,j), the j-th column of VR. If the j-th and
           (j+1)-th eigenvalues form a complex conjugate pair, then
           v(j) = VR(:,j)+i\*VR(:,j+1) and v(j+1) = VR(:,j)-i\*VR(:,j+1).
           Each eigenvector is scaled so the largest component has
           abs(real part)+abs(imag. part)=1.
           Not referenced if JOBVR = 'N'.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value.
           = 1,...,N:
                 The QZ iteration failed.  No eigenvectors have been
                 calculated, but ALPHAR(j), ALPHAI(j), and BETA(j)
                 should be correct for j=INFO+1,...,N.
           > N:  =N+1: other than QZ iteration failed in SHGEQZ.
                 =N+2: error return from STGEVC.

SGGEV computes for a pair of N-by-N real nonsymmetric matrices (A,B)
the generalized eigenvalues, and optionally, the left and/or right
generalized eigenvectors.
A generalized eigenvalue for a pair of matrices (A,B) is a scalar
lambda or a ratio alpha/beta = lambda, such that A - lambda\*B is
singular. It is usually represented as the pair (alpha,beta), as
there is a reasonable interpretation for beta=0, and even for both
being zero.
The right eigenvector v(j) corresponding to the eigenvalue lambda(j)
of (A,B) satisfies

                 A * v(j) = lambda(j) * B * v(j).

The left eigenvector u(j) corresponding to the eigenvalue lambda(j)
of (A,B) satisfies

                 u(j)**H * A  = lambda(j) * u(j)**H * B .

where u(j)\*\*H is the conjugate-transpose of u(j).

*/
static VALUE
lapack_s_sggev(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, b, ans;
    int   n, nb;
    narray_t *na1, *na2;
    /**/
    size_t shape[2];
    ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{OVERWRITE,2}};
    ndfunc_arg_out_t aout[6-CZ] = {{cT,1,shape},{cT,1,shape},{cT,1,shape},{cT,2,shape},{cT,2,shape},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sggev, NO_LOOP|NDF_EXTRACT, 2, 6-CZ, ain, aout};

    args_t g;
    VALUE opts[3] = {Qundef,Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[3] = {id_order,id_jobvl,id_jobvr};

    CHECK_FUNC(func_p,"sggev");

    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
    rb_get_kwargs(kw_hash, kw_table, 0, 3, opts);
    g.order = option_order(opts[0]);
    g.jobvl = option_job(opts[1],'V','N');
    g.jobvr = option_job(opts[2],'V','N');

    COPY_OR_CAST_TO(a,cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);

    COPY_OR_CAST_TO(b,cT);
    GetNArray(b, na2);
    CHECK_DIM_GE(na2, 2);

    CHECK_SQUARE("matrix a",na1);
    n  = COL_SIZE(na1);
    CHECK_SQUARE("matrix b",na2);
    nb = COL_SIZE(na2);
    if (n != nb) {
        rb_raise(nary_eShapeError,"matrix a and b must have same size");
    }
    shape[0] = shape[1] = n;
    if (g.jobvl=='N') { aout[3-CZ].dim = 0; }
    if (g.jobvr=='N') { aout[4-CZ].dim = 0; }

    ans = na_ndloop3(&ndf, &g, 2, a, b);

    if (aout[4-CZ].dim == 0) { RARRAY_ASET(ans,4-CZ,Qnil); }
    if (aout[3-CZ].dim == 0) { RARRAY_ASET(ans,3-CZ,Qnil); }
    return ans;
}

#undef args_t
#undef func_p


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/syev.c"
#define args_t ssyev_args_t
#define func_p ssyev_p

typedef struct {
    int order;
    char jobz, uplo;
} args_t;

static ssyev_t func_p = 0;

static void
iter_lapack_s_ssyev(na_loop_t * const lp)
{
    dtype *a;
    rtype *w;
    int   *info;
    int    n, lda;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
    w = (rtype*)NDL_PTR(lp,1);
    info = (int*)NDL_PTR(lp,2);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[1];
    lda = NDL_STEP(lp,0) / sizeof(dtype);

    //printf("order=%d jobz=%c uplo=%c n=%d lda=%d\n",g->order,g->jobz,g->uplo,n,lda);

    *info = (*func_p)( g->order, g->jobz, g->uplo, n, a, lda, w );
    CHECK_ERROR(*info);
}

/*
  @overload ssyev(a, [jobz:'V', uplo:'U', order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param jobz [String or Symbol]  if 'V': Compute eigenvectors, if 'N': Not compute eigenvectors (default='V')
  @param uplo [String or Symbol]  if 'U': Upper triangle, if 'L': Lower triangle. (default='U')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, w, info]]  Array<Numo::SFloat,Numo::SFloat,Integer>

    - **a** -- 
           A is REAL array, dimension (LDA, N)
           On entry, the symmetric matrix A.  If UPLO = 'U', the
           leading N-by-N upper triangular part of A contains the
           upper triangular part of the matrix A.  If UPLO = 'L',
           the leading N-by-N lower triangular part of A contains
           the lower triangular part of the matrix A.
           On exit, if JOBZ = 'V', then if INFO = 0, A contains the
           orthonormal eigenvectors of the matrix A.
           If JOBZ = 'N', then on exit the lower triangle (if UPLO='L')
           or the upper triangle (if UPLO='U') of A, including the
           diagonal, is destroyed.

    - **w** -- 
           W is REAL array, dimension (N)
           If INFO = 0, the eigenvalues in ascending order.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value
           > 0:  if INFO = i, the algorithm failed to converge; i
                 off-diagonal elements of an intermediate tridiagonal
                 form did not converge to zero.

SSYEV computes all eigenvalues and, optionally, eigenvectors of a
real symmetric matrix A.

*/
static VALUE
lapack_s_ssyev(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, ans;
    int   m, n;
    narray_t *na1;
    size_t shape[1];
    ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
    ndfunc_arg_out_t aout[2] = {{cRT,1,shape},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_ssyev, NO_LOOP|NDF_EXTRACT, 1, 2, ain, aout};

    args_t g = {0,0,0};
    VALUE opts[3] = {Qundef,Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[3] = {id_order,id_jobz,id_uplo};

    CHECK_FUNC(func_p,"ssyev");

    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
    rb_get_kwargs(kw_hash, kw_table, 0, 3, opts);
    g.order = option_order(opts[0]);
    g.jobz = option_job(opts[1],'V','N');
    g.uplo = option_uplo(opts[2]);

    COPY_OR_CAST_TO(a,cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
    m = ROW_SIZE(na1);
    n = COL_SIZE(na1);
    if (m != n) {
        rb_raise(nary_eShapeError,"matrix must be square");
    }
    shape[0] = n;

    ans = na_ndloop3(&ndf, &g, 1, a);

    return rb_ary_new3(3, a, RARRAY_AREF(ans,0), RARRAY_AREF(ans,1));
}

#undef args_t
#undef func_p


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/syev.c"
#define args_t ssyevd_args_t
#define func_p ssyevd_p

typedef struct {
    int order;
    char jobz, uplo;
} args_t;

static ssyevd_t func_p = 0;

static void
iter_lapack_s_ssyevd(na_loop_t * const lp)
{
    dtype *a;
    rtype *w;
    int   *info;
    int    n, lda;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
    w = (rtype*)NDL_PTR(lp,1);
    info = (int*)NDL_PTR(lp,2);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[1];
    lda = NDL_STEP(lp,0) / sizeof(dtype);

    //printf("order=%d jobz=%c uplo=%c n=%d lda=%d\n",g->order,g->jobz,g->uplo,n,lda);

    *info = (*func_p)( g->order, g->jobz, g->uplo, n, a, lda, w );
    CHECK_ERROR(*info);
}

/*
  @overload ssyevd(a, [jobz:'V', uplo:'U', order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param jobz [String or Symbol]  if 'V': Compute eigenvectors, if 'N': Not compute eigenvectors (default='V')
  @param uplo [String or Symbol]  if 'U': Upper triangle, if 'L': Lower triangle. (default='U')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, w, info]]  Array<Numo::SFloat,Numo::SFloat,Integer>

    - **a** -- 
           A is REAL array, dimension (LDA, N)
           On entry, the symmetric matrix A.  If UPLO = 'U', the
           leading N-by-N upper triangular part of A contains the
           upper triangular part of the matrix A.  If UPLO = 'L',
           the leading N-by-N lower triangular part of A contains
           the lower triangular part of the matrix A.
           On exit, if JOBZ = 'V', then if INFO = 0, A contains the
           orthonormal eigenvectors of the matrix A.
           If JOBZ = 'N', then on exit the lower triangle (if UPLO='L')
           or the upper triangle (if UPLO='U') of A, including the
           diagonal, is destroyed.

    - **w** -- 
           W is REAL array, dimension (N)
           If INFO = 0, the eigenvalues in ascending order.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value
           > 0:  if INFO = i and JOBZ = 'N', then the algorithm failed
                 to converge; i off-diagonal elements of an intermediate
                 tridiagonal form did not converge to zero;
                 if INFO = i and JOBZ = 'V', then the algorithm failed
                 to compute an eigenvalue while working on the submatrix
                 lying in rows and columns INFO/(N+1) through
                 mod(INFO,N+1).

SSYEVD computes all eigenvalues and, optionally, eigenvectors of a
real symmetric matrix A. If eigenvectors are desired, it uses a
divide and conquer algorithm.
The divide and conquer algorithm makes very mild assumptions about
floating point arithmetic. It will work on machines with a guard
digit in add/subtract, or on those binary machines without guard
digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
Cray-2. It could conceivably fail on hexadecimal or decimal machines
without guard digits, but we know of none.
Because of large use of BLAS of level 3, SSYEVD needs N\*\*2 more
workspace than SSYEVX.

*/
static VALUE
lapack_s_ssyevd(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, ans;
    int   m, n;
    narray_t *na1;
    size_t shape[1];
    ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
    ndfunc_arg_out_t aout[2] = {{cRT,1,shape},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_ssyevd, NO_LOOP|NDF_EXTRACT, 1, 2, ain, aout};

    args_t g = {0,0,0};
    VALUE opts[3] = {Qundef,Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[3] = {id_order,id_jobz,id_uplo};

    CHECK_FUNC(func_p,"ssyevd");

    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
    rb_get_kwargs(kw_hash, kw_table, 0, 3, opts);
    g.order = option_order(opts[0]);
    g.jobz = option_job(opts[1],'V','N');
    g.uplo = option_uplo(opts[2]);

    COPY_OR_CAST_TO(a,cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
    m = ROW_SIZE(na1);
    n = COL_SIZE(na1);
    if (m != n) {
        rb_raise(nary_eShapeError,"matrix must be square");
    }
    shape[0] = n;

    ans = na_ndloop3(&ndf, &g, 1, a);

    return rb_ary_new3(3, a, RARRAY_AREF(ans,0), RARRAY_AREF(ans,1));
}

#undef args_t
#undef func_p


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/sygv.c"
#define args_t ssygv_args_t
#define func_p ssygv_p

typedef struct {
    int order;
    int itype;
    char jobz, uplo;
} args_t;

static ssygv_t func_p = 0;

static void
iter_lapack_s_ssygv(na_loop_t * const lp)
{
    dtype *a, *b;
    rtype *w;
    int   *info;
    int    n, lda, ldb;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
    b = (dtype*)NDL_PTR(lp,1);
    w = (rtype*)NDL_PTR(lp,2);
    info = (int*)NDL_PTR(lp,3);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[1];
    lda = NDL_STEP(lp,0) / sizeof(dtype);
    ldb = NDL_STEP(lp,1) / sizeof(dtype);

    //printf("order=%d itype=%d jobz=%c uplo=%c n=%d lda=%d ldb=%d\n",g->order,g->itype,g->jobz,g->uplo,n,lda,ldb);

    *info = (*func_p)( g->order, g->itype, g->jobz, g->uplo, n, a, lda, b, ldb, w );
    CHECK_ERROR(*info);
}

/*
  @overload ssygv(a, b, [itype:1, jobz:'V', uplo:'U', order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param b [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param [Integer] itype Specifies the problem type to be solved. If 1:  A*x = (lambda)*B*x, If 2:  A*B*x = (lambda)*x, If 3:  B*A*x = (lambda)*x.
  @param jobz [String or Symbol]  if 'V': Compute eigenvectors, if 'N': Not compute eigenvectors (default='V')
  @param uplo [String or Symbol]  if 'U': Upper triangle, if 'L': Lower triangle. (default='U')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, b, w, info]] Array<Numo::SFloat,Numo::SFloat,Integer>

    - **a** -- 
           A is REAL array, dimension (LDA, N)
           On entry, the symmetric matrix A.  If UPLO = 'U', the
           leading N-by-N upper triangular part of A contains the
           upper triangular part of the matrix A.  If UPLO = 'L',
           the leading N-by-N lower triangular part of A contains
           the lower triangular part of the matrix A.
           On exit, if JOBZ = 'V', then if INFO = 0, A contains the
           matrix Z of eigenvectors.  The eigenvectors are normalized
           as follows:
           if ITYPE = 1 or 2, Z\*\*T\*B\*Z = I;
           if ITYPE = 3, Z\*\*T\*inv(B)\*Z = I.
           If JOBZ = 'N', then on exit the upper triangle (if UPLO='U')
           or the lower triangle (if UPLO='L') of A, including the
           diagonal, is destroyed.

    - **b** -- 
           B is REAL array, dimension (LDB, N)
           On entry, the symmetric positive definite matrix B.
           If UPLO = 'U', the leading N-by-N upper triangular part of B
           contains the upper triangular part of the matrix B.
           If UPLO = 'L', the leading N-by-N lower triangular part of B
           contains the lower triangular part of the matrix B.
           On exit, if INFO <= N, the part of B containing the matrix is
           overwritten by the triangular factor U or L from the Cholesky
           factorization B = U\*\*T\*U or B = L\*L\*\*T.

    - **w** -- 
           W is REAL array, dimension (N)
           If INFO = 0, the eigenvalues in ascending order.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value
           > 0:  SPOTRF or SSYEV returned an error code:
              <= N:  if INFO = i, SSYEV failed to converge;
                     i off-diagonal elements of an intermediate
                     tridiagonal form did not converge to zero;
              > N:   if INFO = N + i, for 1 <= i <= N, then the leading
                     minor of order i of B is not positive definite.
                     The factorization of B could not be completed and
                     no eigenvalues or eigenvectors were computed.

SSYGV computes all the eigenvalues, and optionally, the eigenvectors
of a real generalized symmetric-definite eigenproblem, of the form
A\*x=(lambda)\*B\*x,  A\*Bx=(lambda)\*x,  or B\*A\*x=(lambda)\*x.
Here A and B are assumed to be symmetric and B is also
positive definite.

*/
static VALUE
lapack_s_ssygv(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, b, ans;
    int   n, nb;
    narray_t *na1, *na2;
    size_t shape[1];
    ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{OVERWRITE,2}};
    ndfunc_arg_out_t aout[2] = {{cRT,1,shape},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_ssygv, NO_LOOP|NDF_EXTRACT, 2, 2, ain, aout};

    args_t g;
    VALUE opts[4] = {Qundef,Qundef,Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[4] = {id_order,id_jobz,id_uplo,id_itype};

    CHECK_FUNC(func_p,"ssygv");

    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
    rb_get_kwargs(kw_hash, kw_table, 0, 4, opts);
    g.order = option_order(opts[0]);
    g.jobz = option_job(opts[1],'V','N');
    g.uplo = option_uplo(opts[2]);
    g.itype = NUM2INT(option_value(opts[3],INT2FIX(1)));

    COPY_OR_CAST_TO(a,cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);

    COPY_OR_CAST_TO(b,cT);
    GetNArray(b, na2);
    CHECK_DIM_GE(na2, 2);

    CHECK_SQUARE("matrix a",na1);
    n  = COL_SIZE(na1);
    CHECK_SQUARE("matrix b",na2);
    nb = COL_SIZE(na2);
    if (n != nb) {
        rb_raise(nary_eShapeError,"matrix a and b must have same size");
    }
    shape[0] = n;

    ans = na_ndloop3(&ndf, &g, 2, a, b);

    return rb_ary_new3(4, a, b, RARRAY_AREF(ans,0), RARRAY_AREF(ans,1));
}

#undef args_t
#undef func_p


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/sygv.c"
#define args_t ssygvd_args_t
#define func_p ssygvd_p

typedef struct {
    int order;
    int itype;
    char jobz, uplo;
} args_t;

static ssygvd_t func_p = 0;

static void
iter_lapack_s_ssygvd(na_loop_t * const lp)
{
    dtype *a, *b;
    rtype *w;
    int   *info;
    int    n, lda, ldb;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
    b = (dtype*)NDL_PTR(lp,1);
    w = (rtype*)NDL_PTR(lp,2);
    info = (int*)NDL_PTR(lp,3);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[1];
    lda = NDL_STEP(lp,0) / sizeof(dtype);
    ldb = NDL_STEP(lp,1) / sizeof(dtype);

    //printf("order=%d itype=%d jobz=%c uplo=%c n=%d lda=%d ldb=%d\n",g->order,g->itype,g->jobz,g->uplo,n,lda,ldb);

    *info = (*func_p)( g->order, g->itype, g->jobz, g->uplo, n, a, lda, b, ldb, w );
    CHECK_ERROR(*info);
}

/*
  @overload ssygvd(a, b, [itype:1, jobz:'V', uplo:'U', order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param b [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param [Integer] itype Specifies the problem type to be solved. If 1:  A*x = (lambda)*B*x, If 2:  A*B*x = (lambda)*x, If 3:  B*A*x = (lambda)*x.
  @param jobz [String or Symbol]  if 'V': Compute eigenvectors, if 'N': Not compute eigenvectors (default='V')
  @param uplo [String or Symbol]  if 'U': Upper triangle, if 'L': Lower triangle. (default='U')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, b, w, info]] Array<Numo::SFloat,Numo::SFloat,Integer>

    - **a** -- 
           A is REAL array, dimension (LDA, N)
           On entry, the symmetric matrix A.  If UPLO = 'U', the
           leading N-by-N upper triangular part of A contains the
           upper triangular part of the matrix A.  If UPLO = 'L',
           the leading N-by-N lower triangular part of A contains
           the lower triangular part of the matrix A.
           On exit, if JOBZ = 'V', then if INFO = 0, A contains the
           matrix Z of eigenvectors.  The eigenvectors are normalized
           as follows:
           if ITYPE = 1 or 2, Z\*\*T\*B\*Z = I;
           if ITYPE = 3, Z\*\*T\*inv(B)\*Z = I.
           If JOBZ = 'N', then on exit the upper triangle (if UPLO='U')
           or the lower triangle (if UPLO='L') of A, including the
           diagonal, is destroyed.

    - **b** -- 
           B is REAL array, dimension (LDB, N)
           On entry, the symmetric matrix B.  If UPLO = 'U', the
           leading N-by-N upper triangular part of B contains the
           upper triangular part of the matrix B.  If UPLO = 'L',
           the leading N-by-N lower triangular part of B contains
           the lower triangular part of the matrix B.
           On exit, if INFO <= N, the part of B containing the matrix is
           overwritten by the triangular factor U or L from the Cholesky
           factorization B = U\*\*T\*U or B = L\*L\*\*T.

    - **w** -- 
           W is REAL array, dimension (N)
           If INFO = 0, the eigenvalues in ascending order.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value
           > 0:  SPOTRF or SSYEVD returned an error code:
              <= N:  if INFO = i and JOBZ = 'N', then the algorithm
                     failed to converge; i off-diagonal elements of an
                     intermediate tridiagonal form did not converge to
                     zero;
                     if INFO = i and JOBZ = 'V', then the algorithm
                     failed to compute an eigenvalue while working on
                     the submatrix lying in rows and columns INFO/(N+1)
                     through mod(INFO,N+1);
              > N:   if INFO = N + i, for 1 <= i <= N, then the leading
                     minor of order i of B is not positive definite.
                     The factorization of B could not be completed and
                     no eigenvalues or eigenvectors were computed.

SSYGVD computes all the eigenvalues, and optionally, the eigenvectors
of a real generalized symmetric-definite eigenproblem, of the form
A\*x=(lambda)\*B\*x,  A\*Bx=(lambda)\*x,  or B\*A\*x=(lambda)\*x.  Here A and
B are assumed to be symmetric and B is also positive definite.
If eigenvectors are desired, it uses a divide and conquer algorithm.
The divide and conquer algorithm makes very mild assumptions about
floating point arithmetic. It will work on machines with a guard
digit in add/subtract, or on those binary machines without guard
digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
Cray-2. It could conceivably fail on hexadecimal or decimal machines
without guard digits, but we know of none.

*/
static VALUE
lapack_s_ssygvd(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, b, ans;
    int   n, nb;
    narray_t *na1, *na2;
    size_t shape[1];
    ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{OVERWRITE,2}};
    ndfunc_arg_out_t aout[2] = {{cRT,1,shape},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_ssygvd, NO_LOOP|NDF_EXTRACT, 2, 2, ain, aout};

    args_t g;
    VALUE opts[4] = {Qundef,Qundef,Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[4] = {id_order,id_jobz,id_uplo,id_itype};

    CHECK_FUNC(func_p,"ssygvd");

    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
    rb_get_kwargs(kw_hash, kw_table, 0, 4, opts);
    g.order = option_order(opts[0]);
    g.jobz = option_job(opts[1],'V','N');
    g.uplo = option_uplo(opts[2]);
    g.itype = NUM2INT(option_value(opts[3],INT2FIX(1)));

    COPY_OR_CAST_TO(a,cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);

    COPY_OR_CAST_TO(b,cT);
    GetNArray(b, na2);
    CHECK_DIM_GE(na2, 2);

    CHECK_SQUARE("matrix a",na1);
    n  = COL_SIZE(na1);
    CHECK_SQUARE("matrix b",na2);
    nb = COL_SIZE(na2);
    if (n != nb) {
        rb_raise(nary_eShapeError,"matrix a and b must have same size");
    }
    shape[0] = n;

    ans = na_ndloop3(&ndf, &g, 2, a, b);

    return rb_ary_new3(4, a, b, RARRAY_AREF(ans,0), RARRAY_AREF(ans,1));
}

#undef args_t
#undef func_p


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/sygvx.c"
#define args_t ssygvx_args_t
#define func_p ssygvx_p

typedef struct {
    int order;
    int itype;
    char jobz;
    char uplo;
    char range;
    int il;
    int iu;
} args_t;

static ssygvx_t func_p = 0;

static void
iter_lapack_s_ssygvx(na_loop_t * const lp)
{
    dtype *a, *b, *z;
    rtype *w;
    int   *ifail;
    int   *info;
    int    m, n, lda, ldb, ldz;
    rtype  vl = 0, vu = 0;
    rtype  abstol = 0;

    args_t *g;

    a = (dtype*)NDL_PTR(lp, 0);
    b = (dtype*)NDL_PTR(lp, 1);
    w = (rtype*)NDL_PTR(lp, 2);
    z = (dtype*)NDL_PTR(lp, 3);
    ifail = (int*)NDL_PTR(lp, 4);
    info = (int*)NDL_PTR(lp, 5);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp, 0)[1];
    lda = NDL_STEP(lp, 0) / sizeof(dtype);
    ldb = NDL_STEP(lp, 1) / sizeof(dtype);
    ldz = NDL_SHAPE(lp, 3)[1];

    *info = (*func_p)( g->order, g->itype, g->jobz, g->range, g->uplo, n, a, lda, b, ldb,
                       vl, vu, g->il, g->iu, abstol, &m, w, z, ldz, ifail );

    CHECK_ERROR(*info);
}

/*

  @overload ssygvx(a, b, [itype:1, jobz:'V', uplo:'U', order:'R', range:'I', il: 1, il: 2])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param b [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param [Integer] itype Specifies the problem type to be solved.  If 1:  A*x = (lambda)*B*x, If 2:  A*B*x = (lambda)*x, If 3:  B*A*x = (lambda)*x.
  @param jobz [String or Symbol]  if 'V': Compute eigenvectors, if 'N': Not compute eigenvectors (default='V')
  @param uplo [String or Symbol]  if 'U': Upper triangle, if 'L': Lower triangle. (default='U')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @param [String or Symbol] range If 'A': Compute all eigenvalues, if 'I': Compute eigenvalues with indices il to iu (default='A')
  @param [Integer] il Specifies the index of the smallest eigenvalue in ascending order to be returned. If range = 'A', il is not referenced.
  @param [Integer] iu Specifies the index of the largest eigenvalue in ascending order to be returned. Constraint: 1<=il<=iu<=N. If range = 'A', iu is not referenced.
  @return [[a, b, w, z, ifail, info]]
    Array<Numo::SFloat,Numo::SFloat,Numo::SFloat,Numo::SFloat,Numo::SFloat,Integer>

    - **a** -- 
           A is REAL array, dimension (LDA, N)
           On entry, the symmetric matrix A.  If UPLO = 'U', the
           leading N-by-N upper triangular part of A contains the
           upper triangular part of the matrix A.  If UPLO = 'L',
           the leading N-by-N lower triangular part of A contains
           the lower triangular part of the matrix A.
           On exit, the lower triangle (if UPLO='L') or the upper
           triangle (if UPLO='U') of A, including the diagonal, is
           destroyed.

    - **b** -- 
           B is REAL array, dimension (LDA, N)
           On entry, the symmetric matrix B.  If UPLO = 'U', the
           leading N-by-N upper triangular part of B contains the
           upper triangular part of the matrix B.  If UPLO = 'L',
           the leading N-by-N lower triangular part of B contains
           the lower triangular part of the matrix B.
           On exit, if INFO <= N, the part of B containing the matrix is
           overwritten by the triangular factor U or L from the Cholesky
           factorization B = U\*\*T\*U or B = L\*L\*\*T.

    - **w** -- 
           W is REAL array, dimension (N)
           On normal exit, the first M elements contain the selected
           eigenvalues in ascending order.

    - **z** -- 
           Z is REAL array, dimension (LDZ, max(1,M))
           If JOBZ = 'N', then Z is not referenced.
           If JOBZ = 'V', then if INFO = 0, the first M columns of Z
           contain the orthonormal eigenvectors of the matrix A
           corresponding to the selected eigenvalues, with the i-th
           column of Z holding the eigenvector associated with W(i).
           The eigenvectors are normalized as follows:
           if ITYPE = 1 or 2, Z\*\*T\*B\*Z = I;
           if ITYPE = 3, Z\*\*T\*inv(B)\*Z = I.
           If an eigenvector fails to converge, then that column of Z
           contains the latest approximation to the eigenvector, and the
           index of the eigenvector is returned in IFAIL.
           Note: the user must ensure that at least max(1,M) columns are
           supplied in the array Z; if RANGE = 'V', the exact value of M
           is not known in advance and an upper bound must be used.

    - **ifail** -- 
           IFAIL is INTEGER array, dimension (N)
           If JOBZ = 'V', then if INFO = 0, the first M elements of
           IFAIL are zero.  If INFO > 0, then IFAIL contains the
           indices of the eigenvectors that failed to converge.
           If JOBZ = 'N', then IFAIL is not referenced.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value
           > 0:  SPOTRF or SSYEVX returned an error code:
              <= N:  if INFO = i, SSYEVX failed to converge;
                     i eigenvectors failed to converge.  Their indices
                     are stored in array IFAIL.
              > N:   if INFO = N + i, for 1 <= i <= N, then the leading
                     minor of order i of B is not positive definite.
                     The factorization of B could not be completed and
                     no eigenvalues or eigenvectors were computed.

SSYGVX computes selected eigenvalues, and optionally, eigenvectors
of a real generalized symmetric-definite eigenproblem, of the form
A\*x=(lambda)\*B\*x,  A\*Bx=(lambda)\*x,  or B\*A\*x=(lambda)\*x.  Here A
and B are assumed to be symmetric and B is also positive definite.
Eigenvalues and eigenvectors can be selected by specifying either a
range of values or a range of indices for the desired eigenvalues.
*/

static VALUE
lapack_s_ssygvx(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, b, ans;
    int   n, nb, m;
    narray_t *na1, *na2;
    size_t w_shape[1];
    size_t z_shape[2];
    size_t ifail_shape[1];

    ndfunc_arg_in_t ain[2] = {{OVERWRITE, 2}, {OVERWRITE, 2}};
    ndfunc_arg_out_t aout[4] = {{cRT, 1, w_shape}, {cT, 2, z_shape}, {cI, 1, ifail_shape}, {cInt, 0}};
    ndfunc_t ndf = {&iter_lapack_s_ssygvx, NO_LOOP | NDF_EXTRACT, 2, 4, ain, aout};

    args_t g;
    VALUE opts[7] = {Qundef, Qundef, Qundef, Qundef, Qundef, Qundef, Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[7] = {id_order, id_jobz, id_uplo, id_itype, id_range, id_il, id_iu};

    CHECK_FUNC(func_p,"ssygvx");

    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
    rb_get_kwargs(kw_hash, kw_table, 0, 7, opts);
    g.order = option_order(opts[0]);
    g.jobz = option_job(opts[1], 'V', 'N');
    g.uplo = option_uplo(opts[2]);
    g.itype = NUM2INT(option_value(opts[3], INT2FIX(1)));
    g.range = option_range(opts[4], 'A', 'I');
    g.il = NUM2INT(option_value(opts[5], INT2FIX(1)));
    g.iu = NUM2INT(option_value(opts[6], INT2FIX(1)));

    COPY_OR_CAST_TO(a, cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);

    COPY_OR_CAST_TO(b, cT);
    GetNArray(b, na2);
    CHECK_DIM_GE(na2, 2);
    CHECK_SQUARE("matrix a", na1);
    n  = COL_SIZE(na1);
    CHECK_SQUARE("matrix b", na2);
    nb = COL_SIZE(na2);
    if (n != nb) {
        rb_raise(nary_eShapeError, "matrix a and b must have same size");
    }

    m = g.range == 'I' ? g.iu - g.il + 1 : n;
    w_shape[0] = m;
    z_shape[0] = n;
    z_shape[1] = m;
    ifail_shape[0] = m;

    ans = na_ndloop3(&ndf, &g, 2, a, b);

    return rb_ary_new3(6, a, b, RARRAY_AREF(ans, 0), RARRAY_AREF(ans, 1), RARRAY_AREF(ans, 2), RARRAY_AREF(ans, 3));
}

#undef args_t
#undef func_p


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/fact.c"
/**/
#line 7 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/fact.c"
#define UPLO 0
#define JPVT 0
#define TAU  1
#define args_t sgeqrf_args_t
#define func_p sgeqrf_p

typedef struct {
    int order;
    char uplo;
} args_t;

static sgeqrf_t func_p = 0;

static void
iter_lapack_s_sgeqrf(na_loop_t * const lp)
{
    dtype *a;
#if JPVT
    int   *pv;
#endif
#if TAU
    dtype *tau;
#endif
    int   *info;
    int    m, n, lda, tmp;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
#if JPVT
    pv = (int*)NDL_PTR(lp,1);
#endif
#if TAU
    tau = (dtype*)NDL_PTR(lp,1+JPVT);
#endif
    info = (int*)NDL_PTR(lp,1+JPVT+TAU);
    g = (args_t*)(lp->opt_ptr);

    m = NDL_SHAPE(lp,0)[0];
    n = NDL_SHAPE(lp,0)[1];
    SWAP_IFCOL(g->order,m,n);
#if UPLO
    n = min_(m,n);
#endif
    lda = NDL_STEP(lp,0) / sizeof(dtype);

    //printf("order=%d m=%d n=%d lda=%d \n",g->order,m,n,lda);

    /**/
    *info = (*func_p)(g->order, m, n, a, lda, tau);
    CHECK_ERROR(*info);
}

/*
  @overload sgeqrf(a, [order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, tau, info]] Array<Numo::SFloat, Numo::SFloat, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the M-by-N matrix A.
           On exit, the elements on and above the diagonal of the array
           contain the min(M,N)-by-N upper trapezoidal matrix R (R is
           upper triangular if m >= n); the elements below the diagonal,
           with the array TAU, represent the orthogonal matrix Q as a
           product of min(m,n) elementary reflectors (see Further
           Details).

    - **tau** -- 
           TAU is REAL array, dimension (min(M,N))
           The scalar factors of the elementary reflectors (see Further
           Details).

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value

SGEQRF computes a QR factorization of a real M-by-N matrix A:
A = Q \* R.

*/
static VALUE
lapack_s_sgeqrf(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, ans;
    int   m, n, tmp;
    narray_t *na1;
#if JPVT
    VALUE jpvt;
#endif
    /**/
#if TAU
    size_t shape_tau[1];
#endif
    ndfunc_arg_in_t ain[1+JPVT] = {{OVERWRITE,2}};
    ndfunc_arg_out_t aout[1+TAU] = {{cT,1,shape_tau},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sgeqrf, NO_LOOP|NDF_EXTRACT,
                    1+JPVT, TAU+1, ain,aout};

    args_t g = {0,1};
    VALUE opts[2] = {Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};

    CHECK_FUNC(func_p,"sgeqrf");

#if JPVT
    rb_scan_args(argc, argv, "2:", &a, &jpvt, &kw_hash);
#else
    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
#endif
    rb_get_kwargs(kw_hash, kw_table, 0, 1+UPLO, opts);
    g.order = option_order(opts[0]);
#if UPLO
    g.uplo = option_uplo(opts[1]);
#endif

    COPY_OR_CAST_TO(a,cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
    m = ROW_SIZE(na1);
    n = COL_SIZE(na1);
    SWAP_IFCOL(g.order,m,n);
#if TAU
    shape_tau[0] = min_(m,n);
#endif

#if JPVT
    COPY_OR_CAST_TO(jpvt,cInt);
    ans = na_ndloop3(&ndf, &g, 2, a, jpvt);
    rb_ary_concat(rb_ary_assoc(a,jpvt), ans);
    return ans;
#else
    ans = na_ndloop3(&ndf, &g, 1, a);
#if TAU == 0
    return rb_assoc_new(a, ans);
#else
    rb_ary_unshift(ans, a);
    return ans;
#endif
#endif
}

#undef args_t
#undef func_p
#undef UPLO
#undef JPVT
#undef TAU


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/fact.c"
/**/
#line 7 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/fact.c"
#define UPLO 0
#define JPVT 0
#define TAU  1
#define args_t sgerqf_args_t
#define func_p sgerqf_p

typedef struct {
    int order;
    char uplo;
} args_t;

static sgerqf_t func_p = 0;

static void
iter_lapack_s_sgerqf(na_loop_t * const lp)
{
    dtype *a;
#if JPVT
    int   *pv;
#endif
#if TAU
    dtype *tau;
#endif
    int   *info;
    int    m, n, lda, tmp;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
#if JPVT
    pv = (int*)NDL_PTR(lp,1);
#endif
#if TAU
    tau = (dtype*)NDL_PTR(lp,1+JPVT);
#endif
    info = (int*)NDL_PTR(lp,1+JPVT+TAU);
    g = (args_t*)(lp->opt_ptr);

    m = NDL_SHAPE(lp,0)[0];
    n = NDL_SHAPE(lp,0)[1];
    SWAP_IFCOL(g->order,m,n);
#if UPLO
    n = min_(m,n);
#endif
    lda = NDL_STEP(lp,0) / sizeof(dtype);

    //printf("order=%d m=%d n=%d lda=%d \n",g->order,m,n,lda);

    /**/
    *info = (*func_p)(g->order, m, n, a, lda, tau);
    CHECK_ERROR(*info);
}

/*
  @overload sgerqf(a, [order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, tau, info]] Array<Numo::SFloat, Numo::SFloat, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the M-by-N matrix A.
           On exit,
           if m <= n, the upper triangle of the subarray
           A(1:m,n-m+1:n) contains the M-by-M upper triangular matrix R;
           if m >= n, the elements on and above the (m-n)-th subdiagonal
           contain the M-by-N upper trapezoidal matrix R;
           the remaining elements, with the array TAU, represent the
           orthogonal matrix Q as a product of min(m,n) elementary
           reflectors (see Further Details).

    - **tau** -- 
           TAU is REAL array, dimension (min(M,N))
           The scalar factors of the elementary reflectors (see Further
           Details).

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value

SGERQF computes an RQ factorization of a real M-by-N matrix A:
A = R \* Q.

*/
static VALUE
lapack_s_sgerqf(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, ans;
    int   m, n, tmp;
    narray_t *na1;
#if JPVT
    VALUE jpvt;
#endif
    /**/
#if TAU
    size_t shape_tau[1];
#endif
    ndfunc_arg_in_t ain[1+JPVT] = {{OVERWRITE,2}};
    ndfunc_arg_out_t aout[1+TAU] = {{cT,1,shape_tau},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sgerqf, NO_LOOP|NDF_EXTRACT,
                    1+JPVT, TAU+1, ain,aout};

    args_t g = {0,1};
    VALUE opts[2] = {Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};

    CHECK_FUNC(func_p,"sgerqf");

#if JPVT
    rb_scan_args(argc, argv, "2:", &a, &jpvt, &kw_hash);
#else
    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
#endif
    rb_get_kwargs(kw_hash, kw_table, 0, 1+UPLO, opts);
    g.order = option_order(opts[0]);
#if UPLO
    g.uplo = option_uplo(opts[1]);
#endif

    COPY_OR_CAST_TO(a,cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
    m = ROW_SIZE(na1);
    n = COL_SIZE(na1);
    SWAP_IFCOL(g.order,m,n);
#if TAU
    shape_tau[0] = min_(m,n);
#endif

#if JPVT
    COPY_OR_CAST_TO(jpvt,cInt);
    ans = na_ndloop3(&ndf, &g, 2, a, jpvt);
    rb_ary_concat(rb_ary_assoc(a,jpvt), ans);
    return ans;
#else
    ans = na_ndloop3(&ndf, &g, 1, a);
#if TAU == 0
    return rb_assoc_new(a, ans);
#else
    rb_ary_unshift(ans, a);
    return ans;
#endif
#endif
}

#undef args_t
#undef func_p
#undef UPLO
#undef JPVT
#undef TAU


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/fact.c"
/**/
#line 7 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/fact.c"
#define UPLO 0
#define JPVT 0
#define TAU  1
#define args_t sgeqlf_args_t
#define func_p sgeqlf_p

typedef struct {
    int order;
    char uplo;
} args_t;

static sgeqlf_t func_p = 0;

static void
iter_lapack_s_sgeqlf(na_loop_t * const lp)
{
    dtype *a;
#if JPVT
    int   *pv;
#endif
#if TAU
    dtype *tau;
#endif
    int   *info;
    int    m, n, lda, tmp;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
#if JPVT
    pv = (int*)NDL_PTR(lp,1);
#endif
#if TAU
    tau = (dtype*)NDL_PTR(lp,1+JPVT);
#endif
    info = (int*)NDL_PTR(lp,1+JPVT+TAU);
    g = (args_t*)(lp->opt_ptr);

    m = NDL_SHAPE(lp,0)[0];
    n = NDL_SHAPE(lp,0)[1];
    SWAP_IFCOL(g->order,m,n);
#if UPLO
    n = min_(m,n);
#endif
    lda = NDL_STEP(lp,0) / sizeof(dtype);

    //printf("order=%d m=%d n=%d lda=%d \n",g->order,m,n,lda);

    /**/
    *info = (*func_p)(g->order, m, n, a, lda, tau);
    CHECK_ERROR(*info);
}

/*
  @overload sgeqlf(a, [order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, tau, info]] Array<Numo::SFloat, Numo::SFloat, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the M-by-N matrix A.
           On exit,
           if m >= n, the lower triangle of the subarray
           A(m-n+1:m,1:n) contains the N-by-N lower triangular matrix L;
           if m <= n, the elements on and below the (n-m)-th
           superdiagonal contain the M-by-N lower trapezoidal matrix L;
           the remaining elements, with the array TAU, represent the
           orthogonal matrix Q as a product of elementary reflectors
           (see Further Details).

    - **tau** -- 
           TAU is REAL array, dimension (min(M,N))
           The scalar factors of the elementary reflectors (see Further
           Details).

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value

SGEQLF computes a QL factorization of a real M-by-N matrix A:
A = Q \* L.

*/
static VALUE
lapack_s_sgeqlf(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, ans;
    int   m, n, tmp;
    narray_t *na1;
#if JPVT
    VALUE jpvt;
#endif
    /**/
#if TAU
    size_t shape_tau[1];
#endif
    ndfunc_arg_in_t ain[1+JPVT] = {{OVERWRITE,2}};
    ndfunc_arg_out_t aout[1+TAU] = {{cT,1,shape_tau},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sgeqlf, NO_LOOP|NDF_EXTRACT,
                    1+JPVT, TAU+1, ain,aout};

    args_t g = {0,1};
    VALUE opts[2] = {Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};

    CHECK_FUNC(func_p,"sgeqlf");

#if JPVT
    rb_scan_args(argc, argv, "2:", &a, &jpvt, &kw_hash);
#else
    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
#endif
    rb_get_kwargs(kw_hash, kw_table, 0, 1+UPLO, opts);
    g.order = option_order(opts[0]);
#if UPLO
    g.uplo = option_uplo(opts[1]);
#endif

    COPY_OR_CAST_TO(a,cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
    m = ROW_SIZE(na1);
    n = COL_SIZE(na1);
    SWAP_IFCOL(g.order,m,n);
#if TAU
    shape_tau[0] = min_(m,n);
#endif

#if JPVT
    COPY_OR_CAST_TO(jpvt,cInt);
    ans = na_ndloop3(&ndf, &g, 2, a, jpvt);
    rb_ary_concat(rb_ary_assoc(a,jpvt), ans);
    return ans;
#else
    ans = na_ndloop3(&ndf, &g, 1, a);
#if TAU == 0
    return rb_assoc_new(a, ans);
#else
    rb_ary_unshift(ans, a);
    return ans;
#endif
#endif
}

#undef args_t
#undef func_p
#undef UPLO
#undef JPVT
#undef TAU


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/fact.c"
/**/
#line 7 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/fact.c"
#define UPLO 0
#define JPVT 0
#define TAU  1
#define args_t sgelqf_args_t
#define func_p sgelqf_p

typedef struct {
    int order;
    char uplo;
} args_t;

static sgelqf_t func_p = 0;

static void
iter_lapack_s_sgelqf(na_loop_t * const lp)
{
    dtype *a;
#if JPVT
    int   *pv;
#endif
#if TAU
    dtype *tau;
#endif
    int   *info;
    int    m, n, lda, tmp;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
#if JPVT
    pv = (int*)NDL_PTR(lp,1);
#endif
#if TAU
    tau = (dtype*)NDL_PTR(lp,1+JPVT);
#endif
    info = (int*)NDL_PTR(lp,1+JPVT+TAU);
    g = (args_t*)(lp->opt_ptr);

    m = NDL_SHAPE(lp,0)[0];
    n = NDL_SHAPE(lp,0)[1];
    SWAP_IFCOL(g->order,m,n);
#if UPLO
    n = min_(m,n);
#endif
    lda = NDL_STEP(lp,0) / sizeof(dtype);

    //printf("order=%d m=%d n=%d lda=%d \n",g->order,m,n,lda);

    /**/
    *info = (*func_p)(g->order, m, n, a, lda, tau);
    CHECK_ERROR(*info);
}

/*
  @overload sgelqf(a, [order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, tau, info]] Array<Numo::SFloat, Numo::SFloat, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the M-by-N matrix A.
           On exit, the elements on and below the diagonal of the array
           contain the m-by-min(m,n) lower trapezoidal matrix L (L is
           lower triangular if m <= n); the elements above the diagonal,
           with the array TAU, represent the orthogonal matrix Q as a
           product of elementary reflectors (see Further Details).

    - **tau** -- 
           TAU is REAL array, dimension (min(M,N))
           The scalar factors of the elementary reflectors (see Further
           Details).

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value

SGELQF computes an LQ factorization of a real M-by-N matrix A:
A = L \* Q.

*/
static VALUE
lapack_s_sgelqf(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, ans;
    int   m, n, tmp;
    narray_t *na1;
#if JPVT
    VALUE jpvt;
#endif
    /**/
#if TAU
    size_t shape_tau[1];
#endif
    ndfunc_arg_in_t ain[1+JPVT] = {{OVERWRITE,2}};
    ndfunc_arg_out_t aout[1+TAU] = {{cT,1,shape_tau},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sgelqf, NO_LOOP|NDF_EXTRACT,
                    1+JPVT, TAU+1, ain,aout};

    args_t g = {0,1};
    VALUE opts[2] = {Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};

    CHECK_FUNC(func_p,"sgelqf");

#if JPVT
    rb_scan_args(argc, argv, "2:", &a, &jpvt, &kw_hash);
#else
    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
#endif
    rb_get_kwargs(kw_hash, kw_table, 0, 1+UPLO, opts);
    g.order = option_order(opts[0]);
#if UPLO
    g.uplo = option_uplo(opts[1]);
#endif

    COPY_OR_CAST_TO(a,cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
    m = ROW_SIZE(na1);
    n = COL_SIZE(na1);
    SWAP_IFCOL(g.order,m,n);
#if TAU
    shape_tau[0] = min_(m,n);
#endif

#if JPVT
    COPY_OR_CAST_TO(jpvt,cInt);
    ans = na_ndloop3(&ndf, &g, 2, a, jpvt);
    rb_ary_concat(rb_ary_assoc(a,jpvt), ans);
    return ans;
#else
    ans = na_ndloop3(&ndf, &g, 1, a);
#if TAU == 0
    return rb_assoc_new(a, ans);
#else
    rb_ary_unshift(ans, a);
    return ans;
#endif
#endif
}

#undef args_t
#undef func_p
#undef UPLO
#undef JPVT
#undef TAU


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/fact.c"
/**/
#line 7 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/fact.c"
#define UPLO 0
#define JPVT 1
#define TAU  1
#define args_t sgeqp3_args_t
#define func_p sgeqp3_p

typedef struct {
    int order;
    char uplo;
} args_t;

static sgeqp3_t func_p = 0;

static void
iter_lapack_s_sgeqp3(na_loop_t * const lp)
{
    dtype *a;
#if JPVT
    int   *pv;
#endif
#if TAU
    dtype *tau;
#endif
    int   *info;
    int    m, n, lda, tmp;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
#if JPVT
    pv = (int*)NDL_PTR(lp,1);
#endif
#if TAU
    tau = (dtype*)NDL_PTR(lp,1+JPVT);
#endif
    info = (int*)NDL_PTR(lp,1+JPVT+TAU);
    g = (args_t*)(lp->opt_ptr);

    m = NDL_SHAPE(lp,0)[0];
    n = NDL_SHAPE(lp,0)[1];
    SWAP_IFCOL(g->order,m,n);
#if UPLO
    n = min_(m,n);
#endif
    lda = NDL_STEP(lp,0) / sizeof(dtype);

    //printf("order=%d m=%d n=%d lda=%d \n",g->order,m,n,lda);

    /**/
    *info = (*func_p)(g->order, m, n, a, lda, pv, tau);
    CHECK_ERROR(*info);
}

/*
  @overload sgeqp3(a, jpvt, [order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, jpvt, tau, info]] Array<Numo::SFloat, Numo::Int, Numo::SFloat, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the M-by-N matrix A.
           On exit, the upper triangle of the array contains the
           min(M,N)-by-N upper trapezoidal matrix R; the elements below
           the diagonal, together with the array TAU, represent the
           orthogonal matrix Q as a product of min(M,N) elementary
           reflectors.

    - **jpvt** -- 
           JPVT is INTEGER array, dimension (N)
           On entry, if JPVT(J).ne.0, the J-th column of A is permuted
           to the front of A\*P (a leading column); if JPVT(J)=0,
           the J-th column of A is a free column.
           On exit, if JPVT(J)=K, then the J-th column of A\*P was the
           the K-th column of A.

    - **tau** -- 
           TAU is REAL array, dimension (min(M,N))
           The scalar factors of the elementary reflectors.

    - **info** -- 
           INFO is INTEGER
           = 0: successful exit.
           < 0: if INFO = -i, the i-th argument had an illegal value.

SGEQP3 computes a QR factorization with column pivoting of a
matrix A:  A\*P = Q\*R  using Level 3 BLAS.

*/
static VALUE
lapack_s_sgeqp3(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, ans;
    int   m, n, tmp;
    narray_t *na1;
#if JPVT
    VALUE jpvt;
#endif
    /**/
#if TAU
    size_t shape_tau[1];
#endif
    ndfunc_arg_in_t ain[1+JPVT] = {{OVERWRITE,2},{OVERWRITE,1}};
    ndfunc_arg_out_t aout[1+TAU] = {{cT,1,shape_tau},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sgeqp3, NO_LOOP|NDF_EXTRACT,
                    1+JPVT, TAU+1, ain,aout};

    args_t g = {0,1};
    VALUE opts[2] = {Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};

    CHECK_FUNC(func_p,"sgeqp3");

#if JPVT
    rb_scan_args(argc, argv, "2:", &a, &jpvt, &kw_hash);
#else
    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
#endif
    rb_get_kwargs(kw_hash, kw_table, 0, 1+UPLO, opts);
    g.order = option_order(opts[0]);
#if UPLO
    g.uplo = option_uplo(opts[1]);
#endif

    COPY_OR_CAST_TO(a,cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
    m = ROW_SIZE(na1);
    n = COL_SIZE(na1);
    SWAP_IFCOL(g.order,m,n);
#if TAU
    shape_tau[0] = min_(m,n);
#endif

#if JPVT
    COPY_OR_CAST_TO(jpvt,cInt);
    ans = na_ndloop3(&ndf, &g, 2, a, jpvt);
    rb_ary_concat(rb_ary_assoc(a,jpvt), ans);
    return ans;
#else
    ans = na_ndloop3(&ndf, &g, 1, a);
#if TAU == 0
    return rb_assoc_new(a, ans);
#else
    rb_ary_unshift(ans, a);
    return ans;
#endif
#endif
}

#undef args_t
#undef func_p
#undef UPLO
#undef JPVT
#undef TAU


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/fact.c"
/**/
#line 7 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/fact.c"
#define UPLO 0
#define JPVT 0
#define TAU  1
#define args_t stzrzf_args_t
#define func_p stzrzf_p

typedef struct {
    int order;
    char uplo;
} args_t;

static stzrzf_t func_p = 0;

static void
iter_lapack_s_stzrzf(na_loop_t * const lp)
{
    dtype *a;
#if JPVT
    int   *pv;
#endif
#if TAU
    dtype *tau;
#endif
    int   *info;
    int    m, n, lda, tmp;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
#if JPVT
    pv = (int*)NDL_PTR(lp,1);
#endif
#if TAU
    tau = (dtype*)NDL_PTR(lp,1+JPVT);
#endif
    info = (int*)NDL_PTR(lp,1+JPVT+TAU);
    g = (args_t*)(lp->opt_ptr);

    m = NDL_SHAPE(lp,0)[0];
    n = NDL_SHAPE(lp,0)[1];
    SWAP_IFCOL(g->order,m,n);
#if UPLO
    n = min_(m,n);
#endif
    lda = NDL_STEP(lp,0) / sizeof(dtype);

    //printf("order=%d m=%d n=%d lda=%d \n",g->order,m,n,lda);

    /**/
    *info = (*func_p)(g->order, m, n, a, lda, tau);
    CHECK_ERROR(*info);
}

/*
  @overload stzrzf(a, [order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, tau, info]] Array<Numo::SFloat, Numo::SFloat, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the leading M-by-N upper trapezoidal part of the
           array A must contain the matrix to be factorized.
           On exit, the leading M-by-M upper triangular part of A
           contains the upper triangular matrix R, and elements M+1 to
           N of the first M rows of A, with the array TAU, represent the
           orthogonal matrix Z as a product of M elementary reflectors.

    - **tau** -- 
           TAU is REAL array, dimension (M)
           The scalar factors of the elementary reflectors.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value

STZRZF reduces the M-by-N ( M<=N ) real upper trapezoidal matrix A
to upper triangular form by means of orthogonal transformations.
The upper trapezoidal matrix A is factored as

        A = ( R  0 ) * Z,

where Z is an N-by-N orthogonal matrix and R is an M-by-M upper
triangular matrix.

*/
static VALUE
lapack_s_stzrzf(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, ans;
    int   m, n, tmp;
    narray_t *na1;
#if JPVT
    VALUE jpvt;
#endif
    /**/
#if TAU
    size_t shape_tau[1];
#endif
    ndfunc_arg_in_t ain[1+JPVT] = {{OVERWRITE,2}};
    ndfunc_arg_out_t aout[1+TAU] = {{cT,1,shape_tau},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_stzrzf, NO_LOOP|NDF_EXTRACT,
                    1+JPVT, TAU+1, ain,aout};

    args_t g = {0,1};
    VALUE opts[2] = {Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};

    CHECK_FUNC(func_p,"stzrzf");

#if JPVT
    rb_scan_args(argc, argv, "2:", &a, &jpvt, &kw_hash);
#else
    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
#endif
    rb_get_kwargs(kw_hash, kw_table, 0, 1+UPLO, opts);
    g.order = option_order(opts[0]);
#if UPLO
    g.uplo = option_uplo(opts[1]);
#endif

    COPY_OR_CAST_TO(a,cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
    m = ROW_SIZE(na1);
    n = COL_SIZE(na1);
    SWAP_IFCOL(g.order,m,n);
#if TAU
    shape_tau[0] = min_(m,n);
#endif

#if JPVT
    COPY_OR_CAST_TO(jpvt,cInt);
    ans = na_ndloop3(&ndf, &g, 2, a, jpvt);
    rb_ary_concat(rb_ary_assoc(a,jpvt), ans);
    return ans;
#else
    ans = na_ndloop3(&ndf, &g, 1, a);
#if TAU == 0
    return rb_assoc_new(a, ans);
#else
    rb_ary_unshift(ans, a);
    return ans;
#endif
#endif
}

#undef args_t
#undef func_p
#undef UPLO
#undef JPVT
#undef TAU


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gqr.c"
/**/
#line 4 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/gqr.c"
#define args_t sorgqr_args_t
#define func_p sorgqr_p

typedef struct {
    int order;
} args_t;

static sorgqr_t func_p = 0;

static void
iter_lapack_s_sorgqr(na_loop_t * const lp)
{
    dtype *a;
    dtype *tau;
    int   *info;
    int    m, n, k, lda, tmp;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
    tau = (dtype*)NDL_PTR(lp,1);
    info = (int*)NDL_PTR(lp,2);
    g = (args_t*)(lp->opt_ptr);

    m = NDL_SHAPE(lp,0)[0];
    n = NDL_SHAPE(lp,0)[1];
    k = NDL_SHAPE(lp,1)[0];
    SWAP_IFCOL(g->order,m,n);
    lda = NDL_STEP(lp,0) / sizeof(dtype);

    //printf("order=%d m=%d n=%d k=%d lda=%d \n",g->order,m,n,k,lda);

    *info = (*func_p)(g->order, m, n, k, a, lda, tau);
    CHECK_ERROR(*info);
}

/*
  @overload sorgqr(a, tau, order:'R')
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param tau [Numo::SFloat]  vector (>=1-dimentional NArray).
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, info]] Array<Numo::SFloat, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the i-th column must contain the vector which
           defines the elementary reflector H(i), for i = 1,2,...,k, as
           returned by SGEQRF in the first k columns of its array
           argument A.
           On exit, the M-by-N matrix Q.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument has an illegal value

SORGQR generates an M-by-N real matrix Q with orthonormal columns,
which is defined as the first N columns of a product of K elementary
reflectors of order M

        Q  =  H(1) H(2) . . . H(k)

as returned by SGEQRF.

*/
static VALUE
lapack_s_sorgqr(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
    VALUE a, tau, ans;
    int   m, n, k, tmp;
    narray_t *na1, *na2;
    ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{cT,1}};
    ndfunc_arg_out_t aout[1] = {{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sorgqr, NO_LOOP|NDF_EXTRACT, 2,1, ain,aout};

    args_t g = {0};
    VALUE opts[1] = {Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[1] = {id_order};

    CHECK_FUNC(func_p,"sorgqr");

    rb_scan_args(argc, argv, "2:", &a, &tau, &kw_hash);
    rb_get_kwargs(kw_hash, kw_table, 0, 1, opts);
    g.order = option_order(opts[0]);

    COPY_OR_CAST_TO(a,cT);
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
    m = ROW_SIZE(na1);
    n = COL_SIZE(na1);

    GetNArray(tau, na2);
    CHECK_DIM_GE(na2, 1);
    k = COL_SIZE(na2);
    if (m < n) {
        rb_raise(nary_eShapeError,
                 "a row length (m) must be >= a column length (n): m=%d n=%d",
                 m,n);
    }
    if (n < k) {
        rb_raise(nary_eShapeError,
                 "a column length (n) must be >= tau length (k): n=%d, k=%d",
                 k,n);
    }
    SWAP_IFCOL(g.order,m,n);

    ans = na_ndloop3(&ndf, &g, 2, a, tau);

    return rb_assoc_new(a, ans);
}

#undef args_t
#undef func_p


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"

#line 10 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#define RHS  0
#define TRANS 0
#define UPLO 0
#define IPIV 1
#define IPIV_OUT 1
#define IPIV_IN 0
#define SYM  0
#define args_t sgetrf_args_t
#define func_p sgetrf_p

typedef struct {
    int order;
    char uplo;
    char trans;
} args_t;

static sgetrf_t func_p = 0;

static void
iter_lapack_s_sgetrf(na_loop_t * const lp)
{
    dtype *a;
#if RHS
    dtype *b;
    int    nb, nrhs, ldb;
#endif
#if IPIV
    int   *pv;
#endif
    int   *info;
    int    m, n, lda;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
#if IPIV
    pv = (int*)NDL_PTR(lp,1);
#endif
#if RHS
    b = (dtype*)NDL_PTR(lp,1+IPIV);
#endif
    info = (int*)NDL_PTR(lp,1+IPIV+RHS);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[0];
    m = NDL_SHAPE(lp,0)[1];
    lda = NDL_STEP(lp,0) / sizeof(dtype);

#if RHS
    // same as gels.c
    if (lp->args[1+IPIV].ndim == 1) {
        nrhs = 1;
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        ldb = (g->order==LAPACK_COL_MAJOR) ? nb : 1;
    } else {
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        nrhs = NDL_SHAPE(lp,1+IPIV)[1];
        ldb = nrhs;
        { int tmp; SWAP_IFCOL(g->order,nb,nrhs); }
    }
    //printf("order=%d m=%d n=%d nb=%d nrhs=%d lda=%d ldb=%d\n",g->order,m,n,nb,nrhs,lda,ldb);
#else
    //printf("order=%d m=%d n=%d lda=%d \n",g->order,m,n,lda);
#endif

#if SYM
    n = min_(m,n);
#else
    { int tmp; SWAP_IFCOL(g->order,m,n); }
#endif

    
#line 91 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    *info = (*func_p)(g->order, n, m, a, lda, pv);
    CHECK_ERROR(*info);
}

/*
  @overload sgetrf(a, [order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, ipiv, info]] Array<Numo::SFloat, Numo::Int, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the M-by-N matrix to be factored.
           On exit, the factors L and U from the factorization
           A = P\*L\*U; the unit diagonal elements of L are not stored.

    - **ipiv** -- 
           IPIV is INTEGER array, dimension (min(M,N))
           The pivot indices; for 1 <= i <= min(M,N), row i of the
           matrix was interchanged with row IPIV(i).

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value
           > 0:  if INFO = i, U(i,i) is exactly zero. The factorization
                 has been completed, but the factor U is exactly
                 singular, and division by zero will occur if it is used
                 to solve a system of equations.

SGETRF computes an LU factorization of a general M-by-N matrix A
using partial pivoting with row interchanges.
The factorization has the form

        A = P * L * U

where P is a permutation matrix, L is lower triangular with unit
diagonal elements (lower trapezoidal if m > n), and U is upper
triangular (upper trapezoidal if m < n).
This is the right-looking Level 3 BLAS version of the algorithm.

*/
static VALUE
lapack_s_sgetrf(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    VALUE a, ans;
#if IPIV_IN
    VALUE ipiv;
#endif
#if RHS
    VALUE b;
    size_t n, nb, nrhs;
    narray_t *na2;
#endif
    narray_t *na1;
    
#line 160 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#if IPIV_OUT
    size_t shape_piv[1];
#endif
#if IPIV_IN
# if RHS
    ndfunc_arg_in_t ain[3] = {{cT,2},{cInt,1},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{cInt,1}};
# endif
#else
# if RHS
    ndfunc_arg_in_t ain[2] = {{cT,2},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
# endif
#endif
    ndfunc_arg_out_t aout[1+IPIV_OUT] = {{cInt,1,shape_piv},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sgetrf, NO_LOOP|NDF_EXTRACT,
                    1+IPIV_IN+RHS, IPIV_OUT+1, ain,aout};

    args_t g = {0,0};
    VALUE opts[2] = {Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};

    CHECK_FUNC(func_p,"sgetrf");

#if IPIV_IN
# if RHS
    rb_scan_args(argc, argv, "3:", &a, &ipiv, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "2:", &a, &ipiv, &kw_hash);
# endif
#else
# if RHS
    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
# endif
#endif
#if TRANS
    kw_table[1] = id_trans;
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.trans = option_trans(opts[1]);
#elif UPLO
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.uplo = option_uplo(opts[1]);
#else
    rb_get_kwargs(kw_hash, kw_table, 0, 1, opts);
#endif
    g.order = option_order(opts[0]);

#if !RHS
    COPY_OR_CAST_TO(a,cT);
#endif
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
#if IPIV_OUT
    shape_piv[0] = min_(ROW_SIZE(na1),COL_SIZE(na1));
#endif

#if RHS
    COPY_OR_CAST_TO(b,cT);
    GetNArray(b, na2);
    CHECK_DIM_GE(na2, 1);
    n = COL_SIZE(na1);
#if SYM
    n = min_(n,ROW_SIZE(na1));
#endif
    // same as gesv.c
    if (NA_NDIM(na2) == 1) {
        ain[1+IPIV_IN].dim = 1;
        nb = COL_SIZE(na2);
        nrhs = 1;
    } else {
        nb = ROW_SIZE(na2);
        nrhs = COL_SIZE(na2);
        { int tmp; SWAP_IFCOL(g.order,nb,nrhs); }
    }
    if (n != nb) {
        rb_raise(nary_eShapeError, "matrix dimension mismatch: "
                 "a.col(or a.row)=%"SZF"u b.row=%"SZF"u", n, nb);
    }
#endif

#if IPIV_IN
# if RHS
    ans = na_ndloop3(&ndf, &g, 3, a, ipiv, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 2, a, ipiv);
    return rb_assoc_new(a, ans);
# endif
#else
# if RHS
    ans = na_ndloop3(&ndf, &g, 2, a, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 1, a);
#  if IPIV_OUT
    return rb_ary_unshift(ans, a);
#  else
    return rb_assoc_new(a, ans);
#  endif
# endif
#endif
}

#undef args_t
#undef func_p
#undef RHS
#undef TRANS
#undef UPLO
#undef IPIV
#undef IPIV_OUT
#undef IPIV_IN
#undef SYM


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"

#line 10 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#define RHS  0
#define TRANS 0
#define UPLO 0
#define IPIV 1
#define IPIV_OUT 0
#define IPIV_IN 1
#define SYM  1
#define args_t sgetri_args_t
#define func_p sgetri_p

typedef struct {
    int order;
    char uplo;
    char trans;
} args_t;

static sgetri_t func_p = 0;

static void
iter_lapack_s_sgetri(na_loop_t * const lp)
{
    dtype *a;
#if RHS
    dtype *b;
    int    nb, nrhs, ldb;
#endif
#if IPIV
    int   *pv;
#endif
    int   *info;
    int    m, n, lda;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
#if IPIV
    pv = (int*)NDL_PTR(lp,1);
#endif
#if RHS
    b = (dtype*)NDL_PTR(lp,1+IPIV);
#endif
    info = (int*)NDL_PTR(lp,1+IPIV+RHS);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[0];
    m = NDL_SHAPE(lp,0)[1];
    lda = NDL_STEP(lp,0) / sizeof(dtype);

#if RHS
    // same as gels.c
    if (lp->args[1+IPIV].ndim == 1) {
        nrhs = 1;
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        ldb = (g->order==LAPACK_COL_MAJOR) ? nb : 1;
    } else {
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        nrhs = NDL_SHAPE(lp,1+IPIV)[1];
        ldb = nrhs;
        { int tmp; SWAP_IFCOL(g->order,nb,nrhs); }
    }
    //printf("order=%d m=%d n=%d nb=%d nrhs=%d lda=%d ldb=%d\n",g->order,m,n,nb,nrhs,lda,ldb);
#else
    //printf("order=%d m=%d n=%d lda=%d \n",g->order,m,n,lda);
#endif

#if SYM
    n = min_(m,n);
#else
    { int tmp; SWAP_IFCOL(g->order,m,n); }
#endif

    
#line 91 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    *info = (*func_p)(g->order, n, a, lda, pv);
    CHECK_ERROR(*info);
}

/*
  @overload sgetri(a, ipiv, [order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param ipiv [Numo::Int] pivot computed by sgetrf
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, info]] Array<Numo::SFloat, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the factors L and U from the factorization
           A = P\*L\*U as computed by SGETRF.
           On exit, if INFO = 0, the inverse of the original matrix A.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value
           > 0:  if INFO = i, U(i,i) is exactly zero; the matrix is
                 singular and its inverse could not be computed.

SGETRI computes the inverse of a matrix using the LU factorization
computed by SGETRF.
This method inverts U and then computes inv(A) by solving the system
inv(A)\*L = inv(U) for inv(A).

*/
static VALUE
lapack_s_sgetri(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    VALUE a, ans;
#if IPIV_IN
    VALUE ipiv;
#endif
#if RHS
    VALUE b;
    size_t n, nb, nrhs;
    narray_t *na2;
#endif
    narray_t *na1;
    
#line 160 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#if IPIV_OUT
    size_t shape_piv[1];
#endif
#if IPIV_IN
# if RHS
    ndfunc_arg_in_t ain[3] = {{cT,2},{cInt,1},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{cInt,1}};
# endif
#else
# if RHS
    ndfunc_arg_in_t ain[2] = {{cT,2},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
# endif
#endif
    ndfunc_arg_out_t aout[1+IPIV_OUT] = {{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sgetri, NO_LOOP|NDF_EXTRACT,
                    1+IPIV_IN+RHS, IPIV_OUT+1, ain,aout};

    args_t g = {0,0};
    VALUE opts[2] = {Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};

    CHECK_FUNC(func_p,"sgetri");

#if IPIV_IN
# if RHS
    rb_scan_args(argc, argv, "3:", &a, &ipiv, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "2:", &a, &ipiv, &kw_hash);
# endif
#else
# if RHS
    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
# endif
#endif
#if TRANS
    kw_table[1] = id_trans;
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.trans = option_trans(opts[1]);
#elif UPLO
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.uplo = option_uplo(opts[1]);
#else
    rb_get_kwargs(kw_hash, kw_table, 0, 1, opts);
#endif
    g.order = option_order(opts[0]);

#if !RHS
    COPY_OR_CAST_TO(a,cT);
#endif
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
#if IPIV_OUT
    shape_piv[0] = min_(ROW_SIZE(na1),COL_SIZE(na1));
#endif

#if RHS
    COPY_OR_CAST_TO(b,cT);
    GetNArray(b, na2);
    CHECK_DIM_GE(na2, 1);
    n = COL_SIZE(na1);
#if SYM
    n = min_(n,ROW_SIZE(na1));
#endif
    // same as gesv.c
    if (NA_NDIM(na2) == 1) {
        ain[1+IPIV_IN].dim = 1;
        nb = COL_SIZE(na2);
        nrhs = 1;
    } else {
        nb = ROW_SIZE(na2);
        nrhs = COL_SIZE(na2);
        { int tmp; SWAP_IFCOL(g.order,nb,nrhs); }
    }
    if (n != nb) {
        rb_raise(nary_eShapeError, "matrix dimension mismatch: "
                 "a.col(or a.row)=%"SZF"u b.row=%"SZF"u", n, nb);
    }
#endif

#if IPIV_IN
# if RHS
    ans = na_ndloop3(&ndf, &g, 3, a, ipiv, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 2, a, ipiv);
    return rb_assoc_new(a, ans);
# endif
#else
# if RHS
    ans = na_ndloop3(&ndf, &g, 2, a, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 1, a);
#  if IPIV_OUT
    return rb_ary_unshift(ans, a);
#  else
    return rb_assoc_new(a, ans);
#  endif
# endif
#endif
}

#undef args_t
#undef func_p
#undef RHS
#undef TRANS
#undef UPLO
#undef IPIV
#undef IPIV_OUT
#undef IPIV_IN
#undef SYM


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"

#line 10 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#define RHS  1
#define TRANS 1
#define UPLO 0
#define IPIV 1
#define IPIV_OUT 0
#define IPIV_IN 1
#define SYM  1
#define args_t sgetrs_args_t
#define func_p sgetrs_p

typedef struct {
    int order;
    char uplo;
    char trans;
} args_t;

static sgetrs_t func_p = 0;

static void
iter_lapack_s_sgetrs(na_loop_t * const lp)
{
    dtype *a;
#if RHS
    dtype *b;
    int    nb, nrhs, ldb;
#endif
#if IPIV
    int   *pv;
#endif
    int   *info;
    int    m, n, lda;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
#if IPIV
    pv = (int*)NDL_PTR(lp,1);
#endif
#if RHS
    b = (dtype*)NDL_PTR(lp,1+IPIV);
#endif
    info = (int*)NDL_PTR(lp,1+IPIV+RHS);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[0];
    m = NDL_SHAPE(lp,0)[1];
    lda = NDL_STEP(lp,0) / sizeof(dtype);

#if RHS
    // same as gels.c
    if (lp->args[1+IPIV].ndim == 1) {
        nrhs = 1;
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        ldb = (g->order==LAPACK_COL_MAJOR) ? nb : 1;
    } else {
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        nrhs = NDL_SHAPE(lp,1+IPIV)[1];
        ldb = nrhs;
        { int tmp; SWAP_IFCOL(g->order,nb,nrhs); }
    }
    //printf("order=%d m=%d n=%d nb=%d nrhs=%d lda=%d ldb=%d\n",g->order,m,n,nb,nrhs,lda,ldb);
#else
    //printf("order=%d m=%d n=%d lda=%d \n",g->order,m,n,lda);
#endif

#if SYM
    n = min_(m,n);
#else
    { int tmp; SWAP_IFCOL(g->order,m,n); }
#endif

    
#line 91 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    *info = (*func_p)(g->order, g->trans, n, nrhs, a, lda, pv, b, ldb);
    CHECK_ERROR(*info);
}

/*
  @overload sgetrs(a, ipiv, b, [trans:'N', order:'R'])
  @param a [Numo::SFloat] LU matrix computed by sgetrf
  @param ipiv [Numo::Int] pivot computed by sgetrf
  @param b [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param trans [String or Symbol]  if 'N': Not transpose , if 'T': Transpose . (default='N')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[b, info]] Array<Numo::SFloat, Integer>

    - **b** -- 
           B is REAL array, dimension (LDB,NRHS)
           On entry, the right hand side matrix B.
           On exit, the solution matrix X.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value

SGETRS solves a system of linear equations

        A * X = B  or  A**T * X = B

with a general N-by-N matrix A using the LU factorization computed
by SGETRF.

*/
static VALUE
lapack_s_sgetrs(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    VALUE a, ans;
#if IPIV_IN
    VALUE ipiv;
#endif
#if RHS
    VALUE b;
    size_t n, nb, nrhs;
    narray_t *na2;
#endif
    narray_t *na1;
    
#line 160 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#if IPIV_OUT
    size_t shape_piv[1];
#endif
#if IPIV_IN
# if RHS
    ndfunc_arg_in_t ain[3] = {{cT,2},{cInt,1},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{cInt,1}};
# endif
#else
# if RHS
    ndfunc_arg_in_t ain[2] = {{cT,2},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
# endif
#endif
    ndfunc_arg_out_t aout[1+IPIV_OUT] = {{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_sgetrs, NO_LOOP|NDF_EXTRACT,
                    1+IPIV_IN+RHS, IPIV_OUT+1, ain,aout};

    args_t g = {0,0};
    VALUE opts[2] = {Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};

    CHECK_FUNC(func_p,"sgetrs");

#if IPIV_IN
# if RHS
    rb_scan_args(argc, argv, "3:", &a, &ipiv, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "2:", &a, &ipiv, &kw_hash);
# endif
#else
# if RHS
    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
# endif
#endif
#if TRANS
    kw_table[1] = id_trans;
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.trans = option_trans(opts[1]);
#elif UPLO
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.uplo = option_uplo(opts[1]);
#else
    rb_get_kwargs(kw_hash, kw_table, 0, 1, opts);
#endif
    g.order = option_order(opts[0]);

#if !RHS
    COPY_OR_CAST_TO(a,cT);
#endif
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
#if IPIV_OUT
    shape_piv[0] = min_(ROW_SIZE(na1),COL_SIZE(na1));
#endif

#if RHS
    COPY_OR_CAST_TO(b,cT);
    GetNArray(b, na2);
    CHECK_DIM_GE(na2, 1);
    n = COL_SIZE(na1);
#if SYM
    n = min_(n,ROW_SIZE(na1));
#endif
    // same as gesv.c
    if (NA_NDIM(na2) == 1) {
        ain[1+IPIV_IN].dim = 1;
        nb = COL_SIZE(na2);
        nrhs = 1;
    } else {
        nb = ROW_SIZE(na2);
        nrhs = COL_SIZE(na2);
        { int tmp; SWAP_IFCOL(g.order,nb,nrhs); }
    }
    if (n != nb) {
        rb_raise(nary_eShapeError, "matrix dimension mismatch: "
                 "a.col(or a.row)=%"SZF"u b.row=%"SZF"u", n, nb);
    }
#endif

#if IPIV_IN
# if RHS
    ans = na_ndloop3(&ndf, &g, 3, a, ipiv, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 2, a, ipiv);
    return rb_assoc_new(a, ans);
# endif
#else
# if RHS
    ans = na_ndloop3(&ndf, &g, 2, a, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 1, a);
#  if IPIV_OUT
    return rb_ary_unshift(ans, a);
#  else
    return rb_assoc_new(a, ans);
#  endif
# endif
#endif
}

#undef args_t
#undef func_p
#undef RHS
#undef TRANS
#undef UPLO
#undef IPIV
#undef IPIV_OUT
#undef IPIV_IN
#undef SYM


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"

#line 10 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#define RHS  0
#define TRANS 0
#define UPLO 1
#define IPIV 1
#define IPIV_OUT 1
#define IPIV_IN 0
#define SYM  1
#define args_t ssytrf_args_t
#define func_p ssytrf_p

typedef struct {
    int order;
    char uplo;
    char trans;
} args_t;

static ssytrf_t func_p = 0;

static void
iter_lapack_s_ssytrf(na_loop_t * const lp)
{
    dtype *a;
#if RHS
    dtype *b;
    int    nb, nrhs, ldb;
#endif
#if IPIV
    int   *pv;
#endif
    int   *info;
    int    m, n, lda;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
#if IPIV
    pv = (int*)NDL_PTR(lp,1);
#endif
#if RHS
    b = (dtype*)NDL_PTR(lp,1+IPIV);
#endif
    info = (int*)NDL_PTR(lp,1+IPIV+RHS);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[0];
    m = NDL_SHAPE(lp,0)[1];
    lda = NDL_STEP(lp,0) / sizeof(dtype);

#if RHS
    // same as gels.c
    if (lp->args[1+IPIV].ndim == 1) {
        nrhs = 1;
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        ldb = (g->order==LAPACK_COL_MAJOR) ? nb : 1;
    } else {
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        nrhs = NDL_SHAPE(lp,1+IPIV)[1];
        ldb = nrhs;
        { int tmp; SWAP_IFCOL(g->order,nb,nrhs); }
    }
    //printf("order=%d m=%d n=%d nb=%d nrhs=%d lda=%d ldb=%d\n",g->order,m,n,nb,nrhs,lda,ldb);
#else
    //printf("order=%d m=%d n=%d lda=%d \n",g->order,m,n,lda);
#endif

#if SYM
    n = min_(m,n);
#else
    { int tmp; SWAP_IFCOL(g->order,m,n); }
#endif

    
#line 91 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    *info = (*func_p)(g->order, g->uplo, n, a, lda, pv);
    CHECK_ERROR(*info);
}

/*
  @overload ssytrf(a, [uplo:'U', order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param uplo [String or Symbol]  if 'U': Upper triangle, if 'L': Lower triangle. (default='U')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, ipiv, info]] Array<Numo::SFloat, Numo::Int, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the symmetric matrix A.  If UPLO = 'U', the leading
           N-by-N upper triangular part of A contains the upper
           triangular part of the matrix A, and the strictly lower
           triangular part of A is not referenced.  If UPLO = 'L', the
           leading N-by-N lower triangular part of A contains the lower
           triangular part of the matrix A, and the strictly upper
           triangular part of A is not referenced.
           On exit, the block diagonal matrix D and the multipliers used
           to obtain the factor U or L (see below for further details).

    - **ipiv** -- 
           IPIV is INTEGER array, dimension (N)
           Details of the interchanges and the block structure of D.
           If IPIV(k) > 0, then rows and columns k and IPIV(k) were
           interchanged and D(k,k) is a 1-by-1 diagonal block.
           If UPLO = 'U' and IPIV(k) = IPIV(k-1) < 0, then rows and
           columns k-1 and -IPIV(k) were interchanged and D(k-1:k,k-1:k)
           is a 2-by-2 diagonal block.  If UPLO = 'L' and IPIV(k) =
           IPIV(k+1) < 0, then rows and columns k+1 and -IPIV(k) were
           interchanged and D(k:k+1,k:k+1) is a 2-by-2 diagonal block.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value
           > 0:  if INFO = i, D(i,i) is exactly zero.  The factorization
                 has been completed, but the block diagonal matrix D is
                 exactly singular, and division by zero will occur if it
                 is used to solve a system of equations.

SSYTRF computes the factorization of a real symmetric matrix A using
the Bunch-Kaufman diagonal pivoting method.  The form of the
factorization is

        A = U*D*U**T  or  A = L*D*L**T

where U (or L) is a product of permutation and unit upper (lower)
triangular matrices, and D is symmetric and block diagonal with
1-by-1 and 2-by-2 diagonal blocks.
This is the blocked version of the algorithm, calling Level 3 BLAS.

*/
static VALUE
lapack_s_ssytrf(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    VALUE a, ans;
#if IPIV_IN
    VALUE ipiv;
#endif
#if RHS
    VALUE b;
    size_t n, nb, nrhs;
    narray_t *na2;
#endif
    narray_t *na1;
    
#line 160 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#if IPIV_OUT
    size_t shape_piv[1];
#endif
#if IPIV_IN
# if RHS
    ndfunc_arg_in_t ain[3] = {{cT,2},{cInt,1},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{cInt,1}};
# endif
#else
# if RHS
    ndfunc_arg_in_t ain[2] = {{cT,2},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
# endif
#endif
    ndfunc_arg_out_t aout[1+IPIV_OUT] = {{cInt,1,shape_piv},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_ssytrf, NO_LOOP|NDF_EXTRACT,
                    1+IPIV_IN+RHS, IPIV_OUT+1, ain,aout};

    args_t g = {0,0};
    VALUE opts[2] = {Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};

    CHECK_FUNC(func_p,"ssytrf");

#if IPIV_IN
# if RHS
    rb_scan_args(argc, argv, "3:", &a, &ipiv, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "2:", &a, &ipiv, &kw_hash);
# endif
#else
# if RHS
    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
# endif
#endif
#if TRANS
    kw_table[1] = id_trans;
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.trans = option_trans(opts[1]);
#elif UPLO
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.uplo = option_uplo(opts[1]);
#else
    rb_get_kwargs(kw_hash, kw_table, 0, 1, opts);
#endif
    g.order = option_order(opts[0]);

#if !RHS
    COPY_OR_CAST_TO(a,cT);
#endif
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
#if IPIV_OUT
    shape_piv[0] = min_(ROW_SIZE(na1),COL_SIZE(na1));
#endif

#if RHS
    COPY_OR_CAST_TO(b,cT);
    GetNArray(b, na2);
    CHECK_DIM_GE(na2, 1);
    n = COL_SIZE(na1);
#if SYM
    n = min_(n,ROW_SIZE(na1));
#endif
    // same as gesv.c
    if (NA_NDIM(na2) == 1) {
        ain[1+IPIV_IN].dim = 1;
        nb = COL_SIZE(na2);
        nrhs = 1;
    } else {
        nb = ROW_SIZE(na2);
        nrhs = COL_SIZE(na2);
        { int tmp; SWAP_IFCOL(g.order,nb,nrhs); }
    }
    if (n != nb) {
        rb_raise(nary_eShapeError, "matrix dimension mismatch: "
                 "a.col(or a.row)=%"SZF"u b.row=%"SZF"u", n, nb);
    }
#endif

#if IPIV_IN
# if RHS
    ans = na_ndloop3(&ndf, &g, 3, a, ipiv, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 2, a, ipiv);
    return rb_assoc_new(a, ans);
# endif
#else
# if RHS
    ans = na_ndloop3(&ndf, &g, 2, a, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 1, a);
#  if IPIV_OUT
    return rb_ary_unshift(ans, a);
#  else
    return rb_assoc_new(a, ans);
#  endif
# endif
#endif
}

#undef args_t
#undef func_p
#undef RHS
#undef TRANS
#undef UPLO
#undef IPIV
#undef IPIV_OUT
#undef IPIV_IN
#undef SYM


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"

#line 10 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#define RHS  0
#define TRANS 0
#define UPLO 1
#define IPIV 1
#define IPIV_OUT 0
#define IPIV_IN 1
#define SYM  1
#define args_t ssytri_args_t
#define func_p ssytri_p

typedef struct {
    int order;
    char uplo;
    char trans;
} args_t;

static ssytri_t func_p = 0;

static void
iter_lapack_s_ssytri(na_loop_t * const lp)
{
    dtype *a;
#if RHS
    dtype *b;
    int    nb, nrhs, ldb;
#endif
#if IPIV
    int   *pv;
#endif
    int   *info;
    int    m, n, lda;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
#if IPIV
    pv = (int*)NDL_PTR(lp,1);
#endif
#if RHS
    b = (dtype*)NDL_PTR(lp,1+IPIV);
#endif
    info = (int*)NDL_PTR(lp,1+IPIV+RHS);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[0];
    m = NDL_SHAPE(lp,0)[1];
    lda = NDL_STEP(lp,0) / sizeof(dtype);

#if RHS
    // same as gels.c
    if (lp->args[1+IPIV].ndim == 1) {
        nrhs = 1;
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        ldb = (g->order==LAPACK_COL_MAJOR) ? nb : 1;
    } else {
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        nrhs = NDL_SHAPE(lp,1+IPIV)[1];
        ldb = nrhs;
        { int tmp; SWAP_IFCOL(g->order,nb,nrhs); }
    }
    //printf("order=%d m=%d n=%d nb=%d nrhs=%d lda=%d ldb=%d\n",g->order,m,n,nb,nrhs,lda,ldb);
#else
    //printf("order=%d m=%d n=%d lda=%d \n",g->order,m,n,lda);
#endif

#if SYM
    n = min_(m,n);
#else
    { int tmp; SWAP_IFCOL(g->order,m,n); }
#endif

    
#line 91 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    *info = (*func_p)(g->order, g->uplo, n, a, lda, pv);
    CHECK_ERROR(*info);
}

/*
  @overload ssytri(a, ipiv, [uplo:'U', order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param ipiv [Numo::Int] pivot computed by ssytrf
  @param uplo [String or Symbol]  if 'U': Upper triangle, if 'L': Lower triangle. (default='U')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, info]] Array<Numo::SFloat, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the block diagonal matrix D and the multipliers
           used to obtain the factor U or L as computed by SSYTRF.
           On exit, if INFO = 0, the (symmetric) inverse of the original
           matrix.  If UPLO = 'U', the upper triangular part of the
           inverse is formed and the part of A below the diagonal is not
           referenced; if UPLO = 'L' the lower triangular part of the
           inverse is formed and the part of A above the diagonal is
           not referenced.

    - **info** -- 
           INFO is INTEGER
           = 0: successful exit
           < 0: if INFO = -i, the i-th argument had an illegal value
           > 0: if INFO = i, D(i,i) = 0; the matrix is singular and its
                inverse could not be computed.

SSYTRI computes the inverse of a real symmetric indefinite matrix
A using the factorization A = U\*D\*U\*\*T or A = L\*D\*L\*\*T computed by
SSYTRF.

*/
static VALUE
lapack_s_ssytri(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    VALUE a, ans;
#if IPIV_IN
    VALUE ipiv;
#endif
#if RHS
    VALUE b;
    size_t n, nb, nrhs;
    narray_t *na2;
#endif
    narray_t *na1;
    
#line 160 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#if IPIV_OUT
    size_t shape_piv[1];
#endif
#if IPIV_IN
# if RHS
    ndfunc_arg_in_t ain[3] = {{cT,2},{cInt,1},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{cInt,1}};
# endif
#else
# if RHS
    ndfunc_arg_in_t ain[2] = {{cT,2},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
# endif
#endif
    ndfunc_arg_out_t aout[1+IPIV_OUT] = {{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_ssytri, NO_LOOP|NDF_EXTRACT,
                    1+IPIV_IN+RHS, IPIV_OUT+1, ain,aout};

    args_t g = {0,0};
    VALUE opts[2] = {Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};

    CHECK_FUNC(func_p,"ssytri");

#if IPIV_IN
# if RHS
    rb_scan_args(argc, argv, "3:", &a, &ipiv, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "2:", &a, &ipiv, &kw_hash);
# endif
#else
# if RHS
    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
# endif
#endif
#if TRANS
    kw_table[1] = id_trans;
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.trans = option_trans(opts[1]);
#elif UPLO
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.uplo = option_uplo(opts[1]);
#else
    rb_get_kwargs(kw_hash, kw_table, 0, 1, opts);
#endif
    g.order = option_order(opts[0]);

#if !RHS
    COPY_OR_CAST_TO(a,cT);
#endif
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
#if IPIV_OUT
    shape_piv[0] = min_(ROW_SIZE(na1),COL_SIZE(na1));
#endif

#if RHS
    COPY_OR_CAST_TO(b,cT);
    GetNArray(b, na2);
    CHECK_DIM_GE(na2, 1);
    n = COL_SIZE(na1);
#if SYM
    n = min_(n,ROW_SIZE(na1));
#endif
    // same as gesv.c
    if (NA_NDIM(na2) == 1) {
        ain[1+IPIV_IN].dim = 1;
        nb = COL_SIZE(na2);
        nrhs = 1;
    } else {
        nb = ROW_SIZE(na2);
        nrhs = COL_SIZE(na2);
        { int tmp; SWAP_IFCOL(g.order,nb,nrhs); }
    }
    if (n != nb) {
        rb_raise(nary_eShapeError, "matrix dimension mismatch: "
                 "a.col(or a.row)=%"SZF"u b.row=%"SZF"u", n, nb);
    }
#endif

#if IPIV_IN
# if RHS
    ans = na_ndloop3(&ndf, &g, 3, a, ipiv, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 2, a, ipiv);
    return rb_assoc_new(a, ans);
# endif
#else
# if RHS
    ans = na_ndloop3(&ndf, &g, 2, a, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 1, a);
#  if IPIV_OUT
    return rb_ary_unshift(ans, a);
#  else
    return rb_assoc_new(a, ans);
#  endif
# endif
#endif
}

#undef args_t
#undef func_p
#undef RHS
#undef TRANS
#undef UPLO
#undef IPIV
#undef IPIV_OUT
#undef IPIV_IN
#undef SYM


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"

#line 10 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#define RHS  1
#define TRANS 0
#define UPLO 1
#define IPIV 1
#define IPIV_OUT 0
#define IPIV_IN 1
#define SYM  1
#define args_t ssytrs_args_t
#define func_p ssytrs_p

typedef struct {
    int order;
    char uplo;
    char trans;
} args_t;

static ssytrs_t func_p = 0;

static void
iter_lapack_s_ssytrs(na_loop_t * const lp)
{
    dtype *a;
#if RHS
    dtype *b;
    int    nb, nrhs, ldb;
#endif
#if IPIV
    int   *pv;
#endif
    int   *info;
    int    m, n, lda;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
#if IPIV
    pv = (int*)NDL_PTR(lp,1);
#endif
#if RHS
    b = (dtype*)NDL_PTR(lp,1+IPIV);
#endif
    info = (int*)NDL_PTR(lp,1+IPIV+RHS);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[0];
    m = NDL_SHAPE(lp,0)[1];
    lda = NDL_STEP(lp,0) / sizeof(dtype);

#if RHS
    // same as gels.c
    if (lp->args[1+IPIV].ndim == 1) {
        nrhs = 1;
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        ldb = (g->order==LAPACK_COL_MAJOR) ? nb : 1;
    } else {
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        nrhs = NDL_SHAPE(lp,1+IPIV)[1];
        ldb = nrhs;
        { int tmp; SWAP_IFCOL(g->order,nb,nrhs); }
    }
    //printf("order=%d m=%d n=%d nb=%d nrhs=%d lda=%d ldb=%d\n",g->order,m,n,nb,nrhs,lda,ldb);
#else
    //printf("order=%d m=%d n=%d lda=%d \n",g->order,m,n,lda);
#endif

#if SYM
    n = min_(m,n);
#else
    { int tmp; SWAP_IFCOL(g->order,m,n); }
#endif

    
#line 91 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    *info = (*func_p)(g->order, g->uplo, n, nrhs, a, lda, pv, b, ldb);
    CHECK_ERROR(*info);
}

/*
  @overload ssytrs(a, ipiv, b, [uplo:'U', order:'R'])
  @param a [Numo::SFloat] LU matrix computed by ssytrf
  @param ipiv [Numo::Int] pivot computed by ssytrf
  @param b [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param uplo [String or Symbol]  if 'U': Upper triangle, if 'L': Lower triangle. (default='U')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[b, info]] Array<Numo::SFloat, Integer>

    - **b** -- 
           B is REAL array, dimension (LDB,NRHS)
           On entry, the right hand side matrix B.
           On exit, the solution matrix X.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value

SSYTRS solves a system of linear equations A\*X = B with a real
symmetric matrix A using the factorization A = U\*D\*U\*\*T or
A = L\*D\*L\*\*T computed by SSYTRF.

*/
static VALUE
lapack_s_ssytrs(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    VALUE a, ans;
#if IPIV_IN
    VALUE ipiv;
#endif
#if RHS
    VALUE b;
    size_t n, nb, nrhs;
    narray_t *na2;
#endif
    narray_t *na1;
    
#line 160 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#if IPIV_OUT
    size_t shape_piv[1];
#endif
#if IPIV_IN
# if RHS
    ndfunc_arg_in_t ain[3] = {{cT,2},{cInt,1},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{cInt,1}};
# endif
#else
# if RHS
    ndfunc_arg_in_t ain[2] = {{cT,2},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
# endif
#endif
    ndfunc_arg_out_t aout[1+IPIV_OUT] = {{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_ssytrs, NO_LOOP|NDF_EXTRACT,
                    1+IPIV_IN+RHS, IPIV_OUT+1, ain,aout};

    args_t g = {0,0};
    VALUE opts[2] = {Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};

    CHECK_FUNC(func_p,"ssytrs");

#if IPIV_IN
# if RHS
    rb_scan_args(argc, argv, "3:", &a, &ipiv, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "2:", &a, &ipiv, &kw_hash);
# endif
#else
# if RHS
    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
# endif
#endif
#if TRANS
    kw_table[1] = id_trans;
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.trans = option_trans(opts[1]);
#elif UPLO
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.uplo = option_uplo(opts[1]);
#else
    rb_get_kwargs(kw_hash, kw_table, 0, 1, opts);
#endif
    g.order = option_order(opts[0]);

#if !RHS
    COPY_OR_CAST_TO(a,cT);
#endif
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
#if IPIV_OUT
    shape_piv[0] = min_(ROW_SIZE(na1),COL_SIZE(na1));
#endif

#if RHS
    COPY_OR_CAST_TO(b,cT);
    GetNArray(b, na2);
    CHECK_DIM_GE(na2, 1);
    n = COL_SIZE(na1);
#if SYM
    n = min_(n,ROW_SIZE(na1));
#endif
    // same as gesv.c
    if (NA_NDIM(na2) == 1) {
        ain[1+IPIV_IN].dim = 1;
        nb = COL_SIZE(na2);
        nrhs = 1;
    } else {
        nb = ROW_SIZE(na2);
        nrhs = COL_SIZE(na2);
        { int tmp; SWAP_IFCOL(g.order,nb,nrhs); }
    }
    if (n != nb) {
        rb_raise(nary_eShapeError, "matrix dimension mismatch: "
                 "a.col(or a.row)=%"SZF"u b.row=%"SZF"u", n, nb);
    }
#endif

#if IPIV_IN
# if RHS
    ans = na_ndloop3(&ndf, &g, 3, a, ipiv, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 2, a, ipiv);
    return rb_assoc_new(a, ans);
# endif
#else
# if RHS
    ans = na_ndloop3(&ndf, &g, 2, a, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 1, a);
#  if IPIV_OUT
    return rb_ary_unshift(ans, a);
#  else
    return rb_assoc_new(a, ans);
#  endif
# endif
#endif
}

#undef args_t
#undef func_p
#undef RHS
#undef TRANS
#undef UPLO
#undef IPIV
#undef IPIV_OUT
#undef IPIV_IN
#undef SYM


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"

#line 10 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#define RHS  0
#define TRANS 0
#define UPLO 1
#define IPIV 0
#define IPIV_OUT 0
#define IPIV_IN 0
#define SYM  1
#define args_t spotrf_args_t
#define func_p spotrf_p

typedef struct {
    int order;
    char uplo;
    char trans;
} args_t;

static spotrf_t func_p = 0;

static void
iter_lapack_s_spotrf(na_loop_t * const lp)
{
    dtype *a;
#if RHS
    dtype *b;
    int    nb, nrhs, ldb;
#endif
#if IPIV
    int   *pv;
#endif
    int   *info;
    int    m, n, lda;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
#if IPIV
    pv = (int*)NDL_PTR(lp,1);
#endif
#if RHS
    b = (dtype*)NDL_PTR(lp,1+IPIV);
#endif
    info = (int*)NDL_PTR(lp,1+IPIV+RHS);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[0];
    m = NDL_SHAPE(lp,0)[1];
    lda = NDL_STEP(lp,0) / sizeof(dtype);

#if RHS
    // same as gels.c
    if (lp->args[1+IPIV].ndim == 1) {
        nrhs = 1;
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        ldb = (g->order==LAPACK_COL_MAJOR) ? nb : 1;
    } else {
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        nrhs = NDL_SHAPE(lp,1+IPIV)[1];
        ldb = nrhs;
        { int tmp; SWAP_IFCOL(g->order,nb,nrhs); }
    }
    //printf("order=%d m=%d n=%d nb=%d nrhs=%d lda=%d ldb=%d\n",g->order,m,n,nb,nrhs,lda,ldb);
#else
    //printf("order=%d m=%d n=%d lda=%d \n",g->order,m,n,lda);
#endif

#if SYM
    n = min_(m,n);
#else
    { int tmp; SWAP_IFCOL(g->order,m,n); }
#endif

    
#line 91 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    *info = (*func_p)(g->order, g->uplo, n, a, lda);
    CHECK_ERROR(*info);
}

/*
  @overload spotrf(a, [uplo:'U', order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param uplo [String or Symbol]  if 'U': Upper triangle, if 'L': Lower triangle. (default='U')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, info]] Array<Numo::SFloat, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the symmetric matrix A.  If UPLO = 'U', the leading
           N-by-N upper triangular part of A contains the upper
           triangular part of the matrix A, and the strictly lower
           triangular part of A is not referenced.  If UPLO = 'L', the
           leading N-by-N lower triangular part of A contains the lower
           triangular part of the matrix A, and the strictly upper
           triangular part of A is not referenced.
           On exit, if INFO = 0, the factor U or L from the Cholesky
           factorization A = U\*\*T\*U or A = L\*L\*\*T.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value
           > 0:  if INFO = i, the leading minor of order i is not
                 positive definite, and the factorization could not be
                 completed.

SPOTRF computes the Cholesky factorization of a real symmetric
positive definite matrix A.
The factorization has the form

        A = U**T * U,  if UPLO = 'U', or
        A = L  * L**T,  if UPLO = 'L',

where U is an upper triangular matrix and L is lower triangular.
This is the block version of the algorithm, calling Level 3 BLAS.

*/
static VALUE
lapack_s_spotrf(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    VALUE a, ans;
#if IPIV_IN
    VALUE ipiv;
#endif
#if RHS
    VALUE b;
    size_t n, nb, nrhs;
    narray_t *na2;
#endif
    narray_t *na1;
    
#line 160 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#if IPIV_OUT
    size_t shape_piv[1];
#endif
#if IPIV_IN
# if RHS
    ndfunc_arg_in_t ain[3] = {{cT,2},{cInt,1},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{cInt,1}};
# endif
#else
# if RHS
    ndfunc_arg_in_t ain[2] = {{cT,2},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
# endif
#endif
    ndfunc_arg_out_t aout[1+IPIV_OUT] = {{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_spotrf, NO_LOOP|NDF_EXTRACT,
                    1+IPIV_IN+RHS, IPIV_OUT+1, ain,aout};

    args_t g = {0,0};
    VALUE opts[2] = {Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};

    CHECK_FUNC(func_p,"spotrf");

#if IPIV_IN
# if RHS
    rb_scan_args(argc, argv, "3:", &a, &ipiv, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "2:", &a, &ipiv, &kw_hash);
# endif
#else
# if RHS
    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
# endif
#endif
#if TRANS
    kw_table[1] = id_trans;
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.trans = option_trans(opts[1]);
#elif UPLO
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.uplo = option_uplo(opts[1]);
#else
    rb_get_kwargs(kw_hash, kw_table, 0, 1, opts);
#endif
    g.order = option_order(opts[0]);

#if !RHS
    COPY_OR_CAST_TO(a,cT);
#endif
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
#if IPIV_OUT
    shape_piv[0] = min_(ROW_SIZE(na1),COL_SIZE(na1));
#endif

#if RHS
    COPY_OR_CAST_TO(b,cT);
    GetNArray(b, na2);
    CHECK_DIM_GE(na2, 1);
    n = COL_SIZE(na1);
#if SYM
    n = min_(n,ROW_SIZE(na1));
#endif
    // same as gesv.c
    if (NA_NDIM(na2) == 1) {
        ain[1+IPIV_IN].dim = 1;
        nb = COL_SIZE(na2);
        nrhs = 1;
    } else {
        nb = ROW_SIZE(na2);
        nrhs = COL_SIZE(na2);
        { int tmp; SWAP_IFCOL(g.order,nb,nrhs); }
    }
    if (n != nb) {
        rb_raise(nary_eShapeError, "matrix dimension mismatch: "
                 "a.col(or a.row)=%"SZF"u b.row=%"SZF"u", n, nb);
    }
#endif

#if IPIV_IN
# if RHS
    ans = na_ndloop3(&ndf, &g, 3, a, ipiv, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 2, a, ipiv);
    return rb_assoc_new(a, ans);
# endif
#else
# if RHS
    ans = na_ndloop3(&ndf, &g, 2, a, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 1, a);
#  if IPIV_OUT
    return rb_ary_unshift(ans, a);
#  else
    return rb_assoc_new(a, ans);
#  endif
# endif
#endif
}

#undef args_t
#undef func_p
#undef RHS
#undef TRANS
#undef UPLO
#undef IPIV
#undef IPIV_OUT
#undef IPIV_IN
#undef SYM


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"

#line 10 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#define RHS  0
#define TRANS 0
#define UPLO 1
#define IPIV 0
#define IPIV_OUT 0
#define IPIV_IN 0
#define SYM  1
#define args_t spotri_args_t
#define func_p spotri_p

typedef struct {
    int order;
    char uplo;
    char trans;
} args_t;

static spotri_t func_p = 0;

static void
iter_lapack_s_spotri(na_loop_t * const lp)
{
    dtype *a;
#if RHS
    dtype *b;
    int    nb, nrhs, ldb;
#endif
#if IPIV
    int   *pv;
#endif
    int   *info;
    int    m, n, lda;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
#if IPIV
    pv = (int*)NDL_PTR(lp,1);
#endif
#if RHS
    b = (dtype*)NDL_PTR(lp,1+IPIV);
#endif
    info = (int*)NDL_PTR(lp,1+IPIV+RHS);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[0];
    m = NDL_SHAPE(lp,0)[1];
    lda = NDL_STEP(lp,0) / sizeof(dtype);

#if RHS
    // same as gels.c
    if (lp->args[1+IPIV].ndim == 1) {
        nrhs = 1;
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        ldb = (g->order==LAPACK_COL_MAJOR) ? nb : 1;
    } else {
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        nrhs = NDL_SHAPE(lp,1+IPIV)[1];
        ldb = nrhs;
        { int tmp; SWAP_IFCOL(g->order,nb,nrhs); }
    }
    //printf("order=%d m=%d n=%d nb=%d nrhs=%d lda=%d ldb=%d\n",g->order,m,n,nb,nrhs,lda,ldb);
#else
    //printf("order=%d m=%d n=%d lda=%d \n",g->order,m,n,lda);
#endif

#if SYM
    n = min_(m,n);
#else
    { int tmp; SWAP_IFCOL(g->order,m,n); }
#endif

    
#line 91 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    *info = (*func_p)(g->order, g->uplo, n, a, lda);
    CHECK_ERROR(*info);
}

/*
  @overload spotri(a, [uplo:'U', order:'R'])
  @param a [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param uplo [String or Symbol]  if 'U': Upper triangle, if 'L': Lower triangle. (default='U')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, info]] Array<Numo::SFloat, Integer>

    - **a** -- 
           A is REAL array, dimension (LDA,N)
           On entry, the triangular factor U or L from the Cholesky
           factorization A = U\*\*T\*U or A = L\*L\*\*T, as computed by
           SPOTRF.
           On exit, the upper or lower triangle of the (symmetric)
           inverse of A, overwriting the input factor U or L.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value
           > 0:  if INFO = i, the (i,i) element of the factor U or L is
                 zero, and the inverse could not be computed.

SPOTRI computes the inverse of a real symmetric positive definite
matrix A using the Cholesky factorization A = U\*\*T\*U or A = L\*L\*\*T
computed by SPOTRF.

*/
static VALUE
lapack_s_spotri(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    VALUE a, ans;
#if IPIV_IN
    VALUE ipiv;
#endif
#if RHS
    VALUE b;
    size_t n, nb, nrhs;
    narray_t *na2;
#endif
    narray_t *na1;
    
#line 160 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#if IPIV_OUT
    size_t shape_piv[1];
#endif
#if IPIV_IN
# if RHS
    ndfunc_arg_in_t ain[3] = {{cT,2},{cInt,1},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{cInt,1}};
# endif
#else
# if RHS
    ndfunc_arg_in_t ain[2] = {{cT,2},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
# endif
#endif
    ndfunc_arg_out_t aout[1+IPIV_OUT] = {{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_spotri, NO_LOOP|NDF_EXTRACT,
                    1+IPIV_IN+RHS, IPIV_OUT+1, ain,aout};

    args_t g = {0,0};
    VALUE opts[2] = {Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};

    CHECK_FUNC(func_p,"spotri");

#if IPIV_IN
# if RHS
    rb_scan_args(argc, argv, "3:", &a, &ipiv, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "2:", &a, &ipiv, &kw_hash);
# endif
#else
# if RHS
    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
# endif
#endif
#if TRANS
    kw_table[1] = id_trans;
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.trans = option_trans(opts[1]);
#elif UPLO
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.uplo = option_uplo(opts[1]);
#else
    rb_get_kwargs(kw_hash, kw_table, 0, 1, opts);
#endif
    g.order = option_order(opts[0]);

#if !RHS
    COPY_OR_CAST_TO(a,cT);
#endif
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
#if IPIV_OUT
    shape_piv[0] = min_(ROW_SIZE(na1),COL_SIZE(na1));
#endif

#if RHS
    COPY_OR_CAST_TO(b,cT);
    GetNArray(b, na2);
    CHECK_DIM_GE(na2, 1);
    n = COL_SIZE(na1);
#if SYM
    n = min_(n,ROW_SIZE(na1));
#endif
    // same as gesv.c
    if (NA_NDIM(na2) == 1) {
        ain[1+IPIV_IN].dim = 1;
        nb = COL_SIZE(na2);
        nrhs = 1;
    } else {
        nb = ROW_SIZE(na2);
        nrhs = COL_SIZE(na2);
        { int tmp; SWAP_IFCOL(g.order,nb,nrhs); }
    }
    if (n != nb) {
        rb_raise(nary_eShapeError, "matrix dimension mismatch: "
                 "a.col(or a.row)=%"SZF"u b.row=%"SZF"u", n, nb);
    }
#endif

#if IPIV_IN
# if RHS
    ans = na_ndloop3(&ndf, &g, 3, a, ipiv, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 2, a, ipiv);
    return rb_assoc_new(a, ans);
# endif
#else
# if RHS
    ans = na_ndloop3(&ndf, &g, 2, a, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 1, a);
#  if IPIV_OUT
    return rb_ary_unshift(ans, a);
#  else
    return rb_assoc_new(a, ans);
#  endif
# endif
#endif
}

#undef args_t
#undef func_p
#undef RHS
#undef TRANS
#undef UPLO
#undef IPIV
#undef IPIV_OUT
#undef IPIV_IN
#undef SYM


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"

#line 10 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#define RHS  1
#define TRANS 0
#define UPLO 1
#define IPIV 0
#define IPIV_OUT 0
#define IPIV_IN 0
#define SYM  1
#define args_t spotrs_args_t
#define func_p spotrs_p

typedef struct {
    int order;
    char uplo;
    char trans;
} args_t;

static spotrs_t func_p = 0;

static void
iter_lapack_s_spotrs(na_loop_t * const lp)
{
    dtype *a;
#if RHS
    dtype *b;
    int    nb, nrhs, ldb;
#endif
#if IPIV
    int   *pv;
#endif
    int   *info;
    int    m, n, lda;
    args_t *g;

    a = (dtype*)NDL_PTR(lp,0);
#if IPIV
    pv = (int*)NDL_PTR(lp,1);
#endif
#if RHS
    b = (dtype*)NDL_PTR(lp,1+IPIV);
#endif
    info = (int*)NDL_PTR(lp,1+IPIV+RHS);
    g = (args_t*)(lp->opt_ptr);

    n = NDL_SHAPE(lp,0)[0];
    m = NDL_SHAPE(lp,0)[1];
    lda = NDL_STEP(lp,0) / sizeof(dtype);

#if RHS
    // same as gels.c
    if (lp->args[1+IPIV].ndim == 1) {
        nrhs = 1;
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        ldb = (g->order==LAPACK_COL_MAJOR) ? nb : 1;
    } else {
        nb = NDL_SHAPE(lp,1+IPIV)[0];
        nrhs = NDL_SHAPE(lp,1+IPIV)[1];
        ldb = nrhs;
        { int tmp; SWAP_IFCOL(g->order,nb,nrhs); }
    }
    //printf("order=%d m=%d n=%d nb=%d nrhs=%d lda=%d ldb=%d\n",g->order,m,n,nb,nrhs,lda,ldb);
#else
    //printf("order=%d m=%d n=%d lda=%d \n",g->order,m,n,lda);
#endif

#if SYM
    n = min_(m,n);
#else
    { int tmp; SWAP_IFCOL(g->order,m,n); }
#endif

    
#line 91 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    *info = (*func_p)(g->order, g->uplo, n, nrhs, a, lda, b, ldb);
    CHECK_ERROR(*info);
}

/*
  @overload spotrs(a, b, [uplo:'U', order:'R'])
  @param a [Numo::SFloat] LU matrix computed by spotrf
  @param b [Numo::SFloat]  matrix (>=2-dimentional NArray, inplace allowed).
  @param uplo [String or Symbol]  if 'U': Upper triangle, if 'L': Lower triangle. (default='U')
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[b, info]] Array<Numo::SFloat, Integer>

    - **b** -- 
           B is REAL array, dimension (LDB,NRHS)
           On entry, the right hand side matrix B.
           On exit, the solution matrix X.

    - **info** -- 
           INFO is INTEGER
           = 0:  successful exit
           < 0:  if INFO = -i, the i-th argument had an illegal value

SPOTRS solves a system of linear equations A\*X = B with a symmetric
positive definite matrix A using the Cholesky factorization
A = U\*\*T\*U or A = L\*L\*\*T computed by SPOTRF.

*/
static VALUE
lapack_s_spotrs(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
    VALUE a, ans;
#if IPIV_IN
    VALUE ipiv;
#endif
#if RHS
    VALUE b;
    size_t n, nb, nrhs;
    narray_t *na2;
#endif
    narray_t *na1;
    
#line 160 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/trf.c"
#if IPIV_OUT
    size_t shape_piv[1];
#endif
#if IPIV_IN
# if RHS
    ndfunc_arg_in_t ain[3] = {{cT,2},{cInt,1},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[2] = {{OVERWRITE,2},{cInt,1}};
# endif
#else
# if RHS
    ndfunc_arg_in_t ain[2] = {{cT,2},{OVERWRITE,2}};
# else
    ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
# endif
#endif
    ndfunc_arg_out_t aout[1+IPIV_OUT] = {{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_spotrs, NO_LOOP|NDF_EXTRACT,
                    1+IPIV_IN+RHS, IPIV_OUT+1, ain,aout};

    args_t g = {0,0};
    VALUE opts[2] = {Qundef,Qundef};
    VALUE kw_hash = Qnil;
    ID kw_table[2] = {id_order,id_uplo};

    CHECK_FUNC(func_p,"spotrs");

#if IPIV_IN
# if RHS
    rb_scan_args(argc, argv, "3:", &a, &ipiv, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "2:", &a, &ipiv, &kw_hash);
# endif
#else
# if RHS
    rb_scan_args(argc, argv, "2:", &a, &b, &kw_hash);
# else
    rb_scan_args(argc, argv, "1:", &a, &kw_hash);
# endif
#endif
#if TRANS
    kw_table[1] = id_trans;
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.trans = option_trans(opts[1]);
#elif UPLO
    rb_get_kwargs(kw_hash, kw_table, 0, 2, opts);
    g.uplo = option_uplo(opts[1]);
#else
    rb_get_kwargs(kw_hash, kw_table, 0, 1, opts);
#endif
    g.order = option_order(opts[0]);

#if !RHS
    COPY_OR_CAST_TO(a,cT);
#endif
    GetNArray(a, na1);
    CHECK_DIM_GE(na1, 2);
#if IPIV_OUT
    shape_piv[0] = min_(ROW_SIZE(na1),COL_SIZE(na1));
#endif

#if RHS
    COPY_OR_CAST_TO(b,cT);
    GetNArray(b, na2);
    CHECK_DIM_GE(na2, 1);
    n = COL_SIZE(na1);
#if SYM
    n = min_(n,ROW_SIZE(na1));
#endif
    // same as gesv.c
    if (NA_NDIM(na2) == 1) {
        ain[1+IPIV_IN].dim = 1;
        nb = COL_SIZE(na2);
        nrhs = 1;
    } else {
        nb = ROW_SIZE(na2);
        nrhs = COL_SIZE(na2);
        { int tmp; SWAP_IFCOL(g.order,nb,nrhs); }
    }
    if (n != nb) {
        rb_raise(nary_eShapeError, "matrix dimension mismatch: "
                 "a.col(or a.row)=%"SZF"u b.row=%"SZF"u", n, nb);
    }
#endif

#if IPIV_IN
# if RHS
    ans = na_ndloop3(&ndf, &g, 3, a, ipiv, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 2, a, ipiv);
    return rb_assoc_new(a, ans);
# endif
#else
# if RHS
    ans = na_ndloop3(&ndf, &g, 2, a, b);
    return rb_assoc_new(b, ans);
# else
    ans = na_ndloop3(&ndf, &g, 1, a);
#  if IPIV_OUT
    return rb_ary_unshift(ans, a);
#  else
    return rb_assoc_new(a, ans);
#  endif
# endif
#endif
}

#undef args_t
#undef func_p
#undef RHS
#undef TRANS
#undef UPLO
#undef IPIV
#undef IPIV_OUT
#undef IPIV_IN
#undef SYM



#line 27 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/lib.c"
void
Init_numo_linalg_lapack_s(void)
{
    VALUE mN;

    mN = rb_define_module("Numo");

    
    id_axis = rb_intern("axis");
    id_il = rb_intern("il");
    id_itype = rb_intern("itype");
    id_iu = rb_intern("iu");
    id_jobu = rb_intern("jobu");
    id_jobvl = rb_intern("jobvl");
    id_jobvr = rb_intern("jobvr");
    id_jobvt = rb_intern("jobvt");
    id_jobz = rb_intern("jobz");
    id_keepdims = rb_intern("keepdims");
    id_norm = rb_intern("norm");
    id_order = rb_intern("order");
    id_range = rb_intern("range");
    id_rcond = rb_intern("rcond");
    id_trans = rb_intern("trans");
    id_uplo = rb_intern("uplo");


#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/init_module.c"
    /*
      Document-module: Numo::Linalg
      
    */
    
    mLinalg = rb_define_module_under(mN, "Linalg");
    
    

#line 11 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/init_module.c"
    //  how to do this?
    //rb_extend_object(cT, mTM);

#line 1 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/init_module.c"
    /*
      Document-module: Numo::Linalg::Lapack
      
    */
    
    mLapack = rb_define_module_under(mLinalg, "Lapack");
    
    
    /**/
    eLapackError = rb_define_class_under(mLinalg,"LapackError",rb_eStandardError);
    
    rb_define_module_function(mLapack, "slange", lapack_s_slange, -1);
    rb_define_module_function(mLapack, "sgesv", lapack_s_sgesv, -1);
    rb_define_module_function(mLapack, "ssysv", lapack_s_ssysv, -1);
    rb_define_module_function(mLapack, "sposv", lapack_s_sposv, -1);
    rb_define_module_function(mLapack, "sgesvd", lapack_s_sgesvd, -1);
    rb_define_module_function(mLapack, "sgesdd", lapack_s_sgesdd, -1);
    rb_define_module_function(mLapack, "sgels", lapack_s_sgels, -1);
    rb_define_module_function(mLapack, "sgelss", lapack_s_sgelss, -1);
    rb_define_module_function(mLapack, "sgelsd", lapack_s_sgelsd, -1);
    rb_define_module_function(mLapack, "sgelsy", lapack_s_sgelsy, -1);
    rb_define_module_function(mLapack, "sgeev", lapack_s_sgeev, -1);
    rb_define_module_function(mLapack, "sggev", lapack_s_sggev, -1);
    rb_define_module_function(mLapack, "ssyev", lapack_s_ssyev, -1);
    rb_define_module_function(mLapack, "ssyevd", lapack_s_ssyevd, -1);
    rb_define_module_function(mLapack, "ssygv", lapack_s_ssygv, -1);
    rb_define_module_function(mLapack, "ssygvd", lapack_s_ssygvd, -1);
    rb_define_module_function(mLapack, "ssygvx", lapack_s_ssygvx, -1);
    rb_define_module_function(mLapack, "sgeqrf", lapack_s_sgeqrf, -1);
    rb_define_module_function(mLapack, "sgerqf", lapack_s_sgerqf, -1);
    rb_define_module_function(mLapack, "sgeqlf", lapack_s_sgeqlf, -1);
    rb_define_module_function(mLapack, "sgelqf", lapack_s_sgelqf, -1);
    rb_define_module_function(mLapack, "sgeqp3", lapack_s_sgeqp3, -1);
    rb_define_module_function(mLapack, "stzrzf", lapack_s_stzrzf, -1);
    rb_define_module_function(mLapack, "sorgqr", lapack_s_sorgqr, -1);
    rb_define_module_function(mLapack, "sgetrf", lapack_s_sgetrf, -1);
    rb_define_module_function(mLapack, "sgetri", lapack_s_sgetri, -1);
    rb_define_module_function(mLapack, "sgetrs", lapack_s_sgetrs, -1);
    rb_define_module_function(mLapack, "ssytrf", lapack_s_ssytrf, -1);
    rb_define_module_function(mLapack, "ssytri", lapack_s_ssytri, -1);
    rb_define_module_function(mLapack, "ssytrs", lapack_s_ssytrs, -1);
    rb_define_module_function(mLapack, "spotrf", lapack_s_spotrf, -1);
    rb_define_module_function(mLapack, "spotri", lapack_s_spotri, -1);
    rb_define_module_function(mLapack, "spotrs", lapack_s_spotrs, -1);

#line 11 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/init_module.c"
    //  how to do this?
    //rb_extend_object(cT, mTM);
#line 40 "/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_ruby_rb-numo-linalg/rb31-numo-linalg/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/lib.c"
}
