예제 #1
0
        public static string ConvertToString(BigInteger n, bool escape, int radix)
        {
            if (radix == -1)
            {
                radix = (int)Runtime.GetDynamic(Symbols.PrintBase);
            }

            if (radix == -1)
            {
                radix = 10;
            }
            else if (radix < 2 || radix > 36)
            {
                throw new LispException("Invalid number base: {0}", radix);
            }

            if (n == 0)
            {
                return "0";
            }

            var sign = (n >= 0) ? "" : "-";
            n = (n >= 0) ? n : -n;
            var stk = new Vector();
            while (n != 0)
            {
                var d = (int)(n % radix);
                if (d <= 9)
                {
                    stk.Add((char)(d + '0'));
                }
                else {
                    stk.Add((char)(d - 10 + 'a'));
                }
                n = n / radix;
            }
            stk.Reverse();
            if (escape)
            {
                switch (radix)
                {
                    case 10:
                        return sign + Runtime.MakeString(stk.ToArray());
                    case 16:
                        return sign + "0x" + Runtime.MakeString(stk.ToArray());
                    case 8:
                        return sign + "0" + Runtime.MakeString(stk.ToArray());
                    case 2:
                        return "#b" + sign + Runtime.MakeString(stk.ToArray());
                    default:
                        return "#" + radix + "r" + sign + Runtime.MakeString(stk.ToArray());
                }
            }
            else {
                return sign + Runtime.MakeString(stk.ToArray());
            }
        }
예제 #2
0
        /// <summary>
        /// Calculates the <c>true</c> residual of the matrix equation Ax = b according to: residual = b - Ax
        /// </summary>
        /// <param name="matrix">Instance of the <see cref="Matrix"/> A.</param>
        /// <param name="residual">Residual values in <see cref="Vector"/>.</param>
        /// <param name="x">Instance of the <see cref="Vector"/> x.</param>
        /// <param name="b">Instance of the <see cref="Vector"/> b.</param>
        private static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b)
        {
            // -Ax = residual
            matrix.Multiply(x, residual);
            
            // Do not use residual = residual.Negate() because it creates another object
            residual.Multiply(-1, residual);

            // residual + b
            residual.Add(b, residual);
        }
예제 #3
0
        /// <summary>
        /// Calculates the <c>true</c> residual of the matrix equation Ax = b according to: residual = b - Ax
        /// </summary>
        /// <param name="matrix">Instance of the <see cref="Matrix"/> A.</param>
        /// <param name="residual">Residual values in <see cref="Vector"/>.</param>
        /// <param name="x">Instance of the <see cref="Vector"/> x.</param>
        /// <param name="b">Instance of the <see cref="Vector"/> b.</param>
        static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b)
        {
            // -Ax = residual
            matrix.Multiply(x, residual);
            residual.Multiply(-1, residual);

            // residual + b
            residual.Add(b, residual);
        }
