#include <ruby.h>
#include <math.h>
#include <stdio.h>
#include <narray.h>
#include "ssl2.h"

extern void cgsm_(float*,int*,int*,float*,int*);
extern void csgm_(float*,int*,float*,int*,int*);
extern void cgsbm_(float*,int*,int*,float*,int*,int*);
extern void csbgm_(float*,int*,int*,float*,int*,int*);
extern void cssbm_(float*,int*,float*,int*,int*);
extern void csbsm_(float*,int*,int*,float*,int*);

extern void aggm_(float*,int*,float*,int*,float*,int*,int*,int*,int*);
extern void sggm_(float*,int*,float*,int*,float*,int*,int*,int*,int*);
extern void mggm_(float*,int*,float*,int*,float*,int*,int*,int*,int*,float*,int*);
extern void mgsm_(float*,int*,float*,float*,int*,int*,float*,int*);
extern void assm_(float*,float*,float*,int*,int*);
extern void sssm_(float*,float*,float*,int*,int*);
extern void mssm_(float*,float*,float*,int*,float*,int*);
extern void msgm_(float*,float*,int*,float*,int*,int*,float*,int*);
extern void mav_(float*,int*,int*,int*,float*,float*,int*);
extern void mcv_(scomplex*,int*,int*,int*,scomplex*,scomplex*,int*);
extern void msv_(float*,int*,float*,float*,int*);
extern void msbv_(float*,int*,int*,float*,float*,int*);
extern void mbv_(float*,int*,int*,int*,float*,float*,int*);

extern void lax_(float*,int*,int*,float*,float*,int*,int*,float*,int*,int*);
extern void lcx_(float*,int*,int*,float*,float*,int*,int*,float*,int*,int*);
extern void lsx_(float*,int*,float*,float*,int*,int*);
extern void lsix_(float*,int*,float*,float*,int*,float*,int*,int*,int*);
extern void lsbx_(float*,int*,int*,float*,float*,int*,int*);
extern void lsbix_(float*,int*,int*,int*,float*,float*,int*,float*,int*,int*);
extern void lbx1_(float*,int*,int*,int*,float*,float*,int*,int*,float*,float*,int*,int*);
extern void lstx_(float*,float*,int*,float*,float*,int*,int*);
extern void ltx_(float*,float*,float*,int*,float*,float*,int*,int*,int*,float*,int*);
extern void laxr_(float*,float*,int*,int*,float*,float*,int*,float*,int*);
extern void lcxr_(scomplex*,scomplex*,int*,int*,scomplex*,scomplex*,int*,scomplex*,int*);
extern void lsxr_(float*,float*,int*,float*,float*,float*,int*);
extern void lsixr_(float*,float*,int*,float*,float*,int*,float*,int*);
extern void lsbxr_(float*,float*,int*,int*,float*,float*,float*,int*);
extern void lbx1r_(float*,float*,int*,int*,int*,float*,float*,float*,int*,float*,int*);

extern void luiv_(float*,int*,int*,int*,int*);
extern void cluiv_(scomplex*,int*,int*,int*,int*);
extern void ldiv_(float*,int*,int*);

extern void alu_(float*,int*,int*,float*,int*,int*,float*,int*);
extern void clu_(scomplex*,int*,int*,float*,int*,int*,scomplex*,int*);
extern void sldl_(float*,int*,float*,int*);
extern void smdm_(float*,int*,float*,int*,float*,int*,int*);
extern void sbdl_(float*,int*,int*,float*,int*);
extern void sbmdm_(float*,int*,int*,int*,float*,int*,int*,int*);
extern void blu1_(float*,int*,int*,int*,float*,int*,float*,int*,float*,int*);

extern void lux_(float*,float*,int*,int*,int*,int*,int*);
extern void clux_(scomplex*,scomplex*,int*,int*,int*,int*,int*);
extern void ldlx_(float*,float*,int*,int*);
extern void mdmx_(float*,float*,int*,int*,int*);
extern void bdlx_(float*,float*,int*,int*,int*);
extern void bmdmx_(float*,float*,int*,int*,int*,int*,int*,int*);
extern void blux1_(float*,float*,int*,int*,int*,float*,int*,int*);

extern void laxl_(float*,int*,int*,int*,float*,int*,float*,int*,int*);
extern void laxlr_(float*,float*,int*,int*,int*,float*,float*,float*,int*,float*,int*);
extern void laxlm_(float*,int*,int*,int*,float*,int*,float*,float*,float*,int*,float*,int*);
extern void ginv_(float*,int*,int*,int*,float*,float*,int*,float*,float*,int*);
extern void asvd1_(float*,int*,int*,int*,int*,float*,float*,int*,float*,int*,float*,int*);


static VALUE
rb_cgsm(self, ag)
     VALUE self, ag;
{
  float *cag;
  int n;
  float *cas;
  int icon;

  VALUE as;
  int shape[1];

  int nn;

  cag = ssl2_getcary(ag,&nn);

  n = sqrt(nn);
  if ( nn != n*n )
    rb_raise(rb_eRuntimeError, "ag.length != n*n");

  cas = ALLOC_N(float,n*(n+1)/2);

  cgsm_(cag,&n,&n,cas,&icon);
  free(cag);

  shape[0] = n*(n+1)/2;
  as = ssl2_getary(cas,1,shape);
  free(cas);

  ssl2_error(icon);
  return as;
}

static VALUE
rb_csgm(self, as)
     VALUE self, as;
{
  float *cas;
  int n;
  float *cag;
  int icon;

  VALUE ag;
  int shape[2];

  int nn;

  cas = ssl2_getcary(as,&nn);

  n = (sqrt(8*nn+1)-1)/2;
  if ( nn != n*(n+1)/2 )
    rb_raise(rb_eRuntimeError, "as.length != n*(n+1)/2");

  cag = ALLOC_N(float,n*n);

  csgm_(cas,&n,cag,&n,&icon);
  free(cas);

  shape[0]=n;
  shape[1]=n;

  ag = ssl2_getary(cag,2,shape);
  free(cag);

  ssl2_error(icon);
  return ag;
}

static VALUE
rb_cgsbm(self, ag, nh)
     VALUE self, ag, nh;
{
  float *cag;
  int n;
  float *casb;
  int cnh;
  int icon;

  VALUE asb;
  int shape[1];

  int nn;
  int size;

  cag = ssl2_getcary(ag,&nn);

  n = sqrt(nn);
  if ( nn != n*n )
    rb_raise(rb_eRuntimeError, "ag.length != n*n");

  cnh = NUM2INT(nh);
  if ( cnh < 0 )
    rb_raise(rb_eRuntimeError, "nh must be >= 0");
  else if ( cnh >= n )
    rb_raise(rb_eRuntimeError, "nh must be < n");

  size = n*(cnh+1)-cnh*(cnh+1)/2;
  casb = ALLOC_N(float,size);

  cgsbm_(cag,&n,&n,casb,&cnh,&icon);
  free(cag);

  shape[0] = size;
  asb = ssl2_getary(casb,1,shape);
  free(casb);

  ssl2_error(icon);
  return asb;
}

static VALUE
rb_csbgm(self, asb, nh)
     VALUE self, asb, nh;
{
  float *casb;
  int n;
  int cnh;
  float *cag;
  int icon;

  VALUE ag;
  int shape[2];

  int nn;

  cnh = NUM2INT(nh);
  if (cnh<0)
    rb_raise(rb_eRuntimeError, "nh must be >= 0");

  casb = ssl2_getcary(asb, &nn);
  n = (nn+cnh*(cnh+1)/2)/(cnh+1);
  if (cnh>=n)
    rb_raise(rb_eRuntimeError, "nh must be < n");
  if ( nn != n*(cnh+1)-cnh*(cnh+1)/2 )
    rb_raise(rb_eRuntimeError, "casb.length != n(nh+1)-nh(nh+1)");

  cag = ALLOC_N(float,n*n);

  csbgm_(casb,&n,&cnh,cag,&n,&icon);
  free(casb);

  shape[0]=n;
  shape[1]=n;
  ag = ssl2_getary(cag,2,shape);
  free(cag);

  ssl2_error(icon);
  return ag;
}

static VALUE
rb_cssbm(self, as, nh)
     VALUE self, as, nh;
{
  float *cas;
  int n;
  float *casb;
  int cnh;
  int icon;

  VALUE asb;
  int shape[1];

  int nn;
  int size;

  cas = ssl2_getcary(as,&nn);
  n = (sqrt(8*nn+1)-1)/2;
  if (nn!=n*(n+1)/2) rb_raise(rb_eRuntimeError, "as.length != n(n+1)/2");
  cnh = NUM2INT(nh);
  if (cnh<0) rb_raise(rb_eRuntimeError, "nh must be >=0");
  if (cnh>=n)
    rb_raise(rb_eRuntimeError, "nh must be <n");

  size = n*(cnh+1)-cnh*(cnh+1)/2;
  casb = ALLOC_N(float,size);
  cssbm_(cas,&n,casb,&cnh,&icon);
  free(cas);

  shape[0] = size;
  asb = ssl2_getary(casb,1,shape);
  free(casb);

  ssl2_error(icon);
  return asb;
}

static VALUE
rb_csbsm(self, asb, nh)
     VALUE self, asb, nh;
{
  float *casb;
  int n;
  int cnh;
  float *cas;
  int icon;

  VALUE as;
  int shape[1];

  int nn;

  cnh = NUM2INT(nh);
  if (cnh<0) rb_raise(rb_eRuntimeError, "nh must be >= 0");
  casb = ssl2_getcary(asb,&nn);
  n = (nn+cnh*(cnh+1)/2)/(cnh+1);
  if (nn!=n*(cnh+1)-cnh*(cnh+1)/2)
    rb_raise(rb_eRuntimeError, "nn != n(nh+1)-nh(nh+1)/2");
  if (cnh>=n)
    rb_raise(rb_eRuntimeError, "nh must be < n");

  cas = ALLOC_N(float,n*(n+1)/2);

  csbsm_(casb,&n,&cnh,cas,&icon);
  free(casb);

  shape[0]=n*(n+1)/2;
  as = ssl2_getary(cas,1,shape);
  free(cas);

  ssl2_error(icon);
  return as;
}

