class Func
  def header
    print "module gms_math_mean\n"
    print "  use datatype\n"
    print "  use mem_manager\n"
    print "  implicit none\n"
  end

  def contains
    print "contains\n"
  end

  def footer
    print "end module gms_math_mean\n"
  end
end

class Func1
  Modname = "mean"
  def header1(name) #name = "x", "y", "z"
    print "  interface ",Modname,"_", name, "\n"
  end

  def header2(name, type)
    if type.index(name) != nil then
      print "    module procedure ",Modname,"_", name ,"_", type, "\n"
    end
  end

  def header3
    print "end interface\n\n"
  end

  def output(name, type)
    if type.index(name) != nil then
      outtype=""
      outtype=type.delete(name)

      print "  function ",Modname,"_", name, "_", type, "(input) result(output)\n"
      print "    type(var_", type, "), intent(in) :: input\n"
      if outtype.empty? then
	      print "    real(8) :: output\n"

         if name == "x" then 

	print "    if ( input%grid(1) == 0 ) then\n"
	print "      output & \n"
	print "         = sum( work_",type, "(plb1:pub1,1,1,input%id),1) / (pub1 - plb1 + 1)\n"
	print "    else \n"
	print "      output & \n"
	print "         = sum( work_",type, "(plb1+1:pub1,1,1,input%id),1) / (pub1 - plb1 )\n"
	print "    end if\n"
         elsif name == "y" then 

	print "    if ( input%grid(2) == 0 ) then\n"
	print "      output & \n"
	print "         = sum( work_",type, "(1,plb2:pub2,1,input%id),1) / (pub2 - plb2 + 1)\n"
	print "    else \n"
	print "      output & \n"
	print "         = sum( work_",type, "(1,plb2+1:pub2,1,input%id),1) / (pub2 - plb2 )\n"
	print "    end if\n"
         elsif name == "z" then 

	print "    if ( input%grid(3) == 0 ) then\n"
	print "      output & \n"
	print "         = sum( work_",type, "(1,1,plb3:pub3,input%id),1) / (pub3 - plb3 + 1)\n"
	print "    else \n"
	print "      output & \n"
	print "         = sum( work_",type, "(1,1,plb3+1:pub3,input%id),1) / (pub3 - plb3 )\n"
	print "    end if\n"
	 end


      else
      print "    type(var_", outtype, ") :: output\n"
      print "    integer :: new_id\n\n"

      print "    call get_new_id_", outtype, "(new_id)\n\n"
      print "    output%id = new_id\n\n"

      if name == "x" then 
	print "    output%grid(1) = 1\n"
	print "    output%grid(2) = input%grid(2)\n"
	print "    output%grid(3) = input%grid(3)\n\n"
	print "    if ( input%grid(1) == 0 ) then\n"
	print "      work_", outtype, "(1,:,:,new_id) & \n"
	print "         = sum( work_",type, "(plb1:pub1,:,:,input%id),1) / (pub1 - plb1 + 1)\n"
	print "    else \n"
	print "      work_", outtype, "(1,:,:,new_id) & \n"
	print "         = sum( work_",type, "(plb1+1:pub1,:,:,input%id),1) / (pub1 - plb1 )\n"
	print "    end if\n"
	print "     \n"

      elsif name == "y" then
	print "    output%grid(1) = input%grid(1)\n"
	print "    output%grid(2) = 1 \n"
	print "    output%grid(3) = input%grid(3)\n\n"
	print "    if ( input%grid(2) == 0 ) then\n"
	print "      work_", outtype, "(:,1,:,new_id) & \n"
	print "         = sum( work_",type, "(:,plb2:pub2,:,input%id),2) / (pub2 - plb2 + 1)\n"
	print "    else \n"
	print "      work_", outtype, "(:,1,:,new_id) & \n"
	print "         = sum( work_",type, "(:,plb2+1:pub2,:,input%id),2) / (pub2 - plb2 )\n"
	print "    end if\n"
	print "     \n"

      elsif name == "z" then
	print "    output%grid(1) = input%grid(1)\n"
	print "    output%grid(2) = input%grid(2)\n"
	print "    output%grid(3) = 1 \n\n"
	print "    if ( input%grid(3) == 0 ) then\n"
	print "      work_", outtype, "(:,:,1,new_id) & \n"
	print "         = sum( work_",type, "(:,:,plb3:pub3,input%id),3) / (pub3 - plb3 + 1)\n"
	print "    else \n"
	print "      work_", outtype, "(:,:,1,new_id) & \n"
	print "         = sum( work_",type, "(:,:,plb3+1:pub3,input%id),3) / (pub3 - plb3 )\n"
	print "    end if\n"
	print "     \n"


      end
      end

      print "  end function ",Modname,"_", name, "_", type, "\n\n"

#      end
    else return 
#      print "  function ",Modname,"_", name, "_", type, "(input) result(output)\n"
#      print "    type(var_", type, "), intent(in) :: input\n"
#      print "    type(var_", type, ") :: output\n"
#      print "    integer :: new_id\n\n"

#      print "    stop \"derivative ",Modname,"_", name, "_", type, "\"\n "
#      print "    output%grid = -1\n "
#      
#      print "  end function ",Modname,"_", name, "_", type, "\n\n"
    end
  end
end


func = Func.new
func1 = Func1.new

type=[6]
name=[2]

type[0] = "x"
type[1] = "y"
type[2] = "z"
type[3] = "xy"
type[4] = "xz"
type[5] = "yz"
type[6] = "xyz"

name[0] = "x"
name[1] = "y"
name[2] = "z"

func.header

for  i in 0..2 do
  func1.header1(name[i])
  for j in 0..6 do
    func1.header2(name[i], type[j])
  end
  func1.header3
end


func.contains

for i in 0..2 do
  for j in 0..6 do
    func1.output(name[i], type[j])
#    func2.output(name[i], type[j])
#    func4.output(name[i], type[j])
  end
end

func.footer
