require "ispack_raw.so"

class C2PACK
  def initialize(lm,km,jm,im,r)
    @lm,@km,@jm,@im,@r = lm,km,jm,im,r
    @itj,@tj,@iti,@ti = ISPACK::c2init(@jm,@im)
  end

#  attr_accessor :lm, :km, :jm, :im, :r
  attr_reader :lm, :km, :jm, :im, :r, :itj, :tj, :iti, :ti

  def _alloc_w(length)
    if !@w || @w.length < length
      @w = NArray.float(length)
    end
  end
  def _alloc_ws(length)
    if !@ws || @ws.length < length
      @ws = NArray.float(length)
    end
  end
  def _alloc_wg(length)
    if !@wg || @wg.length < length
      @wg = NArray.float(length)
    end
  end
  private :_alloc_w, :_alloc_ws, :_alloc_wg

  def ajb2(z, s)
    _alloc_ws(((2*@km+1)*(@lm+1)))
    _alloc_wg(((@jm+1)*@im*4))
    dz,ds = ISPACK::c2ajb2(@lm,@km,@jm,@im,@r,z,s,@ws,@wg,@itj,@tj,@iti,@ti)
    return dz.reshape!(@km*2+1,@lm), ds.reshape!(@km*2+1,@lm)
  end
  def ajbs(z)
    _alloc_ws(((2*@km+1)*(@lm+1)))
    _alloc_wg(((@jm+1)*@im*3))
    ISPACK::c2ajbs(@lm,@km,@jm,@im,@r,z,@ws,@wg,@itj,@tj,@iti,@ti).reshape!(@km*2+1,@lm)
  end
  def ajc2(sa, sb1, sb2)
    _alloc_ws(((2*@km+1)*(@lm+1)))
    _alloc_wg(((@jm+1)*@im*4))
    sc1,sc2 = ISPACK::c2ajc2(@lm,@km,@jm,@im,sa,sb1,sb2,@ws,@wg,@itj,@tj,@iti,@ti)
    return sc1.reshape!(@km*2+1,@lm), sc2.reshape!(@km*2+1,@lm)
  end
  def ajcb(sa, sb)
    _alloc_ws(((2*@km+1)*(@lm+1)))
    _alloc_wg(((@jm+1)*@im*3))
    ISPACK::c2ajcb(@lm,@km,@jm,@im,sa,sb,@ws,@wg,@itj,@tj,@iti,@ti).reshape!(@km*2+1,@lm)
  end
  def g2sa(g, isw)
    _alloc_w(((@jm+1)*@im))
    s = ISPACK::c2g2sa(@lm,@km,@jm,@im,g,@w,@itj,@tj,@iti,@ti,isw)
    case(isw)
    when 1,3
      return s[0..(@km*2+1)*@lm-1].reshape!(@km*2+1,@lm)
    when 2,4
      return s[0..(@km*2+1)*(@lm+1)-1].reshape!(@km*2+1,@lm+1)
    end
  end
  def g2st(gg)
    ISPACK::c2g2st(@jm,@im,gg).reshape!(@jm+1,@im)
  end
  def s2ga(s, isw)
    _alloc_w(((@jm+1)*@im))
    ISPACK::c2s2ga(@lm,@km,@jm,@im,s,@w,@itj,@tj,@iti,@ti,isw).reshape!(@jm+1,@im)
  end
  def s2gt(g)
    ISPACK::c2s2gt(@jm,@im,g).reshape!(@im,@jm+1)
  end
  def swbl(barphi, avt, phi)
    _alloc_ws(((2*@km+1)*(@lm+1)))
    _alloc_wg(((@jm+1)*@im*4))
    ISPACK::c2swbl(@lm,@km,@jm,@im,@r,barphi,avt,@ws,@wg,@itj,@tj,@iti,@ti).reshape!(@km*2+1,@lm+1)
  end
  def swck(avt, div, phi)
    _alloc_ws(((2*@km+1)*(@lm+1)))
    _alloc_wg(((@jm+1)*@im*4))
    ISPACK::c2swck(@lm,@km,@jm,@im,@r,avt,div,phi,@ws,@wg,@itj,@tj,@iti,@ti)
  end
  def swnl(avt, div, phi)
    _alloc_ws(((2*@km+1)*(@lm+1)))
    _alloc_wg(((@jm+1)*@im*4))
    davt,ddiv,dphi = ISPACK::c2swnl(@lm,@km,@jm,@im,@r,avt,div,phi,@ws,@wg,@itj,@tj,@iti,@ti)
    return davt.reshape!(@km*2+1,@lm), ddiv.reshape!(@km*2+1,@lm+1), dphi.reshape!(@km*2+1,@lm+1)
  end
  def swnn(barphi, avt, div)
    _alloc_ws(((2*@km+1)*(@lm+1)))
    _alloc_wg(((@jm+1)*@im*4))
    davt,ddiv,dphi = ISPACK::c2swnn(@lm,@km,@jm,@im,@r,barphi,avt,div,@ws,@wg,@itj,@tj,@iti,@ti)
    return davt.reshape!(@km*2+1,@lm), ddiv.reshape!(@km*2+1,@lm+1), dphi.reshape!(@km*2+1,@lm+1)
  end
end

class N2PACK
  def initialize(lm,km,jm,im)
    @lm,@km,@jm,@im = lm,km,jm,im
    @itj,@tj,@iti,@ti = ISPACK::n2init(@jm,@im)
  end