static VALUE
rb_aggm(self, a, b)
     VALUE self, a, b;
{
  float *ca, *cb, *cc;
  int m, n;
  int icon;

  VALUE c;
  int *shape,rank;

  ca = ssl2_getcary_withshape(a,&shape,&rank);
  if (rank!=2) raise(rb_eRuntimeError, "a.rank must be 2");
  m = shape[0];
  if (m<1) rb_raise(rb_eRuntimeError, "m must be >=1");
  n = shape[1];
  free(shape);
  if (n<1) rb_raise(rb_eRuntimeError, "n must be >=1");
  cb = ssl2_getcary_withshape(b,&shape,&rank);
  if (rank!=2) raise(rb_eRuntimeError, "b.rank must be 2");
  if (shape[0]!=m) raise(rb_eRuntimeError, "b.shape[0] must be m");
  if (shape[1]!=n) raise(rb_eRuntimeError, "b.shape[1] must be n");

  cc = ALLOC_N(float,m*n);
  aggm_(ca,&m,cb,&m,cc,&m,&m,&n,&icon);
  free(ca);
  free(cb);

  c = ssl2_getary(cc,2,shape);
  free(shape);
  free(cc);

  ssl2_error(icon);
  return c;
}

static VALUE
rb_sggm(self, a, b)
     VALUE self, a, b;
{
  float *ca, *cb, *cc;
  int m, n;
  int icon;

  VALUE c;
  int *shape;
  int rank;

  ca = ssl2_getcary_withshape(a,&shape,&rank);
  if (rank!=2)
    raise(rb_eRuntimeError, "a.rank must be 2");
  m = shape[0];
  if (m<1)
    rb_raise(rb_eRuntimeError, "m must be >=1");
  n = shape[1];
  if (n<1)
    rb_raise(rb_eRuntimeError, "n must be >=1");
  cb = ssl2_getcary_withshape(b,&shape,&rank);
  if (rank!=2)
    raise(rb_eRuntimeError, "b.rank must be 2");
  if (shape[0]!=m)
    raise(rb_eRuntimeError, "b.shape[0] must be m");
  if (shape[1]!=n)
    raise(rb_eRuntimeError, "b.shape[1] must be n");

  cc = ALLOC_N(float,m*n);

  sggm_(ca,&m,cb,&m,cc,&m,&m,&n,&icon);
  free(ca);
  free(cb);

  c = ssl2_getary(cc,2,shape);
  free(shape);
  free(cc);

  ssl2_error(icon);
  return c;
}

static VALUE
rb_mggm(self, a, b)
     VALUE self, a, b;
{
  float *ca, *cb, *cc;
  int l, m, n;
  int icon;

  VALUE c;
  int *shape;
  int rank;

  float *vw;

  ca = ssl2_getcary_withshape(a,&shape,&rank);
  if (rank!=2)
    raise(rb_eRuntimeError, "a.rank must be 2");
  m = shape[0];
  if (m<1)
    rb_raise(rb_eRuntimeError, "m must be >=1");
  n = shape[1];
  if (n<1)
    rb_raise(rb_eRuntimeError, "n must be >=1");
  cb = ssl2_getcary_withshape(b,&shape,&rank);
  if (rank!=2)
    raise(rb_eRuntimeError, "b.rank must be 2");
  if (shape[0]!=n)
    raise(rb_eRuntimeError, "b.shape[0] must be n");
  l = shape[1];
  if (l<1)
    rb_raise(rb_eRuntimeError, "l must be >=1");

  cc = ALLOC_N(float,m*l);
  vw = ALLOC_N(float,n);

  mggm_(ca,&m,cb,&n,cc,&m,&m,&n,&l,vw,&icon);
  free(ca);
  free(cb);
  free(vw);

  shape[0]=m;
  shape[1]=l;
  c = ssl2_getary(cc,2,shape);
  free(shape);
  free(cc);

  ssl2_error(icon);
  return c;
}

static VALUE
rb_mgsm(self, a, b)
     VALUE self, a, b;
{
  float *ca, *cb, *cc;
  int n;
  int icon;

  VALUE c;
  int shape[2];
  int rank;

  int nn;
  float *vw;

  ca = ssl2_getcary(a,&nn);
  n = sqrt(nn);
  if (nn!=n*n)
    raise(rb_eRuntimeError, "a.length must be n*n");
  cb = ssl2_getcary(b,&nn);
  if (nn!=n*(n+1)/2)
    raise(rb_eRuntimeError, "b.length must be n(n+1)/2");

  cc = ALLOC_N(float,n*n);
  vw = ALLOC_N(float,n);

  mgsm_(ca,&n,cb,cc,&n,&n,vw,&icon);
  free(ca);
  free(cb);
  free(vw);

  shape[0]=n;
  shape[1]=n;
  c = ssl2_getary(cc,2,shape);
  free(cc);

  ssl2_error(icon);
  return c;
}

static VALUE
rb_assm(self, a, b)
     VALUE self, a, b;
{
  float *ca, *cb, *cc;
  int n, icon;

  VALUE c;
  int shape[1];

  int nn;

  ca = ssl2_getcary(a,&nn);
  n = (sqrt(8*nn+1)-1)/2;
  if (nn!=n*(n+1)/2)
    rb_raise(rb_eRuntimeError, "a.length != n(n+1)/2");
  cb = ssl2_getcary(b,&nn);
  if (nn!=n*(n+1)/2)
    rb_raise(rb_eRuntimeError, "b.length != n(n+1)/2");

  cc = ALLOC_N(float,n*(n+1)/2);
  assm_(ca,cb,cc,&n,&icon);
  free(ca);
  free(cb);

  shape[0] = n*(n+1)/2;
  c = ssl2_getary(cc,1,shape);
  free(cc);

  ssl2_error(icon);
  return c;
}

static VALUE
rb_sssm(self, a, b)
     VALUE self, a, b;
{
  float *ca, *cb, *cc;
  int n, icon;

  VALUE c;
  int shape[1];

  int nn;

  ca = ssl2_getcary(a,&nn);
  n = (sqrt(8*nn+1)-1)/2;
  if (nn!=n*(n+1)/2)
    rb_raise(rb_eRuntimeError, "a.length != n(n+1)/2");
  cb = ssl2_getcary(b,&nn);
  if (nn!=n*(n+1)/2)
    rb_raise(rb_eRuntimeError, "b.length != n(n+1)/2");

  cc = ALLOC_N(float,n*(n+1)/2);
  sssm_(ca,cb,cc,&n,&icon);
  free(ca);
  free(cb);

  shape[0] = n*(n+1)/2;
  c = ssl2_getary(cc,1,shape);
  free(cc);

  ssl2_error(icon);
  return c;
}

static VALUE
rb_mssm(self, a, b)
     VALUE self, a, b;
{
  float *ca, *cb, *cc;
  int n, icon;

  VALUE c;
  int shape[2];
  float *vw;

  int nn;

  ca = ssl2_getcary(a,&nn);
  n = (sqrt(8*nn+1)-1)/2;
  if (nn!=n*(n+1)/2)
    rb_raise(rb_eRuntimeError, "a.length != n(n+1)/2");
  cb = ssl2_getcary(b,&nn);
  if (nn!=n*(n+1)/2)
    rb_raise(rb_eRuntimeError, "b.length != n(n+1)/2");

  cc = ALLOC_N(float,n*n);
  vw = ALLOC_N(float,n);
  mssm_(ca,cb,cc,&n,vw,&icon);
  free(ca);
  free(cb);
  free(vw);

  shape[0] = n;
  shape[1] = n;
  c = ssl2_getary(cc,2,shape);
  free(cc);

  ssl2_error(icon);
  return c;
}

static VALUE
rb_msgm(self, a, b)
     VALUE self, a, b;
{
  float *ca, *cb, *cc;
  int n, icon;

  VALUE c;
  int shape[2];
  float *vw;

  int nn;

  ca = ssl2_getcary(a,&nn);
  n = (sqrt(8*nn+1)-1)/2;
  if (nn!=n*(n+1)/2)
    rb_raise(rb_eRuntimeError, "a.length != n(n+1)/2");
  cb = ssl2_getcary(b,&nn);
  if (nn!=n*n)
    rb_raise(rb_eRuntimeError, "b.length != n(n+1)/2");

  cc = ALLOC_N(float,n*n);
  vw = ALLOC_N(float,n);
  msgm_(ca,cb,&n,cc,&n,&n,vw,&icon);
  free(ca);
  free(cb);
  free(vw);

  shape[0] = n;
  shape[1] = n;
  c = ssl2_getary(cc,2,shape);
  free(cc);

  ssl2_error(icon);
  return c;
}

static VALUE
rb_mav(self, a, x)
     VALUE self, a, x;
{
  float *ca;
  int m, n;
  float *cx, *cy;
  int icon;

  VALUE y;
  int *shape;
  int rank;
  int nn;

  ca = ssl2_getcary_withshape(a,&shape,&rank);
  if (rank!=2)
    rb_raise(rb_eRuntimeError, "a.rank must be 2");
  m=shape[0];
  if (m<1)
    rb_raise(rb_eRuntimeError, "a.shape[0] must be >= 1");
  n=shape[1];
  if (n<1)
    rb_raise(rb_eRuntimeError, "a.shape[1] must be >= 1");
  free(shape);

  cx = ssl2_getcary(x,&nn);
  if (nn!=n)
    rb_raise(rb_eRuntimeError, "x.length must be n");

  cy = ALLOC_N(float,m);
  mav_(ca,&m,&m,&n,cx,cy,&icon);
  free(ca);
  free(cx);

  shape[0] = m;
  y = ssl2_getary(cy,1,shape);
  free(cy);
  free(shape);

  ssl2_error(icon);
  return y;
}