예제 #4
0
        /// <summary>
        /// Solves the matrix equation Ax = b, where A is the coefficient matrix, b is the
        /// solution vector and x is the unknown vector.
        /// </summary>
        /// <param name="matrix">The coefficient <see cref="Matrix"/>, <c>A</c>.</param>
        /// <param name="input">The solution <see cref="Vector"/>, <c>b</c>.</param>
        /// <param name="result">The result <see cref="Vector"/>, <c>x</c>.</param>
        public void Solve(Matrix matrix, Vector input, Vector result)
        {
            // If we were stopped before, we are no longer
            // We're doing this at the start of the method to ensure
            // that we can use these fields immediately.
            _hasBeenStopped = false;

            // Parameters checks
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }

            if (matrix.RowCount != matrix.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSquare, "matrix");
            }

            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            if (result == null)
            {
                throw new ArgumentNullException("result");
            }

            if (result.Count != input.Count)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            if (input.Count != matrix.RowCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixDimensions);
            }

            // Initialize the solver fields
            // Set the convergence monitor
            if (_iterator == null)
            {
                _iterator = Iterator.CreateDefault();
            }

            if (_preconditioner == null)
            {
                _preconditioner = new UnitPreconditioner();
            }
            
            _preconditioner.Initialize(matrix);
            
            // Compute r_0 = b - Ax_0 for some initial guess x_0
            // In this case we take x_0 = vector
            // This is basically a SAXPY so it could be made a lot faster
            Vector residuals = new DenseVector(matrix.RowCount);
            CalculateTrueResidual(matrix, residuals, result, input);

            // Choose r~ (for example, r~ = r_0)
            var tempResiduals = residuals.Clone();

            // create seven temporary vectors needed to hold temporary
            // coefficients. All vectors are mangled in each iteration.
            // These are defined here to prevent stressing the garbage collector
            Vector vecP = new DenseVector(residuals.Count);
            Vector vecPdash = new DenseVector(residuals.Count);
            Vector nu = new DenseVector(residuals.Count);
            Vector vecS = new DenseVector(residuals.Count);
            Vector vecSdash = new DenseVector(residuals.Count);
            Vector temp = new DenseVector(residuals.Count);
            Vector temp2 = new DenseVector(residuals.Count);

            // create some temporary double variables that are needed
            // to hold values in between iterations
            Complex currentRho = 0;
            Complex alpha = 0;
            Complex omega = 0;

            var iterationNumber = 0;
            while (ShouldContinue(iterationNumber, result, input, residuals))
            {
                // rho_(i-1) = r~^T r_(i-1) // dotproduct r~ and r_(i-1)
                var oldRho = currentRho;
                currentRho = tempResiduals.DotProduct(residuals);

                // if (rho_(i-1) == 0) // METHOD FAILS
                // If rho is only 1 ULP from zero then we fail.
                if (currentRho.Real.AlmostEqual(0, 1) && currentRho.Imaginary.AlmostEqual(0, 1))
                {
                    // Rho-type breakdown
                    throw new Exception("Iterative solver experience a numerical break down");
                }

                if (iterationNumber != 0)
                {
                    // beta_(i-1) = (rho_(i-1)/rho_(i-2))(alpha_(i-1)/omega(i-1))
                    var beta = (currentRho / oldRho) * (alpha / omega);

                    // p_i = r_(i-1) + beta_(i-1)(p_(i-1) - omega_(i-1) * nu_(i-1))
                    nu.Multiply(-omega, temp);
                    vecP.Add(temp, temp2);
                    temp2.CopyTo(vecP);

                    vecP.Multiply(beta, vecP);
                    vecP.Add(residuals, temp2);
                    temp2.CopyTo(vecP);
                }
                else
                {
                    // p_i = r_(i-1)
                    residuals.CopyTo(vecP);
                }

                // SOLVE Mp~ = p_i // M = preconditioner
                _preconditioner.Approximate(vecP, vecPdash);
                
                // nu_i = Ap~
                matrix.Multiply(vecPdash, nu);

                // alpha_i = rho_(i-1)/ (r~^T nu_i) = rho / dotproduct(r~ and nu_i)
                alpha = currentRho * 1 / tempResiduals.DotProduct(nu);

                // s = r_(i-1) - alpha_i nu_i
                nu.Multiply(-alpha, temp);
                residuals.Add(temp, vecS);

                // Check if we're converged. If so then stop. Otherwise continue;
                // Calculate the temporary result. 
                // Be careful not to change any of the temp vectors, except for
                // temp. Others will be used in the calculation later on.
                // x_i = x_(i-1) + alpha_i * p^_i + s^_i
                vecPdash.Multiply(alpha, temp);
                temp.Add(vecSdash, temp2);
                temp2.CopyTo(temp);
                temp.Add(result, temp2);
                temp2.CopyTo(temp);

                // Check convergence and stop if we are converged.
                if (!ShouldContinue(iterationNumber, temp, input, vecS))
                {
                    temp.CopyTo(result);

                    // Calculate the true residual
                    CalculateTrueResidual(matrix, residuals, result, input);

                    // Now recheck the convergence
                    if (!ShouldContinue(iterationNumber, result, input, residuals))
                    {
                        // We're all good now.
                        return;
                    }

                    // Continue the calculation
                    iterationNumber++;
                    continue;
                }

                // SOLVE Ms~ = s
                _preconditioner.Approximate(vecS, vecSdash);

                // temp = As~
                matrix.Multiply(vecSdash, temp);

                // omega_i = temp^T s / temp^T temp
                omega = temp.DotProduct(vecS) / temp.DotProduct(temp);

                // x_i = x_(i-1) + alpha_i p^ + omega_i s^
                temp.Multiply(-omega, residuals);
                residuals.Add(vecS, temp2);
                temp2.CopyTo(residuals);

                vecSdash.Multiply(omega, temp);
                result.Add(temp, temp2);
                temp2.CopyTo(result);

                vecPdash.Multiply(alpha, temp);
                result.Add(temp, temp2);
                temp2.CopyTo(result);

                // for continuation it is necessary that omega_i != 0.0
                // If omega is only 1 ULP from zero then we fail.
                if (omega.Real.AlmostEqual(0, 1) && omega.Imaginary.AlmostEqual(0, 1))
                {
                    // Omega-type breakdown
                    throw new Exception("Iterative solver experience a numerical break down");
                }

                if (!ShouldContinue(iterationNumber, result, input, residuals))
                {
                    // Recalculate the residuals and go round again. This is done to ensure that
                    // we have the proper residuals.
                    // The residual calculation based on omega_i * s can be off by a factor 10. So here
                    // we calculate the real residual (which can be expensive) but we only do it if we're
                    // sufficiently close to the finish.
                    CalculateTrueResidual(matrix, residuals, result, input);
                }

                iterationNumber++;
            }
        }
