/**
         * returns the OperationEval concrete impl instance corresponding
         * to the supplied operationPtg
         */
        public static ValueEval Evaluate(OperationPtg ptg, ValueEval[] args,
                OperationEvaluationContext ec)
        {
            if(ptg == null) {
            throw new ArgumentException("ptg must not be null");
            }
            Function result = _instancesByPtgClass[ptg] as Function;

            if (result != null) {
            return  result.Evaluate(args, ec.RowIndex, (short) ec.ColumnIndex);
            }

            if (ptg is AbstractFunctionPtg) {
            AbstractFunctionPtg fptg = (AbstractFunctionPtg)ptg;
            int functionIndex = fptg.GetFunctionIndex();
            switch (functionIndex) {
                case NPOI.HSSF.Record.Formula.Function.FunctionMetadataRegistry.FUNCTION_INDEX_INDIRECT:
                    return Indirect.instance.Evaluate(args, ec);
                case NPOI.HSSF.Record.Formula.Function.FunctionMetadataRegistry.FUNCTION_INDEX_EXTERNAL:
                    return UserDefinedFunction.instance.Evaluate(args, ec);
            }

            return FunctionEval.GetBasicFunction(functionIndex).Evaluate(args, ec.RowIndex, ec.ColumnIndex);
            }
            throw new Exception("Unexpected operation ptg class (" + ptg.GetType().Name + ")");
        }
        /**
         * returns the OperationEval concrete impl instance corresponding
         * to the supplied operationPtg
         */
        public static OperationEval Create(OperationPtg ptg)
        {
            if (ptg == null)
            {
                throw new ArgumentException("ptg must not be null");
            }

            Type ptgClass = ptg.GetType();

            ConstructorInfo constructor = (ConstructorInfo)_constructorsByPtgClass[ptgClass];
            if (constructor == null)
            {
                if (ptgClass == typeof(ExpPtg))
                {
                    // ExpPtg Is used for array formulas and shared formulas.
                    // it Is currently Unsupported, and may not even Get implemented here
                    throw new Exception("ExpPtg currently not supported");
                }
                throw new Exception("Unexpected operation ptg class (" + ptgClass.Name + ")");
            }

            Object result;
            Object[] initargs = { ptg };
            try
            {
                result = constructor.Invoke(initargs);
            }
            catch (Exception)
            {
                throw;
            }
            return (OperationEval)result;
        }
 private static void Add(Hashtable m, OperationPtg ptgKey,
     Function instance)
 {
     // make sure ptg has single private constructor because map lookups assume singleton keys
     ConstructorInfo[] cc = ptgKey.GetType().GetConstructors();
     if (cc.Length > 1 || (cc.Length>0&&!cc[0].IsPrivate))
     {
         throw new Exception("Failed to verify instance ("
                 + ptgKey.GetType().Name + ") is a singleton.");
     }
     m[ptgKey] = instance;
 }