static VALUE
rb_mcv(self,za,zx,zy)
     VALUE self,za,zx,zy;
{
  scomplex *cza,*czx,*czy;
  int m,n;
  int icon;

  int *shape,rank;

  int nn;

  cza = ssl2_getcaryc_withshape(za,&shape,&rank);
  if (rank!=2) rb_raise(rb_eRuntimeError,"za.rank!=2");
  n = shape[0];
  m = shape[1];
  if (n==0) rb_raise(rb_eRuntimeError,"za.shape[0]==0");
  if (m<1) rb_raise(rb_eRuntimeError,"za.shape[1]<1");
  czx = ssl2_getcaryc(zx,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"zx.length != za.shape[0]");
  czy = ssl2_getcaryc(zy,&nn);
  if (nn!=m) rb_raise(rb_eRuntimeError,"zy.length != za.shape[1]");

  mcv_(cza,&n,&n,&m,czx,czy,&icon);
  free(cza);
  free(czx);

  shape[0] = m;
  zy = ssl2_getaryc(czy,1,shape);
  free(czy);
  free(shape);
  
  ssl2_error(icon);
  return zy;
}

static VALUE
rb_msv(self, a, x)
     VALUE self, a, x;
{
  float *ca;
  int n;
  float *cx, *cy;
  int icon;

  VALUE y;
  int shape[1];
  int nn;

  ca = ssl2_getcary(a,&nn);
  n=(sqrt(8*nn+1)-1)/2;
  if (nn!=n*(n+1)/2)
    rb_raise(rb_eRuntimeError, "a.length != n(n+1)/2");
  cx = ssl2_getcary(x,&nn);
  if (nn!=n)
    rb_raise(rb_eRuntimeError, "x.length must be n");

  cy = ALLOC_N(float,n);
  msv_(ca,&n,cx,cy,&icon);
  free(ca);
  free(cx);

  shape[0] = n;
  y = ssl2_getary(cy,1,shape);
  free(cy);

  ssl2_error(icon);
  return y;
}

static VALUE
rb_msbv(self, a, nh, x)
     VALUE self, a, nh, x;
{
  float *ca;
  int n;
  int cnh;
  float *cx, *cy;
  int icon;

  VALUE y;
  int shape[1];
  int nn;

  cnh = NUM2INT(nh);
  if (cnh<0)
    rb_raise(rb_eRuntimeError, "nh must be >= 0");
  ca = ssl2_getcary(a,&nn);
  n=(nn+cnh*(cnh+1)/2)/(cnh+1);
  if (nn!=n*(cnh+1)-cnh*(cnh+1)/2)
    rb_raise(rb_eRuntimeError, "a.length != n(nh+1)-nh(nh+1)/2");
  if (n<=cnh)
    rb_raise(rb_eRuntimeError, "nh must be < n");
  cx = ssl2_getcary(x,&nn);
  if (nn!=n)
    rb_raise(rb_eRuntimeError, "x.length must be n");

  cy = ALLOC_N(float,n);
  msbv_(ca,&n,&cnh,cx,cy,&icon);
  free(ca);
  free(cx);

  shape[0] = n;
  y = ssl2_getary(cy,1,shape);
  free(cy);

  ssl2_error(icon);
  return y;
}

static VALUE
rb_mbv(self, a, nh1, nh2, x)
     VALUE self, a, nh1, nh2, x;
{
  float *ca;
  int n;
  int cnh1, cnh2;
  float *cx, *cy;
  int icon;

  VALUE y;
  int shape[1];
  int nn;

  cnh1 = NUM2INT(nh1);
  if (cnh1<0)
    rb_raise(rb_eRuntimeError, "nh1 must be >= 0");
  cnh2 = NUM2INT(nh2);
  if (cnh2<0)
    rb_raise(rb_eRuntimeError, "nh2 must be >= 0");
  cx = ssl2_getcary(x,&nn);
  n = sqrt(nn);
  if (n<=nh1)
    rb_raise(rb_eRuntimeError, "nh1 must be < n");
  if (n<=nh2)
    rb_raise(rb_eRuntimeError, "nh2 must be < n");
  ca = ssl2_getcary(a,&nn);
  if (nn!=n*MIN(n,cnh1+cnh2+1))
    rb_raise(rb_eRuntimeError, "a.length must be n*min(n,nh1+nh2+1)");

  cy = ALLOC_N(float,n);
  mbv_(ca,&n,&cnh1,&cnh2,cx,cy,&icon);
  free(ca);
  free(cx);

  shape[0] = n;
  y = ssl2_getary(cy,1,shape);
  free(cy);

  ssl2_error(icon);
  return y;
}

static VALUE
rb_lax(self,a,b,epsz,isw)
     VALUE self,a,b,epsz,isw;
{
  float *ca;
  int n;
  float *cb;
  float cepsz;
  int cisw;
  int is;
  float *vw;
  int *ip;
  int icon;

  int shape[1];
  int nn;

  ca = ssl2_getcary(a,&nn);
  n = sqrt(nn);
  if (nn!=n*n)
    rb_raise(rb_eRuntimeError, "a.length must be n*n");
  cb = ssl2_getcary(b,&nn);
  if (nn!=n)
    rb_raise(rb_eRuntimeError, "b.length must be n");
  cepsz = (float) NUM2DBL(epsz);
  if (cepsz<0)
    rb_raise(rb_eRuntimeError, "epsz must be >= 0");
  cisw = NUM2INT(isw);
  if (cisw!=1 && cisw!=2)
    rb_raise(rb_eRuntimeError, "isw must be 1 or 2");

  vw = ALLOC_N(float,n);
  ip = ALLOC_N(int,n);
  lax_(ca,&n,&n,cb,&cepsz,&cisw,&is,vw,ip,&icon);
  free(ca);
  free(vw);
  free(ip);

  shape[0] = n;
  b = ssl2_getary(cb,1,shape);
  free(cb);

  ssl2_error(icon);
  return rb_ary_new3(2,b,INT2NUM(is));
}

static VALUE
rb_lcx(self,za,zb,epsz,isw)
     VALUE self,za,zb,epsz,isw;
{
  float *cza, *czb;
  int n;
  float cepsz;
  int cisw;
  int is;
  float *zvw;
  int *ip;
  int icon;

  int shape[2];
  int nn;

  cza = ssl2_getcary(za,&nn);
  n = sqrt(nn/2);
  if (nn!=n*n*2)
    rb_raise(rb_eRuntimeError, "za.length != 2*n*n");
  czb = ssl2_getcary(zb,&nn);
  if (nn!=2*n)
    rb_raise(rb_eRuntimeError, "zb.length != 2*n");
  cepsz = (float) NUM2DBL(epsz);
  if (cepsz<0)
    rb_rise(rb_eRuntimeError, "epsz must be >= 0");
  cisw = NUM2INT(isw);
  if (cisw!=1&&cisw!=2)
    rb_raise(rb_eRuntimeError, "isw must be 1 or 2");

  zvw = ALLOC_N(float,2*n);
  ip = ALLOC_N(int,n);
  lcx_(cza,&n,&n,czb,&cepsz,&cisw,&is,zvw,ip,&icon);
  free(cza);
  free(zvw);
  free(ip);

  shape[0] = 2;
  shape[1] = n;
  zb = ssl2_getary(czb,2,shape);
  free(czb);

  ssl2_error(icon);
  return rb_ary_new3(2,zb,INT2NUM(is));
}

static VALUE
rb_lsx(self,a,b,epsz,isw)
     VALUE self,a,b,epsz,isw;
{
  float *ca, *cb;
  int n;
  float cepsz;
  int cisw;
  int icon;

  int shape[0];
  int nn;

  ca = ssl2_getcary(a,&nn);
  n = (sqrt(8*nn+1)-1)/2;
  if (nn!=n*(n+1)/2)
    rb_raise(rb_eRuntimeError, "a.length != n*(n+1)/2");
  cb = ssl2_getcary(b,&nn);
  if (nn!=n)
    rb_raise(rb_eRuntimeError, "b.length != n");
  cepsz = (float) NUM2DBL(epsz);
  if (cepsz<0)
    rb_raise(rb_eRuntimeError, "epsz must be >= 0");
  cisw = NUM2INT(isw);
  if (cisw!=1 && cisw!=2)
    rb_raise(rb_eRuntimeError, "isw must be 1 or 2");

  lsx_(ca,&n,cb,&cepsz,&cisw,&icon);
  free(ca);

  shape[0]=n;
  b = ssl2_getary(cb,1,shape);
  free(cb);

  ssl2_error(icon);
  return b;
}

static VALUE
rb_lsix(self,a,b,epsz,isw)
     VALUE self,a,b,epsz,isw;
{
  float *ca,*cb;
  int n;
  float cepsz;
  int cisw;
  float *vw;
  int *ip,*ivw;
  int icon;

  int shape[1];

  int nn;

  ca = ssl2_getcary(a,&nn);
  n = (sqrt(8*nn)-1)/2;
  if (nn!=n*(n+1)/2) rb_raise(rb_eRuntimeError,"a.length != n*(n+1)/2");
  if (n<1) rb_raise(rb_eRuntimeError,"n<1");
  cb = ssl2_getcary(b,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"b.length != a.length");
  cepsz = NUM2FLT(epsz);
  if (cepsz<0) rb_raise(rb_eRuntimeError,"epsz < 0");
  cisw = NUM2INT(isw);
  if (cisw!=1&&cisw!=2) rb_raise(rb_eRuntimeError,"isw must be 1 or 2");

  vw = ALLOC_N(float,2*n);
  ip = ALLOC_N(int,n);
  ivw = ALLOC_N(int,n);
  lsix_(ca,&n,cb,&cepsz,&cisw,vw,ip,ivw,&icon);
  free(ca);
  free(vw);
  free(ip);
  free(ivw);

  shape[0] = n;
  b = ssl2_getary(cb,1,shape);
  free(cb);

  ssl2_error(icon);
  return b;
}