#  attr_accessor :lm, :km, :jm, :im
  attr_reader :lm, :km, :jm, :im, :itj, :tj, :iti, :ti

  def _alloc_w(length)
    if !@w || @w.length < length
      @w = NArray.float(length)
    end
  end
  def _alloc_ws(length)
    if !@ws || @ws.length < length
      @ws = NArray.float(length)
    end
  end
  def _alloc_wg(length)
    if !@wg || @wg.length < length
      @wg = NArray.float(length)
    end
  end
  private :_alloc_w, :_alloc_ws, :_alloc_wg

  def ajbs(z)
    _alloc_ws(((2*@km+1)*(2*@lm+1)))
    _alloc_wg((@jm*@im*3))
    ISPACK::n2ajbs(@lm,@km,@jm,@im,z,@ws,@wg,@itj,@tj,@iti,@ti).reshape!(@lm*2+1,@km*2+1)
  end
  def g2sa(g)
    _alloc_w((@jm*@im))
    ISPACK::n2g2sa(@lm,@km,@jm,@im,g,@w,@itj,@tj,@iti,@ti).reshape!(@lm*2+1,@km*2+1)
  end
  def s2ga(s)
    _alloc_w((@jm*@im))
    ISPACK::n2s2ga(@lm,@km,@jm,@im,s,@w,@itj,@tj,@iti,@ti).reshape!(@jm,@im)
  end
  def swbl(barphi, avt)
    _alloc_ws(((2*@km+1)*(2*@lm+1)*2))
    _alloc_wg((@jm*@im*5))
    ISPACK::n2swbl(@lm,@km,@jm,@im,barphi,avt,@ws,@wg,@itj,@tj,@iti,@ti).reshape!(@lm*2+1,@km*2+1)
  end
  def swck(avt, div, phi)
    _alloc_ws(((2*@km+1)*(2*@lm+1)*2))
    _alloc_wg((@jm*@im*5))
    ISPACK::n2swck(@lm,@km,@jm,@im,avt,div,phi,@ws,@wg,@itj,@tj,@iti,@ti)
  end
  def swnl(avt, div, phi)
    _alloc_ws(((2*@km+1)*(2*@lm+1)*2))
    _alloc_wg((@jm*@im*5))
    davt,ddiv,dphi = ISPACK::n2swnl(@lm,@km,@jm,@im,avt,div,phi,@ws,@wg,@itj,@tj,@iti,@ti)
    return davt.reshape!(@lm*2+1,@km*2+1), ddiv.reshape!(@lm*2+1,@km*2+1), dphi.reshape!(@lm*2+1,@km*2+1)
  end
  def swnn(barphi, f, avt, div, phi)
    _alloc_ws(((2*@km+1)*(2*@lm+1)*2))
    _alloc_wg((@jm*@im*5))
    davt,ddiv,dphi = ISPACK::n2swnn(@lm,@km,@jm,@im,barphi,f,avt,div,phi,@ws,@wg,@itj,@tj,@iti,@ti)
    return davt.reshape!(@lm*2+1,@km*2+1), ddiv.reshape!(@lm*2+1,@km*2+1), dphi.reshape!(@lm*2+1,@km*2+1)
  end
end

class P2PACK
  def initialize(lm,km,jm,im,r)
    @lm,@km,@jm,@im,@r = lm,km,jm,im,r
    @itj,@tj,@iti,@ti = ISPACK::p2init(@jm,@im)
  end

#  attr_accessor :lm, :km, :jm, :im, :r
  attr_reader :lm, :km, :jm, :im, :r, :itj, :tj, :iti, :ti

  def _alloc_w(length)
    if !@w || @w.length < length
      @w = NArray.float(length)
    end
  end
  def _alloc_ws(length)
    if !@ws || @ws.length < length
      @ws = NArray.float(length)
    end
  end
  def _alloc_wg(length)
    if !@wg || @wg.length < length
      @wg = NArray.float(length)
    end
  end
  private :_alloc_w, :_alloc_ws, :_alloc_wg

  def ajbs(z)
    _alloc_ws(((2*@km+1)*(2*@lm+1)))
    _alloc_wg((@jm*@im*3))
    ISPACK::p2ajbs(@lm,@km,@jm,@im,@r,z,@ws,@wg,@itj,@tj,@iti,@ti).reshape!(@lm*2+1,@km*2+1)
  end
  def ajcb(sa,sb)
    _alloc_ws(((2*@km+1)*(2*@lm+1)))
    _alloc_wg((@jm*@im*3))
    ISPACK::p2ajcb(@lm,@km,@jm,@im,sa,sb,@ws,@wg,@itj,@tj,@iti,@ti).reshape!(@lm*2+1,@km*2+1)
  end
  def g2sa(g)
    _alloc_w((@jm*@im))
    ISPACK::p2g2sa(@lm,@km,@jm,@im,g,@w,@itj,@tj,@iti,@ti).reshape!(@lm*2+1,@km*2+1)
  end
  def s2ga(s)
    _alloc_w((@jm*@im))
    ISPACK::p2s2ga(@lm,@km,@jm,@im,s,@w,@itj,@tj,@iti,@ti).reshape!(@jm,@im)
  end
  def swbl(barphi, avt)
    _alloc_ws(((2*@km+1)*(2*@lm+1)))
    _alloc_wg((@jm*@im*4))
    ISPACK::p2swbl(@lm,@km,@jm,@im,@r,barphi,avt,@ws,@wg,@itj,@tj,@iti,@ti).reshape!(@lm*2+1,@km*2+1)
  end
  def swck(avt, div, phi)
    _alloc_ws(((2*@km+1)*(2*@lm+1)))
    _alloc_wg((@jm*@im*4))
    ISPACK::p2swck(@lm,@km,@jm,@im,@r,avt,div,phi,@ws,@wg,@itj,@tj,@iti,@ti)
  end
  def swnl(avt, div, phi)
    _alloc_ws(((2*@km+1)*(2*@lm+1)))
    _alloc_wg((@jm*@im*4))
    davt,ddiv,dphi = ISPACK::p2swnl(@lm,@km,@jm,@im,@r,avt,div,phi,@ws,@wg,@itj,@tj,@iti,@ti)
    return davt.reshape!(@lm*2+1,@km*2+1), ddiv.reshape!(@lm*2+1,@km*2+1), dphi.reshape!(@lm*2+1,@km*2+1)
  end
  def swnn(barphi, f, avt, div, phi)
    _alloc_ws(((2*@km+1)*(2*@lm+1)))
    _alloc_wg((@jm*@im*4))
    davt,ddiv,dphi = ISPACK::p2swnn(@lm,@km,@jm,@im,@r,barphi,f,avt,div,phi,@ws,@wg,@itj,@tj,@iti,@ti)
    return davt.reshape!(@lm*2+1,@km*2+1), ddiv.reshape!(@lm*2+1,@km*2+1), dphi.reshape!(@lm*2+1,@km*2+1)
  end
