
#line 1 "/opt/local/var/macports/build/rb31-numo-linalg-003c080d/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_imag;
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_real;
static ID id_trans;
static ID id_uplo;



#line 1 "/opt/local/var/macports/build/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/work/destroot/opt/local/lib/ruby3.1/gems/3.1.0/gems/numo-linalg-0.1.7/ext/numo/linalg/lapack/gen/../tmpl/def_c.c"
#include "numo/types/scomplex.h"
#define CZ 1
#define IS_COMPLEX CZ


#line 1 "/opt/local/var/macports/build/rb31-numo-linalg-003c080d/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 clange_args_t
#define func_p clange_p

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

static clange_t func_p = 0;

static void
iter_lapack_s_clange(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 clange(a, norm, [order:'R'])
  @param a [Numo::SComplex]  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 clange.

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

        CLANGE = ( 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_clange(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_clange, 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,"clange");

    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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cgesv_args_t
#define func_p cgesv_p

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

static cgesv_t cgesv_p = 0;

static void
iter_lapack_s_cgesv(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 cgesv(a, b, [order:'R'])
  @param a [Numo::SComplex]  matrix (>=2-dimentional NArray, inplace allowed, output: lu).
  @param b [Numo::SComplex]  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::SComplex, Numo::SComplex, Numo::Int, Integer>

    - **a** -- 
           A is COMPLEX 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 COMPLEX 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.

CGESV computes the solution to a complex 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_cgesv(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_cgesv, 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,"cgesv");

    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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 csysv_args_t
#define func_p csysv_p

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

static csysv_t csysv_p = 0;

static void
iter_lapack_s_csysv(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 csysv(a, b, [uplo:'U', order:'R'])
  @param a [Numo::SComplex]  matrix (>=2-dimentional NArray, inplace allowed, output: lu).
  @param b [Numo::SComplex]  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::SComplex, Numo::SComplex, Numo::Int, Integer>

    - **a** -- 
           A is COMPLEX 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
           CSYTRF.

    - **b** -- 
           B is COMPLEX 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 CSYTRF.  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.

CSYSV computes the solution to a complex 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_csysv(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_csysv, 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,"csysv");

    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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cposv_args_t
#define func_p cposv_p

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

static cposv_t cposv_p = 0;

static void
iter_lapack_s_cposv(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 cposv(a, b, [uplo:'U', order:'R'])
  @param a [Numo::SComplex]  matrix (>=2-dimentional NArray, inplace allowed, output: lu).
  @param b [Numo::SComplex]  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::SComplex, Numo::SComplex, Integer>

    - **a** -- 
           A is COMPLEX array, dimension (LDA,N)
           On entry, the Hermitian 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\*\*H\*U or A = L\*L\*\*H.

    - **b** -- 
           B is COMPLEX 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.

CPOSV computes the solution to a complex system of linear equations

        A * X = B,

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

        A = U**H* U,  if UPLO = 'U', or
        A = L * L**H,  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_cposv(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_cposv, 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,"cposv");

    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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 chesv_args_t
#define func_p chesv_p

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

static chesv_t chesv_p = 0;

static void
iter_lapack_s_chesv(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 chesv(a, b, [uplo:'U', order:'R'])
  @param a [Numo::SComplex]  matrix (>=2-dimentional NArray, inplace allowed, output: lu).
  @param b [Numo::SComplex]  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::SComplex, Numo::SComplex, Numo::Int, Integer>

    - **a** -- 
           A is COMPLEX array, dimension (LDA,N)
           On entry, the Hermitian 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\*\*H or A = L\*D\*L\*\*H as computed by
           CHETRF.

    - **b** -- 
           B is COMPLEX 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 CHETRF.  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.

CHESV computes the solution to a complex system of linear equations

        A * X = B,

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

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

where U (or L) is a product of permutation and unit upper (lower)
triangular matrices, and D is Hermitian 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_chesv(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_chesv, 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,"chesv");

    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/rb31-numo-linalg-003c080d/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 cgesvd_args_t
#define func_p cgesvd_p

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

static cgesvd_t func_p = 0;

static void
iter_lapack_s_cgesvd(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 cgesvd(a, [jobu:'A', jobvt:'A', order:'R'])
  @param a [Numo::SComplex]  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::SComplex, Numo::SComplex, Numo::SComplex, Integer>


    - **u** -- 
           U is COMPLEX 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 unitary 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 COMPLEX array, dimension (LDVT,N)
           If JOBVT = 'A', VT contains the N-by-N unitary matrix
           V\*\*H;
           if JOBVT = 'S', VT contains the first min(m,n) rows of
           V\*\*H (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 CBDSQR did not converge, INFO specifies how many
                 superdiagonals of an intermediate bidiagonal form B
                 did not converge to zero. See the description of RWORK
                 above for details.

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

        A = U * SIGMA * conjugate-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 unitary matrix, and
V is an N-by-N unitary 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\*\*H, not V.

*/
static VALUE
lapack_s_cgesvd(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_cgesvd, 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,"cgesvd");

    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/rb31-numo-linalg-003c080d/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 cgesdd_args_t
#define func_p cgesdd_p

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

static cgesdd_t func_p = 0;

static void
iter_lapack_s_cgesdd(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 cgesdd(a, [jobz:'A', order:'R'])
  @param a [Numo::SComplex]  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::SComplex, Numo::SComplex, Numo::SComplex, Integer>


    - **u** -- 
           U is COMPLEX 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
           unitary 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 COMPLEX array, dimension (LDVT,N)
           If JOBZ = 'A' or JOBZ = 'O' and M >= N, VT contains the
           N-by-N unitary matrix V\*\*H;
           if JOBZ = 'S', VT contains the first min(M,N) rows of
           V\*\*H (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:  The updating process of SBDSDC did not converge.

CGESDD computes the singular value decomposition (SVD) of a complex
M-by-N matrix A, optionally computing the left and/or right singular
vectors, by using divide-and-conquer method. The SVD is written

        A = U * SIGMA * conjugate-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 unitary matrix, and
V is an N-by-N unitary 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\*\*H, 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_cgesdd(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_cgesdd, 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,"cgesdd");

    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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cgels_args_t
#define func_p cgels_p

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

static cgels_t func_p = 0;

static void
iter_lapack_s_cgels(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 cgels(a, b, trans:'N', order:'R')
  @param a [Numo::SComplex]  matrix (>=2-dimentional NArray, inplace allowed).
  @param b [Numo::SComplex]  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::SComplex, Numo::SComplex, Integer>

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

    - **b** -- 
           B is COMPLEX 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 = 'C'.
           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 the
           modulus 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 = 'C' and m >= n, rows 1 to M of B contain the
           minimum norm solution vectors;
           if TRANS = 'C' 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 the modulus 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.

CGELS solves overdetermined or underdetermined complex linear systems
involving an M-by-N matrix A, or its conjugate-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 = 'C' and m >= n:  find the minimum norm solution of
   an underdetermined system A\*\*H \* X = B.

4. If TRANS = 'C' and m < n:  find the least squares solution of
   an overdetermined system, i.e., solve the least squares problem
                minimize || B - A**H * 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_cgels(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_cgels, 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,"cgels");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cgelss_args_t
#define func_p cgelss_p

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

static cgelss_t func_p = 0;

static void
iter_lapack_s_cgelss(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 cgelss(a, b, rcond:-1, order:'R')
  @param a [Numo::SComplex]  matrix (>=2-dimentional NArray, inplace allowed).
  @param b [Numo::SComplex]  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::SComplex, Numo::SComplex, Numo::SComplex, Integer, Integer>

    - **a** -- 
           A is COMPLEX 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 COMPLEX 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 the modulus 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.

CGELSS computes the minimum norm solution to a complex 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_cgelss(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_cgelss, 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,"cgelss");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cgelsd_args_t
#define func_p cgelsd_p

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

static cgelsd_t func_p = 0;

static void
iter_lapack_s_cgelsd(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 cgelsd(a, b, rcond:-1, order:'R')
  @param b [Numo::SComplex]  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::SComplex, Numo::SComplex, Integer, Integer>

    - **b** -- 
           B is COMPLEX 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 the modulus 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.

CGELSD 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_cgelsd(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_cgelsd, 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,"cgelsd");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cgelsy_args_t
#define func_p cgelsy_p

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

static cgelsy_t func_p = 0;

static void
iter_lapack_s_cgelsy(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 cgelsy(a, b, jpvt, rcond:-1, order:'R')
  @param a [Numo::SComplex]  matrix (>=2-dimentional NArray, inplace allowed).
  @param b [Numo::SComplex]  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::SComplex, Numo::SComplex, Numo::Int, Integer, Integer>

    - **a** -- 
           A is COMPLEX 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 COMPLEX 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 A\*P
           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

CGELSY computes the minimum-norm solution to a complex 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 unitary 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**H [ inv(T11)*Q1**H*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 permutation of matrix B (the right hand side) is faster and
          more simple.
        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.

*/
static VALUE
lapack_s_cgelsy(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_cgelsy, 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,"cgelsy");

#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/rb31-numo-linalg-003c080d/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 cgeev_args_t
#define func_p cgeev_p

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

static cgeev_t func_p = 0;

static void
iter_lapack_s_cgeev(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,w,vl, ldvl, vr, ldvr);
    CHECK_ERROR(*info);
}

/*
  @overload cgeev( a,, [jobvl:'V', jobvr:'V', order:'R'] )
  @param a [Numo::SComplex]  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 [[w, vl, vr, info]] Array<Numo::SComplex, Numo::SComplex, Numo::SComplex, Integer>

    - **w** -- 
           W is COMPLEX array, dimension (N)
           W contains the computed eigenvalues.

    - **vl** -- 
           VL is COMPLEX 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.
           u(j) = VL(:,j), the j-th column of VL.

    - **vr** -- 
           VR is COMPLEX 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.
           v(j) = VR(:,j), the j-th column of VR.

    - **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 and i+1:N of W contain eigenvalues which have
                 converged.

CGEEV computes for an N-by-N complex 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_cgeev(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,2,shape},{cT,2,shape},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_cgeev, 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,"cgeev");

    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/rb31-numo-linalg-003c080d/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 cggev_args_t
#define func_p cggev_p

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

static cggev_t func_p = 0;

static void
iter_lapack_s_cggev(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,alpha,beta, vl, ldvl, vr, ldvr);
    CHECK_ERROR(*info);
}

/*

  @overload cggev(a, b, [jobvl:'V', jobvr:'V', order:'R'] )
  @param a [Numo::SComplex]  matrix (>=2-dimentional NArray, inplace allowed).
  @param b [Numo::SComplex]  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 [[alpha, beta, vl, vr, info]] Array<Numo::SComplex, Numo::SComplex, Numo::SComplex, Numo::SComplex, Integer>

    - **alpha** -- 
           ALPHA is COMPLEX array, dimension (N)

    - **beta** -- 
           BETA is COMPLEX array, dimension (N)
           On exit, ALPHA(j)/BETA(j), j=1,...,N, will be the
           generalized eigenvalues.
           Note: the quotients ALPHA(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, ALPHA 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 COMPLEX array, dimension (LDVL,N)
           If JOBVL = 'V', the left generalized eigenvectors u(j) are
           stored one after another in the columns of VL, in the same
           order as their eigenvalues.
           Each eigenvector is scaled so the largest component has
           abs(real part) + abs(imag. part) = 1.
           Not referenced if JOBVL = 'N'.

    - **vr** -- 
           VR is COMPLEX array, dimension (LDVR,N)
           If JOBVR = 'V', the right generalized eigenvectors v(j) are
           stored one after another in the columns of VR, in the same
           order as their eigenvalues.
           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 ALPHA(j) and BETA(j) should be
                 correct for j=INFO+1,...,N.
           > N:  =N+1: other then QZ iteration failed in SHGEQZ,
                 =N+2: error return from STGEVC.

CGGEV computes for a pair of N-by-N complex 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 generalized eigenvector v(j) corresponding to the
generalized eigenvalue lambda(j) of (A,B) satisfies

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

The left generalized eigenvector u(j) corresponding to the
generalized eigenvalues 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_cggev(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,2,shape},{cT,2,shape},{cInt,0}};
    ndfunc_t ndf = {&iter_lapack_s_cggev, 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,"cggev");

    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/rb31-numo-linalg-003c080d/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 cheev_args_t
#define func_p cheev_p

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

static cheev_t func_p = 0;

static void
iter_lapack_s_cheev(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 cheev(a, [jobz:'V', uplo:'U', order:'R'])
  @param a [Numo::SComplex]  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 COMPLEX array, dimension (LDA, N)
           On entry, the Hermitian 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.

CHEEV computes all eigenvalues and, optionally, eigenvectors of a
complex Hermitian matrix A.

*/
static VALUE
lapack_s_cheev(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_cheev, 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,"cheev");

    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/rb31-numo-linalg-003c080d/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 cheevd_args_t
#define func_p cheevd_p

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

static cheevd_t func_p = 0;

static void
iter_lapack_s_cheevd(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 cheevd(a, [jobz:'V', uplo:'U', order:'R'])
  @param a [Numo::SComplex]  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 COMPLEX array, dimension (LDA, N)
           On entry, the Hermitian 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).

CHEEVD computes all eigenvalues and, optionally, eigenvectors of a
complex Hermitian 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.

*/
static VALUE
lapack_s_cheevd(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_cheevd, 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,"cheevd");

    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/rb31-numo-linalg-003c080d/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 chegv_args_t
#define func_p chegv_p

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

static chegv_t func_p = 0;

static void
iter_lapack_s_chegv(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 chegv(a, b, [itype:1, jobz:'V', uplo:'U', order:'R'])
  @param a [Numo::SComplex]  matrix (>=2-dimentional NArray, inplace allowed).
  @param b [Numo::SComplex]  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 COMPLEX array, dimension (LDA, N)
           On entry, the Hermitian 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\*\*H\*B\*Z = I;
           if ITYPE = 3, Z\*\*H\*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 COMPLEX array, dimension (LDB, N)
           On entry, the Hermitian 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\*\*H\*U or B = L\*L\*\*H.

    - **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:  CPOTRF or CHEEV returned an error code:
              <= N:  if INFO = i, CHEEV 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.

CHEGV computes all the eigenvalues, and optionally, the eigenvectors
of a complex generalized Hermitian-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 Hermitian and B is also
positive definite.

*/
static VALUE
lapack_s_chegv(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_chegv, 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,"chegv");

    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/rb31-numo-linalg-003c080d/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 chegvd_args_t
#define func_p chegvd_p

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

static chegvd_t func_p = 0;

static void
iter_lapack_s_chegvd(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 chegvd(a, b, [itype:1, jobz:'V', uplo:'U', order:'R'])
  @param a [Numo::SComplex]  matrix (>=2-dimentional NArray, inplace allowed).
  @param b [Numo::SComplex]  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 COMPLEX array, dimension (LDA, N)
           On entry, the Hermitian 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\*\*H\*B\*Z = I;
           if ITYPE = 3, Z\*\*H\*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 COMPLEX array, dimension (LDB, N)
           On entry, the Hermitian 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\*\*H\*U or B = L\*L\*\*H.

    - **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:  CPOTRF or CHEEVD 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.

CHEGVD computes all the eigenvalues, and optionally, the eigenvectors
of a complex generalized Hermitian-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 Hermitian 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_chegvd(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_chegvd, 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,"chegvd");

    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/rb31-numo-linalg-003c080d/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 chegvx_args_t
#define func_p chegvx_p

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

static chegvx_t func_p = 0;

static void
iter_lapack_s_chegvx(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 chegvx(a, b, [itype:1, jobz:'V', uplo:'U', order:'R', range:'I', il: 1, il: 2])
  @param a [Numo::SComplex]  matrix (>=2-dimentional NArray, inplace allowed).
  @param b [Numo::SComplex]  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 COMPLEX array, dimension (LDA, N)
           On entry, the Hermitian 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 COMPLEX array, dimension (LDB, N)
           On entry, the Hermitian 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\*\*H\*U or B = L\*L\*\*H.

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

    - **z** -- 
           Z is COMPLEX 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:  CPOTRF or CHEEVX returned an error code:
              <= N:  if INFO = i, CHEEVX 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.

CHEGVX computes selected eigenvalues, and optionally, eigenvectors
of a complex generalized Hermitian-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 Hermitian 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_chegvx(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_chegvx, 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,"chegvx");

    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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cgeqrf_args_t
#define func_p cgeqrf_p

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

static cgeqrf_t func_p = 0;

static void
iter_lapack_s_cgeqrf(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 cgeqrf(a, [order:'R'])
  @param a [Numo::SComplex]  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::SComplex, Numo::SComplex, Integer>

    - **a** -- 
           A is COMPLEX 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 unitary matrix Q as a
           product of min(m,n) elementary reflectors (see Further
           Details).

    - **tau** -- 
           TAU is COMPLEX 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

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

*/
static VALUE
lapack_s_cgeqrf(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_cgeqrf, 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,"cgeqrf");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cgerqf_args_t
#define func_p cgerqf_p

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

static cgerqf_t func_p = 0;

static void
iter_lapack_s_cgerqf(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 cgerqf(a, [order:'R'])
  @param a [Numo::SComplex]  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::SComplex, Numo::SComplex, Integer>

    - **a** -- 
           A is COMPLEX 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
           unitary matrix Q as a product of min(m,n) elementary
           reflectors (see Further Details).

    - **tau** -- 
           TAU is COMPLEX 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

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

*/
static VALUE
lapack_s_cgerqf(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_cgerqf, 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,"cgerqf");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cgeqlf_args_t
#define func_p cgeqlf_p

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

static cgeqlf_t func_p = 0;

static void
iter_lapack_s_cgeqlf(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 cgeqlf(a, [order:'R'])
  @param a [Numo::SComplex]  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::SComplex, Numo::SComplex, Integer>

    - **a** -- 
           A is COMPLEX 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
           unitary matrix Q as a product of elementary reflectors
           (see Further Details).

    - **tau** -- 
           TAU is COMPLEX 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

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

*/
static VALUE
lapack_s_cgeqlf(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_cgeqlf, 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,"cgeqlf");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cgelqf_args_t
#define func_p cgelqf_p

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

static cgelqf_t func_p = 0;

static void
iter_lapack_s_cgelqf(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 cgelqf(a, [order:'R'])
  @param a [Numo::SComplex]  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::SComplex, Numo::SComplex, Integer>

    - **a** -- 
           A is COMPLEX 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 unitary matrix Q as a
           product of elementary reflectors (see Further Details).

    - **tau** -- 
           TAU is COMPLEX 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

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

*/
static VALUE
lapack_s_cgelqf(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_cgelqf, 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,"cgelqf");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cgeqp3_args_t
#define func_p cgeqp3_p

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

static cgeqp3_t func_p = 0;

static void
iter_lapack_s_cgeqp3(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 cgeqp3(a, jpvt, [order:'R'])
  @param a [Numo::SComplex]  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::SComplex, Numo::Int, Numo::SComplex, Integer>

    - **a** -- 
           A is COMPLEX 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
           unitary 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 COMPLEX 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.

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

*/
static VALUE
lapack_s_cgeqp3(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_cgeqp3, 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,"cgeqp3");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 ctzrzf_args_t
#define func_p ctzrzf_p

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

static ctzrzf_t func_p = 0;

static void
iter_lapack_s_ctzrzf(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 ctzrzf(a, [order:'R'])
  @param a [Numo::SComplex]  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::SComplex, Numo::SComplex, Integer>

    - **a** -- 
           A is COMPLEX 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
           unitary matrix Z as a product of M elementary reflectors.

    - **tau** -- 
           TAU is COMPLEX 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

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

        A = ( R  0 ) * Z,

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

*/
static VALUE
lapack_s_ctzrzf(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_ctzrzf, 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,"ctzrzf");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cungqr_args_t
#define func_p cungqr_p

typedef struct {
    int order;
} args_t;

static cungqr_t func_p = 0;

static void
iter_lapack_s_cungqr(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 cungqr(a, tau, order:'R')
  @param a [Numo::SComplex]  matrix (>=2-dimentional NArray, inplace allowed).
  @param tau [Numo::SComplex]  vector (>=1-dimentional NArray).
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, info]] Array<Numo::SComplex, Integer>

    - **a** -- 
           A is COMPLEX 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 CGEQRF 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

CUNGQR generates an M-by-N complex 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 CGEQRF.

*/
static VALUE
lapack_s_cungqr(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_cungqr, 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,"cungqr");

    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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cgetrf_args_t
#define func_p cgetrf_p

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

static cgetrf_t func_p = 0;

static void
iter_lapack_s_cgetrf(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/rb31-numo-linalg-003c080d/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 cgetrf(a, [order:'R'])
  @param a [Numo::SComplex]  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::SComplex, Numo::Int, Integer>

    - **a** -- 
           A is COMPLEX 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.

CGETRF 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_cgetrf(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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_cgetrf, 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,"cgetrf");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cgetri_args_t
#define func_p cgetri_p

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

static cgetri_t func_p = 0;

static void
iter_lapack_s_cgetri(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/rb31-numo-linalg-003c080d/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 cgetri(a, ipiv, [order:'R'])
  @param a [Numo::SComplex]  matrix (>=2-dimentional NArray, inplace allowed).
  @param ipiv [Numo::Int] pivot computed by cgetrf
  @param order [String or Symbol]  if 'R': Row-major, if 'C': Column-major. (default='R')
  @return [[a, info]] Array<Numo::SComplex, Integer>

    - **a** -- 
           A is COMPLEX array, dimension (LDA,N)
           On entry, the factors L and U from the factorization
           A = P\*L\*U as computed by CGETRF.
           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.

CGETRI computes the inverse of a matrix using the LU factorization
computed by CGETRF.
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_cgetri(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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_cgetri, 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,"cgetri");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cgetrs_args_t
#define func_p cgetrs_p

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

static cgetrs_t func_p = 0;

static void
iter_lapack_s_cgetrs(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/rb31-numo-linalg-003c080d/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 cgetrs(a, ipiv, b, [trans:'N', order:'R'])
  @param a [Numo::SComplex] LU matrix computed by cgetrf
  @param ipiv [Numo::Int] pivot computed by cgetrf
  @param b [Numo::SComplex]  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::SComplex, Integer>

    - **b** -- 
           B is COMPLEX 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

CGETRS solves a system of linear equations

        A * X = B,  A**T * X = B,  or  A**H * X = B

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

*/
static VALUE
lapack_s_cgetrs(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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_cgetrs, 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,"cgetrs");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 csytrf_args_t
#define func_p csytrf_p

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

static csytrf_t func_p = 0;

static void
iter_lapack_s_csytrf(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/rb31-numo-linalg-003c080d/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 csytrf(a, [uplo:'U', order:'R'])
  @param a [Numo::SComplex]  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::SComplex, Numo::Int, Integer>

    - **a** -- 
           A is COMPLEX 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.

CSYTRF computes the factorization of a complex 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
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_csytrf(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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_csytrf, 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,"csytrf");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 csytri_args_t
#define func_p csytri_p

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

static csytri_t func_p = 0;

static void
iter_lapack_s_csytri(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/rb31-numo-linalg-003c080d/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 csytri(a, ipiv, [uplo:'U', order:'R'])
  @param a [Numo::SComplex]  matrix (>=2-dimentional NArray, inplace allowed).
  @param ipiv [Numo::Int] pivot computed by csytrf
  @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::SComplex, Integer>

    - **a** -- 
           A is COMPLEX 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 CSYTRF.
           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.

CSYTRI computes the inverse of a complex symmetric indefinite matrix
A using the factorization A = U\*D\*U\*\*T or A = L\*D\*L\*\*T computed by
CSYTRF.

*/
static VALUE
lapack_s_csytri(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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_csytri, 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,"csytri");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 csytrs_args_t
#define func_p csytrs_p

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

static csytrs_t func_p = 0;

static void
iter_lapack_s_csytrs(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/rb31-numo-linalg-003c080d/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 csytrs(a, ipiv, b, [uplo:'U', order:'R'])
  @param a [Numo::SComplex] LU matrix computed by csytrf
  @param ipiv [Numo::Int] pivot computed by csytrf
  @param b [Numo::SComplex]  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::SComplex, Integer>

    - **b** -- 
           B is COMPLEX 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

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

*/
static VALUE
lapack_s_csytrs(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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_csytrs, 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,"csytrs");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 chetrf_args_t
#define func_p chetrf_p

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

static chetrf_t func_p = 0;

static void
iter_lapack_s_chetrf(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/rb31-numo-linalg-003c080d/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 chetrf(a, [uplo:'U', order:'R'])
  @param a [Numo::SComplex]  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::SComplex, Numo::Int, Integer>

    - **a** -- 
           A is COMPLEX array, dimension (LDA,N)
           On entry, the Hermitian 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.

CHETRF computes the factorization of a complex Hermitian matrix A
using the Bunch-Kaufman diagonal pivoting method.  The form of the
factorization is

        A = U*D*U**H  or  A = L*D*L**H

where U (or L) is a product of permutation and unit upper (lower)
triangular matrices, and D is Hermitian 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_chetrf(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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_chetrf, 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,"chetrf");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 chetri_args_t
#define func_p chetri_p

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

static chetri_t func_p = 0;

static void
iter_lapack_s_chetri(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/rb31-numo-linalg-003c080d/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 chetri(a, ipiv, [uplo:'U', order:'R'])
  @param a [Numo::SComplex]  matrix (>=2-dimentional NArray, inplace allowed).
  @param ipiv [Numo::Int] pivot computed by chetrf
  @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::SComplex, Integer>

    - **a** -- 
           A is COMPLEX 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 CHETRF.
           On exit, if INFO = 0, the (Hermitian) 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.

CHETRI computes the inverse of a complex Hermitian indefinite matrix
A using the factorization A = U\*D\*U\*\*H or A = L\*D\*L\*\*H computed by
CHETRF.

*/
static VALUE
lapack_s_chetri(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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_chetri, 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,"chetri");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 chetrs_args_t
#define func_p chetrs_p

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

static chetrs_t func_p = 0;

static void
iter_lapack_s_chetrs(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/rb31-numo-linalg-003c080d/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 chetrs(a, ipiv, b, [uplo:'U', order:'R'])
  @param a [Numo::SComplex] LU matrix computed by chetrf
  @param ipiv [Numo::Int] pivot computed by chetrf
  @param b [Numo::SComplex]  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::SComplex, Integer>

    - **b** -- 
           B is COMPLEX 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

CHETRS solves a system of linear equations A\*X = B with a complex
Hermitian matrix A using the factorization A = U\*D\*U\*\*H or
A = L\*D\*L\*\*H computed by CHETRF.

*/
static VALUE
lapack_s_chetrs(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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_chetrs, 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,"chetrs");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cpotrf_args_t
#define func_p cpotrf_p

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

static cpotrf_t func_p = 0;

static void
iter_lapack_s_cpotrf(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/rb31-numo-linalg-003c080d/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 cpotrf(a, [uplo:'U', order:'R'])
  @param a [Numo::SComplex]  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::SComplex, Integer>

    - **a** -- 
           A is COMPLEX array, dimension (LDA,N)
           On entry, the Hermitian 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\*\*H\*U or A = L\*L\*\*H.

    - **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.

CPOTRF computes the Cholesky factorization of a complex Hermitian
positive definite matrix A.
The factorization has the form

        A = U**H * U,  if UPLO = 'U', or
        A = L  * L**H,  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_cpotrf(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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_cpotrf, 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,"cpotrf");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cpotri_args_t
#define func_p cpotri_p

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

static cpotri_t func_p = 0;

static void
iter_lapack_s_cpotri(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/rb31-numo-linalg-003c080d/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 cpotri(a, [uplo:'U', order:'R'])
  @param a [Numo::SComplex]  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::SComplex, Integer>

    - **a** -- 
           A is COMPLEX array, dimension (LDA,N)
           On entry, the triangular factor U or L from the Cholesky
           factorization A = U\*\*H\*U or A = L\*L\*\*H, as computed by
           CPOTRF.
           On exit, the upper or lower triangle of the (Hermitian)
           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.

CPOTRI computes the inverse of a complex Hermitian positive definite
matrix A using the Cholesky factorization A = U\*\*H\*U or A = L\*L\*\*H
computed by CPOTRF.

*/
static VALUE
lapack_s_cpotri(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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_cpotri, 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,"cpotri");

#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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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 cpotrs_args_t
#define func_p cpotrs_p

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

static cpotrs_t func_p = 0;

static void
iter_lapack_s_cpotrs(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/rb31-numo-linalg-003c080d/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 cpotrs(a, b, [uplo:'U', order:'R'])
  @param a [Numo::SComplex] LU matrix computed by cpotrf
  @param b [Numo::SComplex]  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::SComplex, Integer>

    - **b** -- 
           B is COMPLEX 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

CPOTRS solves a system of linear equations A\*X = B with a Hermitian
positive definite matrix A using the Cholesky factorization
A = U\*\*H\*U or A = L\*L\*\*H computed by CPOTRF.

*/
static VALUE
lapack_s_cpotrs(int argc, VALUE const argv[], VALUE UNUSED(mod))
{
#line 144 "/opt/local/var/macports/build/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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_cpotrs, 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,"cpotrs");

#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/rb31-numo-linalg-003c080d/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_c(void)
{
    VALUE mN;

    mN = rb_define_module("Numo");

    
    id_axis = rb_intern("axis");
    id_il = rb_intern("il");
    id_imag = rb_intern("imag");
    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_real = rb_intern("real");
    id_trans = rb_intern("trans");
    id_uplo = rb_intern("uplo");


#line 1 "/opt/local/var/macports/build/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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, "clange", lapack_s_clange, -1);
    rb_define_module_function(mLapack, "cgesv", lapack_s_cgesv, -1);
    rb_define_module_function(mLapack, "csysv", lapack_s_csysv, -1);
    rb_define_module_function(mLapack, "cposv", lapack_s_cposv, -1);
    rb_define_module_function(mLapack, "chesv", lapack_s_chesv, -1);
    rb_define_module_function(mLapack, "cgesvd", lapack_s_cgesvd, -1);
    rb_define_module_function(mLapack, "cgesdd", lapack_s_cgesdd, -1);
    rb_define_module_function(mLapack, "cgels", lapack_s_cgels, -1);
    rb_define_module_function(mLapack, "cgelss", lapack_s_cgelss, -1);
    rb_define_module_function(mLapack, "cgelsd", lapack_s_cgelsd, -1);
    rb_define_module_function(mLapack, "cgelsy", lapack_s_cgelsy, -1);
    rb_define_module_function(mLapack, "cgeev", lapack_s_cgeev, -1);
    rb_define_module_function(mLapack, "cggev", lapack_s_cggev, -1);
    rb_define_module_function(mLapack, "cheev", lapack_s_cheev, -1);
    rb_define_module_function(mLapack, "cheevd", lapack_s_cheevd, -1);
    rb_define_module_function(mLapack, "chegv", lapack_s_chegv, -1);
    rb_define_module_function(mLapack, "chegvd", lapack_s_chegvd, -1);
    rb_define_module_function(mLapack, "chegvx", lapack_s_chegvx, -1);
    rb_define_module_function(mLapack, "cgeqrf", lapack_s_cgeqrf, -1);
    rb_define_module_function(mLapack, "cgerqf", lapack_s_cgerqf, -1);
    rb_define_module_function(mLapack, "cgeqlf", lapack_s_cgeqlf, -1);
    rb_define_module_function(mLapack, "cgelqf", lapack_s_cgelqf, -1);
    rb_define_module_function(mLapack, "cgeqp3", lapack_s_cgeqp3, -1);
    rb_define_module_function(mLapack, "ctzrzf", lapack_s_ctzrzf, -1);
    rb_define_module_function(mLapack, "cungqr", lapack_s_cungqr, -1);
    rb_define_module_function(mLapack, "cgetrf", lapack_s_cgetrf, -1);
    rb_define_module_function(mLapack, "cgetri", lapack_s_cgetri, -1);
    rb_define_module_function(mLapack, "cgetrs", lapack_s_cgetrs, -1);
    rb_define_module_function(mLapack, "csytrf", lapack_s_csytrf, -1);
    rb_define_module_function(mLapack, "csytri", lapack_s_csytri, -1);
    rb_define_module_function(mLapack, "csytrs", lapack_s_csytrs, -1);
    rb_define_module_function(mLapack, "chetrf", lapack_s_chetrf, -1);
    rb_define_module_function(mLapack, "chetri", lapack_s_chetri, -1);
    rb_define_module_function(mLapack, "chetrs", lapack_s_chetrs, -1);
    rb_define_module_function(mLapack, "cpotrf", lapack_s_cpotrf, -1);
    rb_define_module_function(mLapack, "cpotri", lapack_s_cpotri, -1);
    rb_define_module_function(mLapack, "cpotrs", lapack_s_cpotrs, -1);

#line 11 "/opt/local/var/macports/build/rb31-numo-linalg-003c080d/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/rb31-numo-linalg-003c080d/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"
}