static VALUE
rb_lsbx(self,a,nh,b,epsz,isw)
     VALUE self,a,nh,b,epsz,isw;
{
  float *ca,*cb;
  int n,cnh;
  float cepsz;
  int cisw;
  int icon;

  int shape[1];

  int nn;

  cnh = NUM2INT(nh);
  if (cnh<0) rb_raise(rb_eRuntimeError,"nh<0");
  cb = ssl2_getcary(b,&n);
  if (cnh>=n) rb_raise(rb_eRuntimeError,"nh>=n");
  ca = ssl2_getcary(a,&nn);
  if (nn!=n*(cnh+1)-cnh*(cnh+1)/2) rb_raise(rb_eRuntimeError,"a.length != n(nh+1)-nh(nh+1)");
  cepsz = NUM2FLT(epsz);
  if (epsz<0) rb_raise(rb_eRuntimeError,"epsz<0");
  cisw = NUM2INT(isw);
  if (cisw!=1&&cisw!=2) rb_raise(rb_eRuntimeError,"isw must be 1 or 2");

  lsbx_(ca,&n,&cnh,cb,&cepsz,&cisw,&icon);
  free(ca);

  shape[0] = n;
  b = ssl2_getary(cb,1,shape);
  free(cb);

  ssl2_error(icon);
  return b;
}

static VALUE
rb_lsbix(self,a,nh,mh,b,epsz,isw)
     VALUE self,a,nh,mh,b,epsz,isw;
{
  float *ca,*cb;
  int n,cnh,cmh;
  float cepsz;
  int cisw;
  float *vw;
  int *ivw;
  int icon;

  int shape[1];

  int nn;

  cb = ssl2_getcary(b,&n);
  cnh = NUM2INT(nh);
  if (cnh>0) rb_raise(rb_eRuntimeError,"nh>0");
  cmh = NUM2INT(mh);
  if (cnh>cmh) rb_raise(rb_eRuntimeError,"nh>mh");
  if (cmh>=n) rb_raise(rb_eRuntimeError,"mh>=n");
  ca = ssl2_getcary(b,&nn);
  if (nn!=n*(cnh+1)-cnh*(cnh+1)/2) rb_raise(rb_eRuntimeError,"a.length!=n(h+1)-h(h+1)/2");
  cepsz = NUM2FLT(epsz);
  if (cepsz<0) rb_raise(rb_eRuntimeError,"epsz<0");
  cisw = NUM2INT(isw);
  if (cisw!=1&&cisw!=2) rb_raise(rb_eRuntimeError,"isw must be 1 or 2");

  vw = ALLOC_N(float,n*(cmh+1)-cmh*(cmh+1)/2);
  ivw = ALLOC_N(int,2*n);
  lsbix_(ca,&n,&cnh,&cmh,cb,&cepsz,&cisw,vw,ivw,&icon);
  free(ca);
  free(vw);
  free(ivw);

  shape[0] = n;
  b = ssl2_getary(cb,1,shape);
  free(cb);

  ssl2_error(icon);
  return b;
}

static VALUE
rb_lbx1(self,a,nh1,nh2,b,epsz,isw)
     VALUE self,a,nh1,nh2,b,epsz,isw;
{
  float *ca,*cb;
  int n,cnh1,cnh2;
  float cepsz;
  int cisw;
  int cis;
  float *fl,*vw;
  int *ip;
  int icon;

  int shape[1];

  int nn;

  cb = ssl2_getcary(b,&n);
  cnh1 = NUM2INT(nh1);
  cnh2 = NUM2INT(nh2);
  if (n<=cnh1) rb_raise(rb_eRuntimeError,"n<=nh1");
  if (n<=cnh2) rb_raise(rb_eRuntimeError,"n<=nh2");
  if (cnh1<0) rb_raise(rb_eRuntimeError,"nh1<0");
  if (cnh2<0) rb_raise(rb_eRuntimeError,"nh2<0");
  ca = ssl2_getcary(a,&nn);
  if (nn!=n*MIN(cnh1+cnh2+1,n)) rb_raise(rb_eRuntimeError,"a.length != n*min(h1+h2+1,n)");
  cepsz = NUM2FLT(epsz);
  if (cepsz<0) rb_raise(rb_eRuntimeError,"epsz<0");
  cisw = NUM2INT(isw);
  if (cisw!=1&&cisw!=2) rb_raise(rb_eRuntimeError,"isw must be 1 or 2");

  fl = ALLOC_N(float,(n-1)*cnh1);
  vw = ALLOC_N(float,n);
  ip = ALLOC_N(int,n);
  lbx1_(ca,&n,&cnh1,&cnh2,cb,&cepsz,&cisw,&cis,fl,vw,ip,&icon);
  free(ca);
  free(fl);
  free(vw);
  free(ip);

  shape[0] = n;
  b = ssl2_getary(cb,1,shape);
  free(cb);

  ssl2_error(icon);
  return rb_ary_new3(2,b,INT2NUM(cis));
}

static VALUE
rb_lstx(self,d,sd,b,epsz,isw)
     VALUE self,d,sd,b,epsz,isw;
{
  float *cd,*csd;
  int n;
  float *cb;
  float cepsz;
  int cisw;
  int icon;

  int shape[1];

  int nn;

  cd = ssl2_getcary(d,&n);
  if (n<1) rb_raise(rb_eRuntimeError,"d.length<1");
  csd = ssl2_getcary(sd,&nn);
  if (nn!=n-1) rb_raise(rb_eRuntimeError,"sd.length != d.length-1");
  cb = ssl2_getcary(b,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"b.length != d.length");
  cepsz = NUM2FLT(epsz);
  if (cepsz<0) rb_raise(rb_eRuntimeError,"epsz<0");
  cisw = NUM2INT(isw);
  if (cisw!=1&&cisw!=2) rb_raise(rb_eRuntimeError,"isw must be 1 or 2");

  lstx_(cd,csd,&n,cb,&cepsz,&cisw,&icon);
  free(cd);
  free(csd);

  shape[0] = n;
  b = ssl2_getary(cb,1,shape);
  free(cb);

  ssl2_error(icon);
  return b;
}

static VALUE
rb_ltx(self,sbd,d,spd,b,epsz,isw)
     VALUE self,sbd,d,spd,b,epsz,isw;
{
  float *csbd,*cd,*cspd;
  int n;
  float *cb;
  float cepsz;
  int cisw;
  int cis;
  int *ip;
  float *vw;
  int icon;

  int shape[1];

  int nn;

  csbd = ssl2_getcary(sbd,&nn);
  n = nn+1;
  if (n<1) rb_raise(rb_eRuntimeError,"sbd.length<0");
  cd = ssl2_getcary(d,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"d.length != sbd.length-1");
  cspd = ssl2_getcary(spd,&nn);
  if (nn!=n-1) rb_raise(rb_eRuntimeError,"spd.length != sbd.length");
  cb = ssl2_getcary(b,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"b.length != sbd.length-!");
  cepsz = NUM2FLT(epsz);
  if (cepsz<0) rb_raise(rb_eRuntimeError,"epsz<0");
  cisw = NUM2INT(isw);

  ip = ALLOC_N(int,n);
  vw = ALLOC_N(float,n);
  ltx_(csbd,cd,cspd,&n,cb,&cepsz,&cisw,&cis,ip,vw,&icon);
  free(csbd);
  free(cd);
  free(cspd);
  free(ip);
  free(vw);

  shape[0] = n;
  b = ssl2_getary(cb,1,shape);
  free(cb);

  ssl2_error(icon);
  return rb_ary_new3(2,b,cis);
}

static VALUE
rb_laxr(self,x,a,fa,b,ip)
     VALUE self,x,a,fa,b,ip;
{
  float *cx;
  int n;
  float *ca,*cfa,*cb;
  int *cip;
  float *vw;
  int icon;

  int rank;
  int *shape;

  int nn;

  cx = ssl2_getcary(x,&n);
  if (n<1) rb_raise(rb_eRuntimeError,"x.length < 1");
  ca = ssl2_getcary_withshape(a,&shape,&rank);
  if (rank!=2) rb_raise(rb_eRuntimeError,"a.rank != 2");
  if (shape[0]!=n) rb_raise(rb_eRuntimeError,"a.shape[0] != x.length");
  if (shape[1]!=n) rb_raise(rb_eRuntimeError,"a.shape[1] != x.length");
  free(shape);
  cfa = ssl2_getcary_withshape(fa,&shape,&rank);
  if (rank!=2) rb_raise(rb_eRuntimeError,"fa.rank != 2");
  if (shape[0]!=n) rb_raise(rb_eRuntimeError,"fa.shape[0] != x.length");
  if (shape[1]!=n) rb_raise(rb_eRuntimeError,"fa.shape[1] != x.length");
  cb = ssl2_getcary(b,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"b.length != x.length");
  cip = ssl2_getcaryi(ip,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"ip.length != x.length");

  vw = ALLOC_N(float,n);
  laxr_(cx,ca,&n,&n,cfa,cb,cip,vw,&icon);
  free(ca);
  free(cb);
  free(cfa);
  free(cip);  

  shape[0] = n;
  shape[1] = n;
  x = ssl2_getary(cx,1,shape);
  free(cx);
  free(shape);

  ssl2_error(icon);
  return x;
}