end

class P3PACK
  def initialize(nm,mm,lm,km,jm,im)
    @nm,@mm,@lm,@km,@jm,@im = nm,mm,lm,km,jm,im
    @itk,@tk,@itj,@tj,@iti,@ti = ISPACK::p3init(@jm,@im)
  end

#  attr_accessor :lm, :km, :jm, :im
  attr_reader :nm, :mm, :lm, :km, :jm, :im, :itk, :tk, :itj, :tj, :iti, :ti

  def _alloc_w(length)
    if !@w || @w.length < length
      @w = NArray.float(length)
    end
  end
  def _alloc_ws(length)
    if !@ws || @ws.length < length
      @ws = NArray.float(length)
    end
  end
  private :_alloc_w, :_alloc_ws

  def cnsv(z)
    ISPACK::p3cnsv(@nm,@mm,@lm,z)
  end
  def elnl(z)
    _alloc_ws((2*@nm+1)*(2*@mm+1)*(2*@lm+1))
    _alloc_w((@km*@jm*@im*4))
    ISPACK::p3elnl(@nm,@mm,@lm,@km,@jm,@im,z,@ws,@w,@itk,@tk,@itj,@tj,@iti,@ti).reshape!(@nm*2+1,@mm*2+1,@lm*2+1,2)
  end
  def espt(kmax, z)
    ISPACK::p3espt(@nm,@mm,@lm,kmax,z)
  end
  def g2sa(g)
    _alloc_w((@km*@jm*@im))
    ISPACK::p3g2sa(@nm,@mm,@lm,@km,@jm,@im,g,@w,@itk,@tk,@itj,@tj,@iti,@ti).reshape!(@nm*2+1,@mm*2+1,@lm*2+1)
  end
  def geto(z, isw)
    ISPACK::p3geto(@nm,@mm,@lm,z,isw).reshape!(@nm*2+1,@mm*2+1,@lm*2+1)
  end
  def getu(z, isw)
    ISPACK::p3getu(@nm,@mm,@lm,z,isw).reshape!(@nm*2+1,@mm*2+1,@lm*2+1)
  end
  def s2ga(s)
    _alloc_w((@km*@jm*@im))
    ISPACK::p3s2ga(@nm,@mm,@lm,@km,@jm,@im,s,@w,@itk,@tk,@itj,@tj,@iti,@ti).reshape!(@km,@jm,@im)
  end
end

class SMPACK
  def initialize(mm,im,jm,km)
    @mm,@im,@jm,@km = mm,im,jm,km
    @x,@y,@w,@it,@t,@ip,@p,@qsg,@qgs,@qsv,@qvs,@qsu,@qus,@r,@ml,@nl,@rf,@rb = ISPACK::sminit(@mm,@im,@jm,@km)
  end

#  attr_accessor :mm, :im, :jm, :km
  attr_reader :mm, :im, :jm, :km, :x, :y, :w, :it, :t, :ip, :p, 
    :qsg, :qgs, :qsv, :qvs, :qsu, :qus, :r, :ml, :nl, :rf, :rb

  def _alloc_work(length)
    if !@work || @work.length < length
      @work = NArray.float(length)
    end
  end
  private :_alloc_work

  def clap(a)
    ISPACK::smclap(@mm,@km,a,@rf).reshape!((@mm+1)*(@mm+1),@km)
  end
  def l2nm(l)
    ISPACK::sml2nm(@mm,l)
  end
  def nm2l(n,m)
    ISPACK::smnm2l(@mm,n,m)
  end
  def tg2s(g)
    id = g.shape[0]
    jd = g.shape[1]
    _alloc_work(id*jd*@km*2)
    ISPACK::smtg2s(@mm,@im,id,@jm,jd,@km,g,@work,@it,@t,@ip,@p,@qgs).reshape!((@mm+1)*(@mm+1),@km)
  end
#  def ts1v(a, id=@im/2*2+1, jd=@jm/2*2+1)
  def ts1v(a, id=@im, jd=@jm)
    _alloc_work(id*jd*@km*2)
    u,v = ISPACK::smts1v(@mm,@im,id,@jm,jd,@km,a,@work,@it,@t,@ip,@p,@qsv,@r,@ml)
    return u.reshape!(id,jd,@km), v.reshape!(id,jd,@km)
  end
