# Extension of GPhys class for Gfdnavi

require "numru/gphys"

module NumRu
  class GPhys

    # == Parameters @@read_size_limit_1 and @@read_size_limit_2
    # 
    # By default, both are nil, so no restriction is made
    # on the size of data to read in onto run-time memory.
    # To limit it, set these parameters explicitly by calling 
    # the class methods read_size_limit_1= and/or read_size_limit_2=.
    # 
    # It's up to the programmer how to use the
    # two limits. It's OK to use only one of them.
    # If both are set, it is recommended to set as
    # @@read_size_limit_2 > @@read_size_limit_1, because
    # of the order of judgements (the former is evaluated first).

    @@read_size_limit_1 = nil   # e.g., 2000000
    @@read_size_limit_2 = nil   # e.g., 10000000


    class Read_Size_Limit_2_Exceeded < StandardError
    end

    class Read_Size_Limit_1_Exceeded < StandardError
    end

    # class method definitions:
    class << self

      alias :__new__ :new

      # Limit the size of data to read in with GPhys#val.
      # This is implemented by defining singletone method
      # for the VArray that represent the main data array.
      # (Note that no restriction is made for coordinate varaibles,
      # which is practically unnecessary.)
      def new(*argv)
	gp = __new__(*argv)
	data = gp.data
	def data.val
	  if @@read_size_limit_2 && length > @@read_size_limit_2
	    raise Read_Size_Limit_2_Exceeded, "Exceeded the maximum array size to read in (length=#{@@read_size_limit_2}). Reduce the size by using the 'axes' window, and try again. (Or perhaps you may get around the error by programming with GPhys::each_along_dims.)"
	  elsif @@read_size_limit_1 && length > @@read_size_limit_1
	    raise Read_Size_Limit_1_Exceeded, "Exceeded the maximum array size to read in (length=#{@@read_size_limit_1}). Reduce the size by using the 'axes' window, and try again. (Or perhaps you may get around the error by programming with GPhys::each_along_dims.)"
	  end
	  super
	end
	gp
      end

      # Set internal parameter @@read_size_limit_1
      def read_size_limit_1= (limit)
	return if limit.nil?
	raise(ArgumentError,"Expect an integer") if !limit.is_a?(Integer)
	@@read_size_limit_1 = limit
      end

      # Set internal parameter @@read_size_limit_2 
      def read_size_limit_2= (limit)
	return if limit.nil?
	raise(ArgumentError,"Expect an integer") if !limit.is_a?(Integer)
	@@read_size_limit_2 = limit
      end

      def read_size_limit_1
	@@read_size_limit_1
      end

      def read_size_limit_2
	@@read_size_limit_1
      end

    end

  end
end