static VALUE
rb_lcxr(self,zx,za,zfa,zb,ip)
     VALUE self,zx,za,zfa,zb,ip;
{
  scomplex *czx,*cza;
  int n;
  scomplex *czfa,*czb;
  int *cip;
  scomplex *zvw;
  int icon;

  int *shape,rank;

  int nn;

  czx = ssl2_getcaryc(zx,&n);
  if (n<1) rb_raise(rb_eRuntimeError,"zx.length<1");
  cza = ssl2_getcaryc_withshape(za,&shape,&rank);
  if (rank!=2) rb_raise(rb_eRuntimeError,"za.rank!=2");
  if (shape[0]!=n) rb_raise(rb_eRuntimeError,"za.shape[0]!=zx.length");
  if (shape[1]!=n) rb_raise(rb_eRuntimeError,"za.shape[1]!=zx.length");
  free(shape);
  czfa = ssl2_getcaryc_withshape(zfa,&shape,&rank);
  if (rank!=2) rb_raise(rb_eRuntimeError,"zfa.rank!=2");
  if (shape[0]!=n) rb_raise(rb_eRuntimeError,"zfa.shape[0]!=zx.length");
  if (shape[1]!=n) rb_raise(rb_eRuntimeError,"zfa.shape[1]!=zx.length");
  czb = ssl2_getcaryc(zb,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"zb.length != zx.length");
  cip = ssl2_getcaryi(ip,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"ip.length != zx.length");

  zvw = ALLOC_N(scomplex,n);
  lcxr_(czx,cza,&n,&n,czfa,czb,cip,zvw,&icon);
  free(cza);
  free(czfa);
  free(czb);
  free(cip);
  free(zvw);

  zx = ssl2_getaryc(czx,1,shape);
  free(czx);
  free(shape);

  ssl2_error(icon);
  return zx;
}

static VALUE
rb_lsxr(self,x,a,fa,b)
     VALUE self,x,a,fa,b;
{
  float *cx;
  float *ca,*cfa,*cb;
  int n;
  float *vw;
  int icon;

  int shape[1];

  int nn;

  cx = ssl2_getcary(x,&n);
  if (n==0) rb_raise(rb_eRuntimeError,"x.length == 0");
  ca = ssl2_getcary(x,&nn);
  if (nn!=n*(n+1)/2) rb_raise(rb_eRuntimeError,"a.length != n(n+1)/2");
  cfa = ssl2_getcary(fa,&nn);
  if (nn!=n*(n+1)/2) rb_raise(rb_eRuntimeError,"fa.length != n(n+1)/2");
  cb = ssl2_getcary(b,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"b.length != x.length");

  vw = ALLOC_N(float,n);
  lsxr_(cx,ca,&n,cfa,cb,vw,&icon);
  free(ca);
  free(cfa);
  free(cb);
  free(vw);

  shape[0] = n;
  x = ssl2_getary(cx,1,shape);
  free(cx);

  ssl2_error(icon);
  return x;
}

static VALUE
rb_lsixr(self,x,a,fa,b,ip)
     VALUE self,x,a,fa,b,ip;
{
  float *cx;
  float *ca,*cfa,*cb;
  int n;
  int *cip;
  float *vw;
  int icon;

  int shape[1];

  int nn;

  cx = ssl2_getcary(x,&n);
  if (n==0) rb_raise(rb_eRuntimeError,"x.length == 0");
  ca = ssl2_getcary(a,&nn);
  if (nn!=n*(n+1)/2) rb_raise(rb_eRuntimeError,"a.length != n(n+1)/2");
  cfa = ssl2_getcary(fa,&nn);
  if (nn!=n*(n+1)/2) rb_raise(rb_eRuntimeError,"fa.length != n(n+1)/2");
  cb = ssl2_getcary(b,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"b.length != x.length");
  cip = ssl2_getcaryi(ip,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"ip.length != x.length");

  vw = ALLOC_N(float,n);
  lsixr_(cx,ca,&n,cfa,cb,cip,vw,&icon);
  free(ca);
  free(cfa);
  free(cb);
  free(cip);
  free(vw);

  shape[0] = n;
  x = ssl2_getary(cx,1,shape);
  free(cx);

  ssl2_error(icon);
  return x;
}

static VALUE
rb_lsbxr(self,x,a,nh,fa,b)
     VALUE self,x,a,nh,fa,b;
{
  float *cx;
  float *ca,*cfa,*cb;
  int n;
  int cnh;
  float *vw;
  int icon;

  int shape[1];

  int nn;

  cx = ssl2_getcary(x,&n);
  if (n==0) rb_raise(rb_eRuntimeError,"x.length == 0");
  cnh = NUM2INT(nh);
  if (cnh<0) rb_raise(rb_eRuntimeError,"nh<0");
  if (cnh>=abs(n)) rb_raise(rb_eRuntimeError,"nh>=|n|");
  ca = ssl2_getcary(a,&nn);
  if (nn!=n*(cnh+1)-cnh*(cnh+1)/2) rb_raise(rb_eRuntimeError,"a.length != n(nh+1)-nh(nh+1)/2");
  cfa = ssl2_getcary(fa,&nn);
  if (nn!=n*(cnh+1)-cnh*(cnh+1)/2) rb_raise(rb_eRuntimeError,"fa.length != n(nh+1)-nh(nh+1)/2");
  cb = ssl2_getcary(b,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"b.length != x.length");

  vw = ALLOC_N(float,n);
  lsbxr_(cx,ca,&n,&cnh,cfa,cb,vw,&icon);
  free(ca);
  free(cfa);
  free(cb);
  free(vw);

  shape[0] = n;
  x = ssl2_getary(cx,1,shape);
  free(cx);

  ssl2_error(icon);
  return x;
}

static VALUE
rb_lbx1r(self,x,a,nh1,nh2,fl,fu,b,ip)
     VALUE self,x,a,nh1,nh2,fl,fu,b,ip;
{
  float *cx;
  float *ca,*cfl,*cfu,*cb;
  int n,cnh1,cnh2;
  int *cip;
  float *vw;
  int icon;

  int shape[1];

  int nn;

  cx = ssl2_getcary(x,&n);
  if (n==0) rb_raise(rb_eRuntimeError,"x.length == 0");
  cnh1 = NUM2INT(nh1);
  cnh2 = NUM2INT(nh2);
  if (n<=cnh1) rb_raise(rb_eRuntimeError,"n<=nh1");
  if (n<=cnh2) rb_raise(rb_eRuntimeError,"n<=nh2");
  if (cnh1<0) rb_raise(rb_eRuntimeError,"nh1<0");
  if (cnh2<0) rb_raise(rb_eRuntimeError,"nh2<0");
  ca = ssl2_getcary(a,&nn);
  if (nn!=n*MIN(cnh1+cnh2+1,n)) rb_raise(rb_eRuntimeError,"a.length != n*min(h1+h2+1,n)");
  cfl = ssl2_getcary(fl,&nn);
  if (nn!=(n-1)*cnh1) rb_raise(rb_eRuntimeError,"fl.lenght != (n-1)*nh1");
  cfu = ssl2_getcary(fu,&nn);
  if (nn!=n*MIN(cnh1+cnh2+1,n)) rb_raise(rb_eRuntimeError,"fu.length != n*min(h1+h2+1,n)");
  cb = ssl2_getcary(b,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"b.length != x.length");
  cip = ssl2_getcaryi(ip,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"b.length != ip.length");

  vw = ALLOC_N(float,n);
  lbx1r_(cx,ca,&n,&cnh1,&cnh2,cfl,cfu,cb,cip,vw,&icon);
  free(ca);
  free(cfl);
  free(cfu);
  free(cip);
  free(vw);

  shape[0] = n;
  x = ssl2_getary(cx,1,shape);
  free(cx);

  ssl2_error(icon);
  return x;
}

static VALUE
rb_luiv(self,fa,ip)
     VALUE self,fa,ip;
{
  float *cfa;
  int n;
  int *cip;
  int icon;

  int rank;
  int *shape;

  int nn;

  cfa = ssl2_getcary_withshape(fa,&shape,&rank);
  if (rank!=2) rb_raise(rb_eRuntimeError,"fa.rank!=2");
  n = shape[0];
  if (shape[1]!=n) rb_raise(rb_eRuntimeError,"fa.shape[0]!=fa.shape[1]");
  cip = ssl2_getcaryi(ip,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"ip.length!=n");

  luiv_(cfa,&n,&n,cip,&icon);
  free(cip);

  fa = ssl2_getary(cfa,2,shape);
  free(cfa);
  free(shape);

  ssl2_error(icon);
  return fa;
}

static VALUE
rb_cluiv(self,zfa,ip)
     VALUE self,zfa,ip;
{
  scomplex *czfa;
  int n;
  int *cip;
  int icon;

  int *shape,rank;

  int nn;

  czfa = ssl2_getcaryc_withshape(zfa,&shape,&rank);
  if (rank!=2) rb_raise(rb_eRuntimeError,"zfa.rank!=2");
  n = shape[0];
  if (shape[1]!=n) rb_raise(rb_eRuntimeError,"zfa.shape[0]!=zfa.shape[1]");
  if (n<1) rb_raise(rb_eRuntimeError,"n<1");
  cip = ssl2_getcaryi(ip,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"ip.length != n");

  cluiv_(czfa,&n,&n,cip,&icon);
  free(cip);

  zfa = ssl2_getaryc(czfa,2,shape);
  free(czfa);
  free(shape);

  ssl2_error(icon);
  return zfa;
}

