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()); } }
/// <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); }
/// <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); }
/// <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++; } }
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)); } }
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; }
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(); } }
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(); } } }