예제 #5
0
        public static object ParseInterpolateString(string s)
        {
            var pos = 0;
            var code = new Vector();

            for (var match = InterpolationStringPatterns.Match(s, pos); match.Success; match = match.NextMatch())
            {
                var left = match.Index;
                var sideEffect = false;
                var script = "";

                if (left != pos)
                {
                    code.Add(s.Substring(pos, left - pos));
                }

                pos = match.Index + match.Length;

                if (match.Groups[1].Success)
                {
                    // <%...%> or <%=...%>
                    script = match.Groups[1].Value.Trim();
                    if (script.StartsWith("="))
                    {
                        script = script.Substring(1);
                        sideEffect = false;
                    }
                    else
                    {
                        sideEffect = true;
                    }
                }
                else if (match.Groups[2].Success)
                {
                    // <!...!> or <!=...!>
                    script = match.Groups[2].Value.Trim();
                    if (script.StartsWith("="))
                    {
                        script = script.Substring(1);
                        sideEffect = false;
                    }
                    else
                    {
                        sideEffect = true;
                    }
                }
                else if (match.Groups[3].Success)
                {
                    // ${...}
                    script = match.Groups[3].Value;
                    sideEffect = false;
                }

                script = script.Trim();

                if (script.Length > 0)
                {
                    if (sideEffect)
                    {
                        if (script[0] != '(')
                        {
                            // must have function call to have side effect
                            script = "(with-output-to-string ($stdout) (" + script + "))";
                        }
                        else
                        {
                            script = "(with-output-to-string ($stdout) " + script + ")";
                        }
                    }
                    var statements = ReadAllFromString(script);

                    if (statements.Count > 1)
                    {
                        code.Add(new Cons(Symbols.Do, AsList(statements)));
                    }
                    else
                    {
                        code.AddRange(statements);
                    }
                }
            }

            if (code.Count == 0)
            {
                return s;
            }
            else
            {
                if (pos < s.Length)
                {
                    code.Add(s.Substring(pos, s.Length - pos));
                }

                return new Cons(Symbols.Str, AsList(code));
            }
        }
예제 #6
0
 public static object ReadVectorHandler2(LispReader stream, string ch, int arg)
 {
     if (stream.ReadChar() != '(')
     {
         throw stream.MakeScannerException("Invalid #() expression");
     }
     var list = stream.ReadDelimitedList(")");
     var obj = new Vector();
     obj.AddRange(list);
     if (arg == -1)
     {
         // default no action
     }
     else if (arg < obj.Count)
     {
         throw new LispException("Vector {0} contains more than {1} items", ToPrintString(obj), arg);
     }
     else if (arg > obj.Count)
     {
         var filler = obj.Count == 0 ? (object)null : obj[obj.Count - 1];
         while (obj.Count < arg)
         {
             obj.Add(filler);
         }
     }
     return obj;
 }
예제 #7
0
 public static string WriteToString(object item, params object[] kwargs)
 {
     using (var stream = new StringWriter())
     {
         var kwargs2 = new Vector(kwargs);
         kwargs2.Add(Symbols.Stream);
         kwargs2.Add(stream);
         Write(item, kwargs2.ToArray());
         return stream.ToString();
     }
 }
예제 #8
0
        public static void Write(object item, bool crlf, params object[] kwargs)
        {
            var args = ParseKwargs(true, kwargs, new string[] { "escape", "width", "stream", "padding", "pretty", "left", "right", "base", "force", "format" },
                           GetDynamic(Symbols.PrintEscape), 0, MissingValue, " ", false, null, null, -1,
                           GetDynamic(Symbols.PrintForce), null);

            var outputstream = args[2];
            var stream = ConvertToTextWriter(outputstream);

            if (stream == null)
            {
                return;
            }

            var escape = ToBool(args[0]);
            var width = ToInt(args[1]);
            var padding = MakeString(args[3]);
            var pretty = ToBool(args[4]);
            var left = args[5];
            var right = args[6];
            var radix = ToInt(args[7]);
            var force = ToBool(args[8]);
            var format = (string)args[9];

            try
            {
                // Only the REPL result printer sets this variable to false.

                if (force)
                {
                    item = Force(item);
                }

                if (pretty && Symbols.PrettyPrintHook.Value != null)
                {
                    var saved = SaveStackAndFrame();

                    DefDynamic(Symbols.StdOut, stream);
                    DefDynamic(Symbols.PrintEscape, escape);
                    DefDynamic(Symbols.PrintBase, radix);
                    DefDynamic(Symbols.PrintForce, false);

                    var kwargs2 = new Vector();
                    kwargs2.Add(item);
                    kwargs2.Add(Symbols.Left);
                    kwargs2.Add(left);
                    kwargs2.Add(Symbols.Right);
                    kwargs2.Add(right);

                    ApplyStar((IApply)Symbols.PrettyPrintHook.Value, kwargs2);

                    if (crlf)
                    {
                        PrintLine();
                    }

                    RestoreStackAndFrame(saved);
                }
                else {
                    WriteImp(item, stream, escape, width, padding, radix, crlf, format);
                }
            }
            finally
            {
                if (outputstream is string)
                {
                    // Appending to log file
                    stream.Close();
                }
            }
        }