static VALUE
rb_ldiv(self,fa)
     VALUE self,fa;
{
  float *cfa;
  int n;
  int icon;

  int shape[1];

  int nn;

  cfa = ssl2_getcary(fa,&nn);
  n = (sqrt(8*nn+1)-1)/2;
  if (nn!=n*(n+1)/2) rb_raise(rb_eRuntimeError,"fa.length != n(n+1)/2");

  udiv_(cfa,&n,&icon);

  shape[0] = n*(n+1)/2;
  fa = ssl2_getary(cfa,1,shape);
  free(cfa);

  ssl2_error(icon);
  return fa;
}

static VALUE
rb_alu(self,a,epsz)
     VALUE self,a,epsz;
{
  float *ca;
  int n;
  float cepsz;
  int *cip;
  int cis;
  float *vw;
  int icon;

  int *shape;
  int rank;

  ca = ssl2_getcary_withshape(a,&shape,&rank);
  if (rank!=2) rb_raise(rb_eRuntimeError,"a.rank!=2");
  n = shape[0];
  if (shape[1]!=n) rb_raise(rb_eRuntimeError,"a.shape[0]!=a.shape[1]");
  cepsz = NUM2FLT(epsz);

  cip = ALLOC_N(int,n);
  vw = ALLOC_N(float,n);
  alu_(ca,&n,&n,&cepsz,cip,&cis,vw,&icon);
  free(cip);
  free(vw);

  a = ssl2_getary(ca,2,shape);
  free(ca);
  free(shape);

  ssl2_error(icon);
  return rb_ary_new3(2,a,INT2NUM(cis));
}

static VALUE
rb_clu(self,za,epsz)
     VALUE self,za,epsz;
{
  scomplex *cza;
  int n;
  float cepsz;
  int *cip;
  int cis;
  scomplex *zvw;
  int icon;

  VALUE ip;
  int *shape,rank;

  int nn;

  cza = ssl2_getcaryc_withshape(za,&shape,&rank);
  if (rank!=2) rb_raise(rb_eRuntimeError,"za.rank!=2");
  n = shape[0];
  if (shape[1]!=shape[0]) rb_raise(rb_eRuntimeError,"za.shape[0]!=za.shape[1]");
  if (n<1) rb_raise(rb_eRuntimeError,"n<1");
  cepsz = NUM2FLT(epsz);
  if (cepsz<0) rb_raise(rb_eRuntimeError,"epsz<0");

  cip = ALLOC_N(int,n);
  zvw = ALLOC_N(scomplex,n);
  clu_(cza,&n,&n,&cepsz,cip,&cis,zvw,&icon);
  free(zvw);

  za = ssl2_getaryc(cza,2,shape);
  free(cza);
  ip = ssl2_getaryi(cip,1,shape);
  free(cip);
  free(shape);

  ssl2_error(icon);
  return rb_ary_new3(3,za,ip,INT2NUM(cis));
}

static VALUE
rb_sldl(self,a,epsz)
     VALUE self,a,epsz;
{
  float *ca;
  int n;
  float cepsz;
  int icon;

  int shape[1];

  int nn;

  ca = ssl2_getcary(a,&nn);
  n = (sqrt(nn*8+1)-1)/2;
  if (nn!=n*(n+1)/2) rb_raise(rb_eRuntimeError,"a.length!=n(n+1)/2");
  cepsz = NUM2FLT(epsz);
  if (cepsz<0) rb_raise(rb_eRuntimeError,"epsz<0");

  sldl_(ca,&n,&cepsz,&icon);

  shape[0] = n*(n+1)/2;
  a = ssl2_getary(ca,1,shape);
  free(ca);

  ssl2_error(icon);
  return a;
}

static VALUE
rb_smdm(self,a,epsz)
     VALUE self,a,epsz;
{
  float *ca;
  int n;
  float cepsz;
  int *cip;
  float *vw;
  int *ivw;
  int icon;

  VALUE ip;
  int shape[1];

  int nn;

  ca = ssl2_getcary(a,&nn);
  n = (sqrt(nn*8+1)-1)/2;
  if (nn!=n*(n+1)/2) rb_raise(rb_eRuntimeError,"a.lenth != n(n+1)/2");
  cepsz = NUM2FLT(epsz);
  if (cepsz<0) rb_raise(rb_eRuntimeError,"epsz<0");

  cip = ALLOC_N(int,n);
  vw = ALLOC_N(float,2*n);
  ivw = ALLOC_N(int,n);
  smdm_(ca,&n,&cepsz,cip,vw,ivw,&icon);
  free(vw);
  free(ivw);

  shape[0] = n*(n+1)/2;
  a = ssl2_getary(ca,1,shape);
  free(ca);
  shape[0] = n;
  ip = ssl2_getaryi(cip,1,shape);
  free(cip);

  ssl2_error(icon);
  return rb_ary_new3(2,a,ip);
}

static VALUE
rb_sbdl(self,a,nh,epsz)
     VALUE self,a,nh,epsz;
{
  float *ca;
  int n;
  int cnh;
  float cepsz;
  int icon;

  int nn;

  int shape[1];

  cnh = NUM2INT(nh);
  if (cnh<0) rb_raise(rb_eRuntimeError,"nh<0");
  ca = ssl2_getcary(a,&nn);
  n = (nn+cnh*(cnh+1)/2)/(cnh+1);
  if (nn!=n*(cnh+1)-cnh*(cnh+1)/2) rb_rase(rb_eRuntimeError,"a.length!=n(nh+1)-nh(nh+1)/2");
  if (cnh>=n) rb_raise(rb_eRuntimeError,"nh>=n");
  cepsz = NUM2FLT(epsz);
  if (cepsz<0) rb_raise(rb_eRuntimeError,"epsz<0");

  sbdl_(ca,&n,&cnh,&cepsz,&icon);

  shape[0] = n*(cnh+1)-cnh*(cnh+1)/2;
  a = ssl2_getary(ca,1,shape);
  free(ca);

  ssl2_error(icon);
  return a;
}

static VALUE
rb_sbmdm(self,a,nh,mh,epsz)
     VALUE self,a,nh,mh,epsz;
{
  float *ca;
  int n;
  int cnh,cmh;
  float cepsz;
  int *cip;
  int *ivw;
  int icon;

  VALUE ip;
  int shape[1];

  int nn;

  cnh = NUM2INT(nh);
  if (cnh<0) rb_raise(rb_eRuntimeError,"nh<0");
  cmh = NUM2INT(mh);
  if (cnh>cmh) rb_raise(rb_eRuntimeError,"nh>mh");
  ca = ssl2_getcary(a,&nn);
  n = (nn+cmh*(cmh+1)/2)/(cmh+1);
  if (nn!=n*(cmh+1)-cmh*(cmh+1)/2) rb_rase(rb_eRuntimeError,"a.length!=n(mh+1)-mh(mh+1)/2");
  if (cmh>=n) rb_raise(rb_eRuntimeError,"mh>=n");
  cepsz = NUM2FLT(epsz);
  if (cepsz<0) rb_raise(rb_eRuntimeError,"epsz<0");

  cip = ALLOC_N(int,n);
  ivw = ALLOC_N(int,n);
  sbmdm_(ca,&n,&cnh,&cmh,&cepsz,cip,ivw,&icon);
  free(ivw);

  shape[0] = n*(cmh+1)-cmh*(cmh+1)/2;
  a = ssl2_getary(ca,1,shape);
  free(ca);
  shape[0] = n;
  ip = ssl2_getaryi(cip,1,shape);
  free(cip);

  ssl2_error(icon);
  return rb_ary_new3(2,a,ip);
}

static VALUE
rb_blu1(self,a,nh1,nh2,epsz)
     VALUE self,a,nh1,nh2,epsz;
{
  float *ca;
  int n;
  int cnh1,cnh2;
  float cepsz;
  int cis;
  float *cfl;
  int *cip;
  float *vw;
  int icon;

  VALUE fl,ip;
  int shape[1];

  int nn;

  cnh1 = NUM2INT(nh1);
  cnh2 = NUM2INT(nh2);
  if (cnh1<0) rb_raise(rb_eRuntimeError,"nh1<0");
  if (cnh2<0) rb_raise(rb_eRuntimeError,"nh2<0");
  ca = ssl2_getcary(a,&nn);
  if (nn/(cnh1+cnh2+1)>cnh1+cnh2+1)
    n = nn/(cnh1+cnh2+1);
  else
    n = sqrt(nn);
  if (nn!=n*MIN(cnh1+cnh2+1,n)) rb_raise(rb_eRuntimeError,"a.length != n*min(nh1+nh2+1)");
  if (n<=cnh1) rb_raise(rb_eRuntimeError,"n<=nh1");
  if (n<=cnh2) rb_raise(rb_eRuntimeError,"n<=nh2");
  cepsz = NUM2FLT(epsz);
  if (cepsz<0) rb_raise(rb_eRuntimeError,"epsz<0");

  cfl = ALLOC_N(float,(n-1)*cnh1);
  cip = ALLOC_N(int,n);
  vw = ALLOC_N(float,n);
  blu1_(ca,&n,&cnh1,&cnh2,&cepsz,&cis,cfl,cip,vw,&icon);
  free(vw);

  shape[0] = n*MIN(cnh1+cnh2+1,n);
  a = ssl2_getary(ca,1,shape);
  free(ca);
  shape[0] = (n-1)*cnh1;
  fl = ssl2_getary(cfl,1,shape);
  free(cfl);
  shape[0] = n;
  ip = ssl2_getaryi(cip,1,shape);
  free(cip);

  ssl2_error(icon);
  return rb_ary_new3(4,a,INT2NUM(cis),fl,ip);
}