#  def ts2g(s, id=@im/2*2+1, jd=@jm/2*2+1)
  def ts2g(s, id=@im, jd=@jm)
    _alloc_work(id*jd*@km)
    ISPACK::smts2g(@mm,@im,id,@jm,jd,@km,s,@work,@it,@t,@ip,@p,@qsg).reshape!(@id,@jd,@km)
  end
#  def ts2v(a, b, id=@im/2*2+1, jd=@jm/2*2+1)
  def ts2v(a, b, id=@im, jd=@jm)
    _alloc_work(id*jd*@km*2)
    u,v = ISPACK::smts2v(@mm,@im,id,@jm,jd,@km,a,b,@work,@it,@t,@ip,@p,@qsv,@r,@ml)
    return u.reshape!(id,jd,@km), v.reshape!(id,jd,@km)
  end
  def tv1s(u, v)
    id = u.shape[0]
    jd = u.shape[1]
    _alloc_work(id*jd*@km*3)
    ISPACK::smtv1s(@mm,@im,id,@jm,jd,@km,u,v,@work,@it,@t,@ip,@p,@qvs,@r,@ml).reshape!(id,jd,@km).reshape!((@mm+1)*(@mm+1),@km)
  end
  def tv2s(u, v)
    id = u.shape[0]
    jd = u.shape[1]
    _alloc_work(id*jd*@km*3)
    a,b = ISPACK::smtv2s(@mm,@im,id,@jm,jd,@km,u,v,@work,@it,@t,@ip,@p,@qvs,@r,@ml)
    return a.reshape!((@mm+1)*(@mm+1),@km), b.reshape!((@mm+1)*(@mm+1),@km)
  end
end

class SNPACK
  def initialize(mm,im,jm,km)
    @mm,@im,@jm,@km = mm,im,jm,km
    @it,@t,@y,@ip,@p,@r,@ia,@a = ISPACK::sninit(@mm,@im,@jm)
    if @km > 1
      @ipk,@pk,@rk = ISPACK::snkini(@mm,@jm,@km,@ip,@p,@r)
    end
  end

#  attr_accessor :mm, :im, :jm, :km
  attr_reader :mm, :im, :jm, :km, :it, :t, :y, :ip, :p, :r, :ia, :a
#  if @km > 1
#    attr_reader :ipk, :pk, :rk
#  end

  def _alloc_q(length)
    if !@q || @q.length < length
      @q = NArray.float(length)
    end
  end
  def _alloc_ws(length)
    if !@ws || @ws.length < length
      @ws = NArray.float(length)
    end
  end
  def _alloc_ww(length)
    if !@ww || @ww.length < length
      @ww = NArray.float(length)
    end
  end
  private :_alloc_q, :_alloc_ws, :_alloc_ww

  def l2nm(l)
    ISPACK::snl2nm(l)
  end
  def nm2l(n,m)
    ISPACK::snnm2l(n,m)
  end
  def tg2s(g, ipow, iflag)
    id = g.shape[0]
    jd = g.shape[1]
    _alloc_q(((@km*(@mm+1)/2+@mm+1)*@jm))
    size_w = @km*[((@mm+1)/2*2+3)*(@mm/2+2)*2,jd*((@mm+1)/2+@mm+1)*2,jd*@im].max
    _alloc_ws(size_w)
    _alloc_ww(size_w)
    if @km > 1
      ISPACK::sntg2s(@mm,@im,id,@jm,jd,@km,g,@it,@t,@y,@ipk,@pk,@rk,@ia,@a,@q,@ws,@ww,ipow,iflag).reshape!((@mm+1)*(@mm+1),@km)
    else
      ISPACK::sntg2s(@mm,@im,id,@jm,jd,@km,g,@it,@t,@y,@ip,@p,@r,@ia,@a,@q,@ws,@ww,ipow,iflag)
    end
  end
#  def ts2g(s, ipow, iflag, id=@im/2*2+1, jd=@jm/2*2+1 )
  def ts2g(s, ipow, iflag, id=@im, jd=@jm )
    _alloc_q((@km*((@mm+1)/2+@mm+1)*@jm))
    size_w = @km*[((@mm+1)/2*2+3)*(@mm/2+2)*2,jd*((@mm+1)/2+@mm+1)*2,jd*@im].max
    _alloc_ws(size_w)
    _alloc_ww(size_w)
    if @km > 1
      ISPACK::snts2g(@mm,@im,id,@jm,jd,@km,s,@it,@t,@y,@ipk,@pk,@rk,@ia,@a,@q,@ws,@ww,ipow,iflag).reshape!(id,jd,@km)
    else
      ISPACK::snts2g(@mm,@im,id,@jm,jd,@km,s,@it,@t,@y,@ip,@p,@r,@ia,@a,@q,@ws,@ww,ipow,iflag).reshape!(id,jd)
    end
  end
end

class SOPACK < SNPACK
  def initialize(mm,im,jm)
    @mm0 = mm
    super(mm+1,im,jm,2)
    @ib,@b = ISPACK::soinit(mm)
  end

#  def ndnl(s, id=@im/2*2+1, jd=@jm/2*2+1)
  def ndnl(s, id=@im, jd=@jm)
    _alloc_q((2*((@mm+2)/2+@mm+2)*@jm))
    size_w = @km*[((@mm+1)/2*2+3)*(@mm/2+2)*2,jd*((@mm+1)/2+@mm+1)*2,jd*id].max
    _alloc_ws(size_w)
    _alloc_ww(size_w)
    ISPACK::sondnl(@mm,@im,id,@jm,jd,s,@it,@t,@y,@ipk,@pk,@rk,@ia,@a,@ib,@b,@q,@ws,@ww)
  end
