Beispiel #1
0
        double[] CalculateMultipleWithBuffer(MemoryStream codeStream, IReadOnlyTable <double> table, double[][] parameters)
        {
            int iterations = parameters.GetLength(0);
            Stack <double[]> resultStack = new Stack <double[]>();

            byte[] buffer = new byte[sizeof(double)];

            // a small memory & time optimization: it allows multiple usage of number buffers after performing calculations on them
            Queue <double[]> freeValueBuffers = new Queue <double[]>();

            while (true)
            {
                int command = codeStream.ReadByte();
                if (command == -1)
                {
                    throw new Exception("Can't execute next command");
                }

                double[] values = (freeValueBuffers.Count > 0) ? freeValueBuffers.Dequeue() : new double[iterations];

                if ((PostfixFunction.PostfixCommand)command == PostfixFunction.PostfixCommand.End)
                {
                    return(resultStack.Pop());
                }

                switch ((PostfixFunction.PostfixCommand)command)
                {
                case PostfixFunction.PostfixCommand.PushLiteral:
                {
                    codeStream.Read(buffer, 0, sizeof(double));
                    double literal = BitConverter.ToDouble(buffer, 0);

                    for (int i = 0; i < iterations; ++i)
                    {
                        values[i] = literal;
                    }
                }
                break;

                case PostfixFunction.PostfixCommand.PushVariable:
                {
                    codeStream.Read(buffer, 0, sizeof(int));
                    int index = BitConverter.ToInt32(buffer, 0);

                    for (int i = 0; i < iterations; ++i)
                    {
                        values[i] = table[index];
                    }
                }
                break;

                case PostfixFunction.PostfixCommand.PushParameter:
                {
                    codeStream.Read(buffer, 0, sizeof(int));
                    int index = BitConverter.ToInt32(buffer, 0);

                    for (int i = 0; i < iterations; ++i)
                    {
                        values[i] = parameters[i][index];
                    }
                }
                break;

                case PostfixFunction.PostfixCommand.CalculateUnary:
                {
                    double[] operands = resultStack.Pop();

                    codeStream.Read(buffer, 0, sizeof(int));
                    int            id        = BitConverter.ToInt32(buffer, 0);
                    UnaryOperation operation = (UnaryOperation)Operation.AllOperations[id];

                    for (int i = 0; i < values.Length; ++i)
                    {
                        values[i] = operation.Function(operands[i]);
                    }

                    // add free buffer to the queue
                    freeValueBuffers.Enqueue(operands);
                }
                break;

                case PostfixFunction.PostfixCommand.CalculateBinary:
                {
                    // pop in reverse order!
                    double[] rightOperands = resultStack.Pop();
                    double[] leftOperands  = resultStack.Pop();

                    codeStream.Read(buffer, 0, sizeof(int));
                    int             id        = BitConverter.ToInt32(buffer, 0);
                    BinaryOperation operation = (BinaryOperation)Operation.AllOperations[id];

                    for (int i = 0; i < values.Length; ++i)
                    {
                        values[i] = operation.Function(leftOperands[i], rightOperands[i]);
                    }

                    // add free buffers to the queue
                    freeValueBuffers.Enqueue(rightOperands);
                    freeValueBuffers.Enqueue(leftOperands);
                }
                break;
                }

                resultStack.Push(values);
            }
        }
Beispiel #2
0
        public double Calculate(PostfixFunction function, double[] parameters)
        {
            Stack <double> resultStack = new Stack <double>();
            MemoryStream   codeStream  = function.GetStream();

            byte[] buffer = new byte[sizeof(double)];

            while (true)
            {
                int command = codeStream.ReadByte();
                if (command == -1)
                {
                    throw new Exception("Can't execute next command");
                }

                switch ((PostfixFunction.PostfixCommand)command)
                {
                case PostfixFunction.PostfixCommand.End: return(resultStack.Pop());

                case PostfixFunction.PostfixCommand.PushLiteral:
                {
                    codeStream.Read(buffer, 0, sizeof(double));
                    double literal = BitConverter.ToDouble(buffer, 0);
                    resultStack.Push(literal);
                }
                break;

                case PostfixFunction.PostfixCommand.PushVariable:
                {
                    codeStream.Read(buffer, 0, sizeof(int));
                    int index = BitConverter.ToInt32(buffer, 0);
                    resultStack.Push(function.OriginalFunction.VariableTable[index]);
                }
                break;

                case PostfixFunction.PostfixCommand.PushParameter:
                {
                    codeStream.Read(buffer, 0, sizeof(int));
                    int index = BitConverter.ToInt32(buffer, 0);
                    resultStack.Push(parameters[index]);
                }
                break;

                case PostfixFunction.PostfixCommand.CalculateUnary:
                {
                    double operand = resultStack.Pop();

                    codeStream.Read(buffer, 0, sizeof(int));
                    int            id        = BitConverter.ToInt32(buffer, 0);
                    UnaryOperation operation = (UnaryOperation)Operation.AllOperations[id];
                    resultStack.Push(operation.Function(operand));
                }
                break;

                case PostfixFunction.PostfixCommand.CalculateBinary:
                {
                    // pop in reverse order!
                    double rightOperand = resultStack.Pop();
                    double leftOperand  = resultStack.Pop();

                    codeStream.Read(buffer, 0, sizeof(int));
                    int             id        = BitConverter.ToInt32(buffer, 0);
                    BinaryOperation operation = (BinaryOperation)Operation.AllOperations[id];
                    resultStack.Push(operation.Function(leftOperand, rightOperand));
                }
                break;

                default: throw new Exception("Unknown command");
                }
            }
        }