static VALUE
rb_lux(self,b,fa,isw,ip)
     VALUE self,b,fa,isw,ip;
{
  float *cb,*cfa;
  int n;
  int cisw;
  int *cip;
  int icon;

  int rank;
  int *shape;

  int nn;

  cb = ssl2_getcary(b,&n);
  cfa = ssl2_getcary_withshape(fa,&shape,&rank);
  if (rank!=2) rb_raise(rb_eRuntimeError,"fa.rakn!=2");
  if (shape[0]!=n) rb_raise(rb_eRuntimeError,"fa.shape[0]!=n");
  if (shape[1]!=n) rb_raise(rb_eRuntimeError,"fa.shape[1]!=n");
  cisw = NUM2INT(isw);
  if (cisw!=1&&cisw!=2&&cisw!=3) rb_raise(rb_eRuntimeError,"isw must be 1,2,or3");
  cip = ssl2_getcaryi(ip,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"ip.length != b.length");

  lux_(cb,cfa,&n,&n,&cisw,cip,&icon);
  free(cfa);
  free(cip);

  shape[0] = n;
  b = ssl2_getary(cb,1,shape);
  free(cb);
  free(shape);

  ssl2_error(icon);
  return b;
}

static VALUE
rb_clux(self,zb,zfa,isw,ip)
     VALUE self,zb,zfa,isw,ip;
{
  scomplex *czb,*czfa;
  int n;
  int cisw;
  int *cip;
  int icon;

  int *shape,rank;

  int nn;

  czb = ssl2_getcaryc(zb,&n);
  if (n<1) rb_raise(rb_eRuntimeError,"zb.length < 1");
  czfa = ssl2_getcaryc_withshape(zfa,&shape,&rank);
  if (rank!=2) rb_raise(rb_eRuntimeError,"zfa.rank != 2");
  if (shape[0]!=n) rb_raise(rb_eRuntimeError,"zfa.shape[0]!=zb.length");
  if (shape[1]!=n) rb_raise(rb_eRuntimeError,"zfa.shape[1]!=zb.length");
  cisw = NUM2INT(isw);
  if (cisw!=1&&cisw!=2&&cisw!=3) rb_raise(rb_eRuntimeError,"isw must be 1,2,or 3");
  cip = ssl2_getcaryi(ip,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"ip.length != zb.length");

  clux_(czb,czfa,&n,&n,&cisw,cip,&icon);
  free(czfa);

  zb = ssl2_getaryc(czb,1,shape);
  free(czb);
  free(shape);

  ssl2_error(icon);
  return zb;
}

static VALUE
rb_ldlx(self,b,fa)
     VALUE self,b,fa;
{
  float *cb,*cfa;
  int n;
  int icon;

  int shape[1];

  int nn;

  cb = ssl2_getcary(b,&n);
  cfa = ssl2_getcary(fa,&nn);
  if (nn!=n*(n+1)/2) rb_raise(rb_eRuntimeError,"fa.length!=n(n+1)/2");

  ldlx_(cb,cfa,&n,&icon);
  free(cfa);

  shape[0] = n;
  b = ssl2_getary(cb,1,shape);
  free(cb);

  ssl2_error(icon);
  return b;
}

static VALUE
rb_mdmx(self,b,fa,ip)
     VALUE self,b,fa,ip;
{
  float *cb,*cfa;
  int n;
  int *cip;
  int icon;

  int shape[1];

  int nn;

  cb = ssl2_getcary(b,&n);
  cfa = ssl2_getcary(fa,&nn);
  if (nn!=n*(n+1)/2) rb_raise(rb_eRuntimeError,"fa.length!=n(n+1)/2");
  cip = ssl2_getcaryi(ip,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"ip.lenght!=b.lengh");

  mdmx_(cb,cfa,&n,cip,&icon);
  free(cip);
  free(cfa);

  shape[0] = n;
  b = ssl2_getary(cb,1,shape);
  free(cb);

  ssl2_error(icon);
  return b;
}

static VALUE
rb_bdlx(self,b,fa,nh)
     VALUE self,b,fa,nh;
{
  float *cb,*cfa;
  int n;
  int cnh;
  int icon;

  int shape[1];

  int nn;

  cb = ssl2_getcary(b,&n);
  cnh = NUM2INT(nh);
  if (cnh<0) rb_raise(rb_eRuntimeError,"nh<0");
  if (cnh>=n) rb_raise(rb_eRuntimeError,"nh>=n");
  cfa = ssl2_getcary(fa,&nn);
  if (nn!=n*(cnh+1)-cnh+(cnh+1)/2) rb_raise(rb_eRuntimeError,"fa.length!=n(nh+1)-nh(nh+1)/2");

  bdlx_(cb,cfa,&n,&cnh,&icon);
  free(cfa);

  shape[0] = n;
  b = ssl2_getary(cb,1,shape);
  free(cb);

  ssl2_error(icon);
  return b;
}

static VALUE
rb_bmdmx(self,b,fa,nh,mh,ip)
     VALUE self,b,fa,nh,mh,ip;
{
  float *cb,*cfa;
  int n;
  int cnh,cmh;
  int *cip;
  int *ivw;
  int icon;

  int shape[1];

  int nn;

  cb = ssl2_getcary(b,&n);
  cnh = NUM2INT(nh);
  if (cnh<0) rb_raise(rb_eRuntimeError,"nh<0");
  cmh = NUM2INT(mh);
  if (cnh>cmh) rb_raise(rb_eRuntimeError,"nh>mh");
  if (n>=cmh) rb_raise(rb_eRuntimeError,"n>=mh");
  cfa = ssl2_getcary(fa,&nn);
  if (nn!=n*(cmh+1)-cmh+(cmh+1)/2) rb_raise(rb_eRuntimeError,"fa.length!=n(mh+1)-mh(mh+1)/2");
  cip = ssl2_getcaryi(ip,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"ip.length!=b.length");

  ivw = ALLOC_N(int,n);
  bmdmx_(cb,cfa,&n,&cnh,&cmh,cip,ivw,&icon);
  free(cfa);
  free(cip);
  free(ivw);

  shape[0] = n;
  b = ssl2_getary(cb,1,shape);
  free(cb);

  ssl2_error(icon);
  return b;
}

static VALUE
rb_blux1(self,b,fa,nh1,nh2,fl,ip)
     VALUE self,b,fa,nh1,nh2,fl,ip;
{
  float *cb,*cfa;
  int n;
  int cnh1,cnh2;
  float *cfl;
  int *cip;
  int icon;

  int shape[1];

  int nn;

  cb = ssl2_getcary(b,&n);
  cnh1 = NUM2INT(nh1);
  if (cnh2<0) rb_raise(rb_eRuntimeError,"nh1<0");
  if (n<=cnh1) rb_raise(rb_eRuntimeError,"n<=nh1");
  cnh2 = NUM2INT(nh2);
  if (cnh2<0) rb_raise(rb_eRuntimeError,"nh2<0");
  if (n<=cnh2) rb_raise(rb_eRuntimeError,"n<=nh2");
  cfa = ssl2_getcary(fa,&nn);
  if (nn!=n*MIN(cnh1+cnh2+1,n)) rb_raise(rb_eRuntimeError,"fa.length!=n*min(nh1+nh2+1)");
  cfl = ssl2_getcary(fl,&nn);
  if (nn!=(n-1)*cnh1) rb_raise(rb_eRuntimeError,"fl.length != (n-1)*nh1");
  cip = ssl2_getcaryi(ip,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"ip.length!=b.length");

  blux1_(cb,cfa,&n,&cnh1,&cnh2,cfl,cip,&icon);
  free(cfa);
  free(cfl);
  free(cip);

  shape[0] = n;
  b = ssl2_getary(cb,1,shape);
  free(cb);

  ssl2_error(icon);
  return b;
}

static VALUE
rb_laxl(self,a,b,isw)
     VALUE self,a,b,isw;
{
  float *ca,*cb;
  int n,m;
  int cisw;
  float *vw;
  int *ivw;
  int icon;

  int rank;
  int *shape;

  int nn;

  ca = ssl2_getcary_withshape(a,&shape,&rank);
  if (rank!=2) rb_raise(rb_eRuntimeError,"a.rank!=2");
  m = shape[0];
  n = shape[1];
  if (m<n) rb_raise(rb_eRuntimeError,"m<n");
  cb = ssl2_getcary(b,&nn);
  if (nn!=m) rb_raise(rb_eRuntimeError,"b.length!=m");
  cisw = NUM2INT(isw);
  if (cisw!=1&&cisw!=2) rb_raise(rb_eRuntimeError,"isw must be 1 or 2");

  vw = ALLOC_N(float,2*n);
  ivw = ALLOC_N(int,n);
  laxl_(ca,&m,&m,&n,cb,&cisw,vw,ivw,&icon);
  free(ca);
  free(vw);
  free(ivw);

  shape[0] = m;
  b = ssl2_getary(cb,1,shape);
  free(cb);
  free(shape);

  ssl2_error(icon);
  return b;
}

static VALUE
rb_laxlr(self,x,a,fa,fd,b,ip)
     VALUE self,x,a,fa,fd,b,ip;
{
  float *cx;
  float *ca;
  int n,m;
  float *cfa,*cfd;
  float *cb;
  int *cip;
  float *vw;
  int icon;

  int rank;
  int *shape;

  int nn;

  cx = ssl2_getcary(x,&n);
  ca = ssl2_getcary_withshape(a,&shape,&rank);
  if (rank!=2) rb_raise(rb_eRuntimeError,"a.rank!=2");
  m = shape[0];
  if (shape[1]!=n) rb_raise(rb_eRuntimeError,"a.shape[1]!=x.length");
  if (m<n) rb_raise(rb_eRuntimeError,"m<n");
  free(shape);
  cfa = ssl2_getcary_withshape(fa,&shape,&rank);
  if (rank!=2) rb_raise(rb_eRuntimeError,"fa.rank!=2");
  if (shape[0]!=m) rb_raise(rb_eRuntimeError,"fa.shape[0]!=m");
  if (shape[1]!=n) rb_raise(rb_eRuntimeError,"fa.shape[1]!=x.length");
  cfd = ssl2_getcary(fd,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"fd.lenght != x.length");
  cb = ssl2_getcary(b,&nn);
  if (nn!=m) rb_raise(rb_eRuntimeError,"b.length!=m");
  cip = ssl2_getcaryi(ip,&nn);
  if (nn!=n) rb_raise(rb_eRuntimeError,"ip.length!=x.length");

  vw = ALLOC_N(float,2*n);
  laxlr_(cx,ca,&m,&m,&n,cfa,cfd,cb,cip,vw,&icon);
  free(ca);
  free(cfa);
  free(cfd);
  free(cb);
  free(cip);
  free(vw);

  shape[0] = n;
  x = ssl2_getary(cx,1,shape);
  free(cx);
  free(shape);

  ssl2_error(icon);
  return x;
}