end

class STPACK
  def initialize(mm,jm,im)
    @mm,@jm,@im = mm,jm,im
    @q,@r,@it,@t = ISPACK::stinit(@mm,@jm,@im)
  end

#  attr_accessor :mm, :jm, :im
  attr_reader :mm, :jm, :im, :q, :r, :it, :t

  def _alloc_p(length)
    if !@p || @p.length < length
      @p = NArray.float(length)
    end
  end
  private :_alloc_p

  def ajba(a, b)
    _alloc_p((@jm*@im*4))
    ISPACK::stajba(@mm,@jm,@im,a,b,@p,@q,@r,@it,@t)
  end
  def clba(a)
    ISPACK::stclba(@mm,a)
  end
  def clfa(a)
    ISPACK::stclfa(@mm,a)
  end
  def g2sa(g)
    _alloc_p((@jm*@im))
    ISPACK::stg2sa(@mm,@jm,@im,g,@p,@q,@r,@it,@t)
  end
  def l2nm(l)
    ISPACK::stl2nm(@mm,l)
  end
  def nm2l(n,m)
    ISPACK::stnm2l(@mm,n,m)
  end
  def ogrd()
    ISPACK::stogrd(@jm,@im,@q)
  end
  def s2ga(s)
    _alloc_p((@jm*@im))
    ISPACK::sts2ga(@mm,@jm,@im,s,@p,@q,@r,@it,@t).reshape!(@jm,@im)
  end
  def s2va(s)
    _alloc_p((@jm*@im))
    u,v = ISPACK::sts2va(@mm,@jm,@im,s,@p,@q,@r,@it,@t)
    return u.reshape!(@jm,@im), v.reshape!(@jm,@im)
  end
  def srva(s)
    _alloc_p((@jm*@im))
    u,v = ISPACK::stsrva(@mm,@jm,@im,s,@p,@q,@r,@it,@t)
    return u.reshape!(@jm,@im), v.reshape!(@jm,@im)
  end
  def v2sa(u, v)
    _alloc_p((@jm*@im))
    ISPACK::stv2sa(@mm,@jm,@im,u,v,@p,@q,@r,@it,@t)
  end
  def vrsa(u, v)
    _alloc_p((@jm*@im))
    ISPACK::stvrsa(@mm,@jm,@im,u,v,@p,@q,@r,@it,@t)
  end
end

class LTPACK
  def initialize(mm,jm)
    @mm,@jm = mm,jm
    @q,@r = ISPACK::ltinit(@mm,@jm)
  end

#  attr_accessor :mm, :jm
  attr_reader :mm, :jm, :q, :r

  def _alloc_p(length)
    if !@p || @p.length < length
      @p = NArray.float(length)
    end
  end
  private :_alloc_p

  def clbw(a)
    ISPACK::ltclbw(@mm,@m,a)
  end
  def clbz(a)
    ISPACK::ltclbz(@mm,a)
  end
  def clfw(a)
    ISPACK::ltclfw(@mm,@m,a)
  end
  def clfz(a)
    ISPACK::ltclfz(@mm,a)
  end
  def g2sw(g)
    _alloc_p(@jm)
    ISPACK::ltg2sw(@mm,@jm,@m,g,@p,@q,@r)
  end
  def g2sz(g)
    _alloc_p(@jm)
    ISPACK::ltg2sz(@mm,@jm,g,@p,@q,@r)
  end
  def ogrd()
    ISPACK::ltogrd(@jm,@q)
  end
  def s2gw(s)
    _alloc_p(@jm)
    ISPACK::lts2gw(@mm,@jm,@m,s,@p,@q,@r,@im)
  end
  def s2gz(s)
    _alloc_p(@jm)
    ISPACK::lts2gz(@mm,@jm,s,@p,@q,@r,@im)
  end
  def s2vw(s)
    _alloc_p(@jm)
    ISPACK::lts2vw(@mm,@jm,@m,s,@p,@q,@r,@im)
  end
  def s2vz(s)
    _alloc_p(@jm)
    ISPACK::lts2vz(@mm,@jm,s,@p,@q,@r,@im)
  end
  def srvw(s)
    _alloc_p(@jm)
    ISPACK::ltsrvw(@mm,@jm,@m,s,@p,@q,@r,@im)
  end
  def srvz(s)
    _alloc_p(@jm)
    ISPACK::ltsrvz(@mm,@jm,s,@p,@q,@r,@im)
  end
  def v2sw(u, v)
    _alloc_p(@jm)
    ISPACK::ltv2sw(@mm,@jm,@m,u,v,@p,@q,@r)
  end
  def v2sz(v)
    _alloc_p(@jm)
    ISPACK::ltv2sz(@mm,@jm,v,@p,@q,@r)
  end
  def vrsw(u, v)
    _alloc_p(@jm)
    ISPACK::ltvrsw(@mm,@jm,@m,u,v,@p,@q,@r)
  end
  def vrsz(u)
    _alloc_p(@jm)
    ISPACK::ltvrsz(@mm,@jm,u,@p,@q,@r)
  end
end

class SPPACK < SNPACK
  def initialize(mm,im,jm,id=nil,jd=nil)
    @mm,@im,@jm = mm,im,jm
    @it,@t,@y,@ip,@p,@r,@ia,@a = ISPACK::sninit(@mm,@im,@jm)
    @rn = ISPACK::spnini(@mm)
    @irm = ISPACK::spmini(@mm)
