private static void Add(Hashtable m, OperationPtg ptgKey,
     NPOI.SS.Formula.Functions.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;
 }
        /**
         * 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;
        }
        /**
         * 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");
            }
            NPOI.SS.Formula.Functions.Function result = _instancesByPtgClass[ptg] as NPOI.SS.Formula.Functions.Function;

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

            if (ptg is AbstractFunctionPtg)
            {
                AbstractFunctionPtg fptg = (AbstractFunctionPtg)ptg;
                int functionIndex = fptg.FunctionIndex;
                switch (functionIndex)
                {
                    case NPOI.SS.Formula.Function.FunctionMetadataRegistry.FUNCTION_INDEX_INDIRECT:
                        return Indirect.instance.Evaluate(args, ec);
                    case NPOI.SS.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 + ")");
        }