static VALUE
rb_laxlm(self,a,b,isw,eps)
     VALUE self,a,b,isw,eps;
{
  float *ca,*cb;
  int m,n;
  int cisw;
  float ceps;
  float *csig;
  float *v,*vw;
  int icon;

  VALUE sig;
  int rank;
  int *shape;

  int nn;

  ca = ssl2_getcary_withshape(a,&shape,&rank);
  if (rank!=2) rb_raise(rb_eRuntimeError,"a.rank!=2");
  m = shape[0];
  n = shape[1];
  cb = ssl2_getcary(b,&nn);
  if (nn!=MAX(m,n)) rb_raise(rb_eRuntimeError,"b.length!=max(m,n)");
  cisw = NUM2INT(isw);
  if (cisw!=0&&cisw!=1&&cisw!=2) rb_raise(rb_eRuntimeError,"isw must be 0, 1, or 2");
  ceps = NUM2FLT(eps);
  if (ceps<0) rb_raise(rb_eRuntimeError,"eps<0");

  csig = ALLOC_N(float,n);
  v = ALLOC_N(float,n*MIN(m+1,n));
  vw = ALLOC_N(float,n);
  laxlm_(ca,&m,&m,&n,cb,&cisw,&ceps,csig,v,&n,vw,&icon);
  free(ca);
  free(v);
  free(vw);

  shape[0] = MAX(m,n);
  b = ssl2_getary(cb,1,shape);
  free(cb);
  shape[0] = n;
  sig = ssl2_getary(csig,1,shape);
  free(csig);
  free(shape);

  ssl2_error(icon);
  return rb_ary_new3(2,b,sig);
}

static VALUE
rb_ginv(self,a,eps)
     VALUE self,a,eps;
{
  float *ca;
  int m,n;
  float *csig;
  float *cv;
  float ceps;
  float *vw;
  int icon;

  VALUE sig,v;
  int rank;
  int *shape;

  ca = ssl2_getcary_withshape(a,&shape,&rank);
  if (rank!=2) rb_raise(rb_eRuntimeError,"a.rank!=2");
  m = shape[0];
  n = shape[1];
  ceps = NUM2FLT(eps);
  if (ceps<0) rb_raise(rb_eRuntimeError,"eps<0");

  csig = ALLOC_N(float,n);
  cv = ALLOC_N(float,n*MIN(m+1,n));
  vw = ALLOC_N(float,n);
  ginv_(ca,&m,&m,&n,csig,cv,&n,&ceps,vw,&icon);
  free(ca);
  free(vw);

  shape[0] = n;
  sig = ssl2_getary(csig,1,shape);
  free(csig);
  shape[1] = MIN(m+1,n);
  v = ssl2_getary(cv,2,shape);
  free(cv);
  free(shape);

  ssl2_error(icon);
  return rb_ary_new3(2,sig,v);
}

static VALUE
rb_asvd1(self,a,isw)
     VALUE self,a,isw;
{
  float *ca;
  int m,n;
  int cisw;
  float *csig;
  float *cu;
  float *cv;
  float *vw;
  int icon;

  VALUE sig,u,v;
  int rank;
  int *shape;

  int nn;

  ca = ssl2_getcary_withshape(a,&shape,&rank);
  if (rank!=2) rb_raise(rb_eRuntimeError,"a.rank!=2");
  m = shape[0];
  n = shape[1];
  cisw = NUM2INT(isw);
  if (cisw!=0&&cisw!=1&&cisw!=10&&cisw!=11) rb_raise(rb_eRuntimeError,"isw must be 0,1,10,or 11");

  csig = ALLOC_N(float,MIN(m,n));
  cu = ALLOC_N(float,m*n);
  cv = ALLOC_N(float,n*MIN(m+1,n));
  vw = ALLOC_N(float,n);
  asvd1_(ca,&m,&m,&n,&cisw,csig,cu,&n,cv,&n,vw,&icon);
  free(ca);
  free(vw);

  shape[0] = MIN(m,n);
  sig = ssl2_getary(csig,1,shape);
  free(csig);
  shape[0] = m;
  shape[1] = n;
  u = ssl2_getary(cu,2,shape);
  free(cu);
  shape[0] = n;
  shape[1] = MIN(m+1,n);
  v = ssl2_getary(cv,2,shape);
  free(cv);
  free(shape);

  ssl2_error(icon);
  switch (cisw){
  case 0:
    return sig;
  case 1:
    return rb_ary_new3(2,sig,v);
  case 10:
    return rb_ary_new3(2,sig,u);
  case 11:
    return rb_ary_new3(3,sig,u,v);
  }
}


void init_linear_algebra(mSSL2)
     VALUE mSSL2;
{
  rb_define_module_function(mSSL2, "cgsm", rb_cgsm, 1);
  rb_define_module_function(mSSL2, "csgm", rb_csgm, 1);
  rb_define_module_function(mSSL2, "cgsbm", rb_cgsbm, 2);
  rb_define_module_function(mSSL2, "csbgm", rb_csbgm, 2);
  rb_define_module_function(mSSL2, "cssbm", rb_cssbm, 2);
  rb_define_module_function(mSSL2, "csbsm", rb_csbsm, 2);
  rb_define_module_function(mSSL2, "aggm", rb_aggm, 2);
  rb_define_module_function(mSSL2, "sggm", rb_sggm, 2);
  rb_define_module_function(mSSL2, "mggm", rb_mggm, 2);
  rb_define_module_function(mSSL2, "mgsm", rb_mgsm, 2);
  rb_define_module_function(mSSL2, "assm", rb_assm, 2);
  rb_define_module_function(mSSL2, "sssm", rb_sssm, 2);
  rb_define_module_function(mSSL2, "mssm", rb_mssm, 2);
  rb_define_module_function(mSSL2, "msgm", rb_msgm, 2);
  rb_define_module_function(mSSL2, "mav", rb_mav, 2);
  rb_define_module_function(mSSL2, "mcv", rb_mcv, 3);
  rb_define_module_function(mSSL2, "msv", rb_msv, 2);
  rb_define_module_function(mSSL2, "msbv", rb_msbv, 3);
  rb_define_module_function(mSSL2, "mbv", rb_mbv, 4);
  rb_define_module_function(mSSL2, "lax", rb_lax, 4);
  rb_define_module_function(mSSL2, "lcx", rb_lcx, 4);
  rb_define_module_function(mSSL2, "lsix", rb_lsix, 4);
  rb_define_module_function(mSSL2, "lsbx", rb_lsbx, 5);
  rb_define_module_function(mSSL2, "lsbix", rb_lsbix, 6);
  rb_define_module_function(mSSL2, "lbx1", rb_lbx1, 6);
  rb_define_module_function(mSSL2, "lstx", rb_lstx, 5);
  rb_define_module_function(mSSL2, "ltx", rb_ltx, 6);
  rb_define_module_function(mSSL2, "laxr", rb_laxr, 5);
  rb_define_module_function(mSSL2, "lcxr", rb_lcxr, 5);
  rb_define_module_function(mSSL2, "lsxr", rb_lsxr, 4);
  rb_define_module_function(mSSL2, "lsixr", rb_lsixr, 5);
  rb_define_module_function(mSSL2, "lsbxr", rb_lsbxr, 5);
  rb_define_module_function(mSSL2, "lbxir", rb_lbx1r, 8);

  rb_define_module_function(mSSL2, "luiv", rb_luiv, 2);
  rb_define_module_function(mSSL2, "cluiv", rb_cluiv, 2);
  rb_define_module_function(mSSL2, "ldiv", rb_ldiv, 1);

  rb_define_module_function(mSSL2, "alu", rb_alu, 2);
  rb_define_module_function(mSSL2, "clu", rb_clu, 2);
  rb_define_module_function(mSSL2, "sldl", rb_sldl, 2);
  rb_define_module_function(mSSL2, "smdm", rb_smdm, 2);
  rb_define_module_function(mSSL2, "sbdl", rb_sbdl, 3);
  rb_define_module_function(mSSL2, "sbmdm", rb_sbmdm, 4);
  rb_define_module_function(mSSL2, "blu1", rb_blu1, 4);

  rb_define_module_function(mSSL2, "lux", rb_lux, 4);
  rb_define_module_function(mSSL2, "clux", rb_clux, 4);
  rb_define_module_function(mSSL2, "ldlx", rb_ldlx, 2);
  rb_define_module_function(mSSL2, "mdmx", rb_mdmx, 3);
  rb_define_module_function(mSSL2, "bdlx", rb_bdlx, 3);
  rb_define_module_function(mSSL2, "bmdmx", rb_bmdmx, 5);
  rb_define_module_function(mSSL2, "blux1", rb_blux1, 6);

  rb_define_module_function(mSSL2, "laxl", rb_laxl, 3);
  rb_define_module_function(mSSL2, "laxlr", rb_laxlr, 6);
  rb_define_module_function(mSSL2, "laxlm", rb_laxlm, 4);
  rb_define_module_function(mSSL2, "ginv", rb_ginv, 2);
  rb_define_module_function(mSSL2, "asvd1", rb_asvd1, 2);
}