#    @id = @im/2*2+1 # least odd number >= @im
#    @jd = @jm/2*2+1 # least odd number >= @jm
    if(id)
      @id = id
    else
      @id = @im
    end
    if(jd)
      @jd = jd
    else
      @jd = @jm
    end
    @km = 1
  end

#  attr_accessor :mm, :im, :jm
  attr_reader :mm, :im, :jm, :it, :t, :y, :ip, :p, :r, :ia, :a, :rn, :irm, :id, :jd

  def _alloc_2
    if !@ip2 || !@p2 || !@r2
      @ip2,@p2,@r2 = ISPACK::snkini(@mm,@jm,2,@ip,@p,@r)
    end
  end
  def _alloc_3
    if !@ip3 || !@p3 || !@r3
      @ip3,@p3,@r3 = ISPACK::snkini(@mm,@jm,3,@ip,@p,@r)
    end
  end
  def _alloc_4
    if !@ip4 || !@p4 || !@r4
      @ip4,@p4,@r4 = ISPACK::snkini(@mm,@jm,4,@ip,@p,@r)
    end
  end
  def _alloc_5
    if !@ip5 || !@p5 || !@r5
      @ip5,@p5,@r5 = ISPACK::snkini(@mm,@jm,5,@ip,@p,@r)
    end
  end
  private :_alloc_2, :_alloc_3, :_alloc_4

  def clam(a)
    ISPACK::spclam(@mm,a,@irm)
  end
  def clap(a)
    ISPACK::spclap(@mm,a,@rn)
  end
  def njcb(sa, sb)
#    _alloc_q(((3*(@mm+1)/2+@mm+1)*@jm))
    _alloc_q(3*((@mm+1)/2+@mm+1)*@jm)
    size_w = 3*[((@mm+1)/2*2+3)*(@mm/2+2)*2,@jd*((@mm+1)/2+@mm+1)*2,@jd*@id].max
    _alloc_ws(size_w)
    _alloc_ww(size_w)
    _alloc_2
    _alloc_3
    ISPACK::spnjcb(@mm,@im,@id,@jm,@jd,sa,sb,@it,@t,@y,@ip2,@p2,@r2,@ip3,@p3,@r3,@ia,@a,@q,@ws,@ww)
  end
  def swck(omega, avt, div, phi)
#    _alloc_q(((4*(@mm+1)/2+@mm+1)*@jm))
    _alloc_q(4*((@mm+1)/2+@mm+1)*@jm)
    size_w = 4*[((@mm+1)/2*2+3)*(@mm/2+2)*2,@jd*((@mm+1)/2+@mm+1)*2,@jd*@id].max
    _alloc_ws(size_w)
    _alloc_ww(size_w)
    _alloc_4
    ISPACK::spswck(@mm,@im,@id,@jm,@jd,omega,avt,div,phi,@rn,@it,@t,@y,@ip4,@p4,@r4,@ia,@a,@q,@ws,@ww)
  end
  def swcv(omega, avt, div, phi)
#    _alloc_q(((4*(@mm+1)/2+@mm+1)*@jm))
    _alloc_q(4*((@mm+1)/2+@mm+1)*@jm)
    size_w = [((@mm+1)/2*2+3)*(@mm/2+2)*2,@jd*((@mm+1)/2+@mm+1)*2,@jd*@id].max
    _alloc_ws(size_w*4)
    _alloc_ww(size_w)
    ISPACK::spswcv(@mm,@im,@id,@jm,@jd,omega,avt,div,phi,@rn,@it,@t,@y,@ip,@p,@r,@ia,@a,@q,@ws,@ww)
  end
  def swcx(omega, avt, div, phi)
#    _alloc_q(((4*(@mm+1)/2+@mm+1)*@jm))
    _alloc_q(4*((@mm+1)/2+@mm+1)*@jm)
    size_w = [((@mm+1)/2*2+3)*(@mm/2+2)*2,@jd*((@mm+1)/2+@mm+1)*2,@jd*@id].max
    _alloc_ws(size_w*4)
    _alloc_ww(size_w)
    ISPACK::spswcx(@mm,@im,@id,@jm,@jd,omega,avt,div,phi,@rn,@it,@t,@y,@ip,@p,@r,@ia,@a,@q,@ws,@ww)
  end
  def swhi(barphi, dnu, alpha, lev, dt)
    ISPACK::spswhi(@mm,barphi,dnu,alpha,lev,dt)
  end
  def swhv(omega, barphi, dnu, alpha, lev, avt, div, phi)
    _alloc_q((((@mm+1)/2+@mm+1)*@jm))
    size_w = [((@mm+1)/2*2+3)*(@mm/2+2)*2,@jd*((@mm+1)/2+@mm+1)*2,@jd*@id].max
    _alloc_ws(size_w*11)
    _alloc_ww(size_w)
    ISPACK::spswhv(@mm,@im,@id,@jm,@jd,omega,barphi,dnu,alpha,lev,avt,div,phi,@rn,@irm,@it,@t,@y,@ip,@p,@r,@ia,@a,@q,@ws,@ww)
  end
  def swhw(omega, barphi, dnu, alpha, lev, avt, div, phi)
    _alloc_q((((@mm+1)/2+@mm+1)*@jm))
    size_w = 11*[((@mm+1)/2*2+3)*(@mm/2+2)*2,@jd*((@mm+1)/2+@mm+1)*2,@jd*@id].max
    _alloc_ws(size_w)
    _alloc_ww(size_w)
    ISPACK::spswhw(@mm,@im,@id,@jm,@jd,omega,barphi,dnu,alpha,lev,avt,div,phi,@rn,@irm,@it,@t,@y,@ip,@p,@r,@ia,@a,@q,@ws,@ww)
  end
  def swhx(omega, barphi, dnu, lev, avt, div, phi)
    _alloc_q((((@mm+1)/2+@mm+1)*@jm))
    size_w = 10*[((@mm+1)/2*2+3)*(@mm/2+2)*2,@jd*((@mm+1)/2+@mm+1)*2,@jd*@id].max
    _alloc_ws(size_w)
    _alloc_ww(size_w)
    ISPACK::spswhx(@mm,@im,@id,@jm,@jd,omega,barphi,dnu,lev,avt,div,phi,@rn,@irm,@it,@t,@y,@ip,@p,@r,@ia,@a,@q,@ws,@ww)
  end
  def swli(barphi, dnu, alpha, dt)
    ISPACK::spswli(@mm,barphi,dnu,alpha,dt)
  end
  def swlv(avt, div, phi, cl)
    ISPACK::spswlv(@mm,avt,div,phi,cl)
  end
  def swnl(omega, avt, div, phi)
#    _alloc_q(((5*(@mm+1)/2+@mm+1)*@jm))
    _alloc_q(5*((@mm+1)/2+@mm+1)*@jm)
    size_w = 5*[((@mm+1)/2*2+3)*(@mm/2+2)*2,@jd*((@mm+1)/2+@mm+1)*2,@jd*@id].max
    _alloc_ws(size_w)
    _alloc_ww(size_w)
    _alloc_4
    _alloc_5
    ISPACK::spswnl(@mm,@im,@id,@jm,@jd,omega,avt,div,phi,@rn,@it,@t,@y,@ip4,@p4,@r4,@ip5,@p5,@r5,@ia,@a,@q,@ws,@ww)
  end
  def swnv(omega, barphi, dnu, alpha, avt, div, phi)
    _alloc_q((((@mm+1)/2+@mm+1)*@jm))
    size_w = [((@mm+1)/2*2+3)*(@mm/2+2)*2,@jd*((@mm+1)/2+@mm+1)*2,@jd*@id].max
    _alloc_ws(size_w*8)
    _alloc_ww(size_w)
    ISPACK::spswnv(@mm,@im,@id,@jm,@jd,omega,barphi,dnu,alpha,avt,div,phi,@rn,@irm,@it,@t,@y,@ip,@p,@r,@ia,@a,@q,@ws,@ww)
  end
  def swnw(omega, barphi, dnu, alpha, avt, div, phi)
    _alloc_q((((@mm+1)/2+@mm+1)*@jm))
    size_w = 8*[((@mm+1)/2*2+3)*(@mm/2+2)*2,@jd*((@mm+1)/2+@mm+1)*2,@jd*@id].max
    _alloc_ws(size_w)
    _alloc_ww(size_w)
    ISPACK::spswnw(@mm,@im,@id,@jm,@jd,omega,barphi,dnu,alpha,avt,div,phi,@rn,@irm,@it,@t,@y,@ip,@p,@r,@ia,@a,@q,@ws,@ww)
  end
  def swnx(omega, barphi, dnu, avt, div, phi)
    _alloc_q((((@mm+1)/2+@mm+1)*@jm))
    size_w = 7*[((@mm+1)/2*2+3)*(@mm/2+2)*2,@jd*((@mm+1)/2+@mm+1)*2,@jd*@id].max
    _alloc_ws(size_w)
    _alloc_ww(size_w)
    ISPACK::spswnx(@mm,@im,@id,@jm,@jd,omega,barphi,dnu,avt,div,phi,@rn,@irm,@it,@t,@y,@ip,@p,@r,@ia,@a,@q,@ws,@ww)
  end
end

class FTTZL
  def initialize(n)
    @n = n
    @it,@t = ISPACK::fttzli(n)
  end
#  attr_accessor :n
  attr_reader :n, :it, :t

  def _alloc_y(length)
    if !@y || @y.length < length
      @y = NArray.float(length)
    end
  end
  private :_alloc_y

  def m(x)
    raise "args must be a 3-d narray" if x.rank != 3
    shape = x.shape
    @m = shape[0]
    _alloc_y(@m*@n*2)
    ISPACK::fttzlm(@m,@n,x,@y,@it,@t).reshape!(*shape)
  end
end

class FTTZU
  def initialize(n)
    @n = n
    @it,@t = ISPACK::fttzui(n)
  end
#  attr_accessor :n
  attr_reader :n, :it, :t

  def _alloc_y(length)
    if !@y || @y.length < length
      @y = NArray.float(length)
    end
  end
  private :_alloc_y

  def f(x)
    raise "args must be a 3-d narray" if x.rank != 3
    shape = x.shape
    @m = shape[0]
    _alloc_y(@m*@n*2)
    ISPACK::fttzuf(@m,@n,x,@y,@it,@t).reshape!(*shape)
  end
  def b(x)
    raise "args must be a 3-d narray" if x.rank != 3
    shape = x.shape
    @m = shape[0]
    _alloc_y(@m*@n*2)
    ISPACK::fttzub(@m,@n,x,@y,@it,@t).reshape!(*shape)
  end
end

class FTTRU
  def initialize(n)
    @n = n
    @it,@t = ISPACK::fttrui(n)
  end
#  attr_accessor :n
  attr_reader :n, :it, :t

  def _alloc_y(length)
    if !@y || @y.length < length
      @y = NArray.float(length)
    end
  end
  private :_alloc_y

  def f(x)
    raise "args must be a 3-d narray" if x.rank != 3
    shape = x.shape
    @m = shape[0]
    _alloc_y(@m*@n*2)
    ISPACK::fttruf(@m,@n,x,@y,@it,@t).reshape!(*shape)
  end
  def b(x)
    raise "args must be a 3-d narray" if x.rank != 3
    shape = x.shape
    @m = shape[0]
    _alloc_y(@m*@n*2)
    ISPACK::fttrub(@m,@n,x,@y,@it,@t).reshape!(*shape)
  end
end

class FTTCT
  def initialize(n)
    @n = n
    @it,@t = ISPACK::fttcti(n)
  end
#  attr_accessor :n
  attr_reader :n, :it, :t

  def _alloc_y(length)
    if !@y || @y.length < length
      @y = NArray.float(length)
    end
  end
  private :_alloc_y

  def f(x)
    raise "args must be a 3-d narray" if x.rank != 3
    shape = x.shape
    @m = shape[0]
    _alloc_y(@m*@n*2)
    ISPACK::fttctf(@m,@n,x,@y,@it,@t).reshape!(*shape)
  end
  def b(x)
    raise "args must be a 3-d narray" if x.rank != 3
    shape = x.shape
    @m = shape[0]
    _alloc_y(@m*@n*2)
    ISPACK::fttctb(@m,@n,x,@y,@it,@t).reshape!(*shape)
  end
end

class FTTST
  def initialize(n)
    @n = n
    @it,@t = ISPACK::fttsti(n)
  end
#  attr_accessor :n
  attr_reader :n, :it, :t

  def _alloc_y(length)
    if !@y || @y.length < length
      @y = NArray.float(length)
    end
  end
  private :_alloc_y

  def f(x)
    raise "args must be a 3-d narray" if x.rank != 3
    shape = x.shape
    @m = shape[0]
    _alloc_y(@m*@n*2)
    ISPACK::fttstf(@m,@n,x,@y,@it,@t).reshape!(*shape)
  end
  def b(x)
    raise "args must be a 3-d narray" if x.rank != 3
    shape = x.shape
    @m = shape[0]
    _alloc_y(@m*@n*2)
    ISPACK::fttstb(@m,@n,x,@y,@it,@t).reshape!(*shape)
  end
end

class FTTCM
  def initialize(n)
    @n = n
    @it,@t = ISPACK::fttcmi(n)
  end
#  attr_accessor :n
  attr_reader :n, :it, :t

  def _alloc_y(length)
    if !@y || @y.length < length
      @y = NArray.float(length)
    end
  end
  private :_alloc_y

  def f(x)
    raise "args must be a 3-d narray" if x.rank != 3
    shape = x.shape
    @m = shape[0]
    _alloc_y(@m*@n*2)
    ISPACK::fttcmf(@m,@n,x,@y,@it,@t).reshape!(*shape)
  end
  def b(x)
    raise "args must be a 3-d narray" if x.rank != 3
    shape = x.shape
    @m = shape[0]
    _alloc_y(@m*@n*2)
    ISPACK::fttcmb(@m,@n,x,@y,@it,@t).reshape!(*shape)
  end
end

class FTTSM
  def initialize(n)
    @n = n
    @it,@t = ISPACK::fttsmi(n)
  end
#  attr_accessor :n
  attr_reader :n, :it, :t

  def _alloc_y(length)
    if !@y || @y.length < length
      @y = NArray.float(length)
    end
  end
  private :_alloc_y

  def f(x)
    raise "args must be a 3-d narray" if x.rank != 3
    shape = x.shape
    @m = shape[0]
    _alloc_y(@m*@n*2)
    ISPACK::fttsmf(@m,@n,x,@y,@it,@t).reshape!(*shape)
  end
  def b(x)
    raise "args must be a 3-d narray" if x.rank != 3
    shape = x.shape
    @m = shape[0]
    _alloc_y(@m*@n*2)
    ISPACK::fttsmb(@m,@n,x,@y,@it,@t).reshape!(*shape)
  end
end


#class NDPACK
module ND
  def ca2p(omg, avt)
    @mm = (avt.length).sqrt-1
    ISPACK::ndca2p(@mm,omg,avt)
  end
  def cp2a(omg, psi)
    @mm = (psi.length).sqrt-1
    ISPACK::ndcp2a(@mm,omg,psi)
  end
  def disa(a, d)
    @mm = (a.length).sqrt-1
    ISPACK::nddisa(@mm,a,d)
  end
  def disi(mm, lev, dtdnu)
    ISPACK::nddisi(mm,lev,dtdnu)
  end
  def geea(psi)
    @mm = (psi.length).sqrt-1
    ISPACK::ndgeea(@mm,psi)
  end
  def geew(m, psi)
    @mm = (psi.length)/2-1+m
    ISPACK::ndgeew(@mm,m,psi)
  end
  def geez(psi)
    @mm = (psi.length)-1
    ISPACK::ndgeez(@mm,psi)
  end
  def gena(psi)
    @mm = (psi.length).sqrt-1
    ISPACK::ndgena(@mm,psi)
  end
  def genw(m, psi)
    @mm = (psi.length)/2-1+m
    ISPACK::ndgenw(@mm,m,psi)
  end
  def genz(psi)
    @mm = (psi.length)-1
    ISPACK::ndgenz(@mm,psi)
  end
  def ta2v(omg, vrt)
    ISPACK::ndta2v(omg,vrt)
  end
  def tv2a(omg, vrt)
    ISPACK::ndtv2a(omg,vrt)
  end
  def vis1(a)
    @mm = (a.length).sqrt-1
    ISPACK::ndvis1(@mm,a)
  end
end

