/// <summary> /// Returns the minimal absolute distance between the components of /// the two matrices. /// </summary> public static __ftype__ DistanceMin(__nmtype__ a, __nmtype__ b) { return(Fun.Min( /*# n.ForEach(i => { */ Fun.Min( /*# m.ForEach(j => { */ Fun.Abs(b.M__i____j__ - a.M__i____j__) /*# * }, comma); */) /*# }, comma); */)); }
/// <summary> /// Perform a QR factorization of the supplied m x n matrix using /// Householder transofmations, i.e. A = QR, where Q is orthogonal /// (a product of n-2 Householder-Transformations) and R is a right /// upper n x n triangular matrix. An array of the diagonal elements /// of R is returned. WARNING: the supplied matrix A is overwritten /// with its factorization QR, both in the parameter aqr. /// </summary> public static double[] QrFactorize( this Matrix <double> aqr) { double[] diag = new double[Fun.Min(aqr.SX, aqr.SY)]; aqr.Data.QrFactorize(aqr.Origin, aqr.DX, aqr.DY, aqr.SX, aqr.SY, diag); return(diag); }
/// <summary> /// Fills the target array starting at offset with normalized /// Lerp/weighted combinations of the source array. /// </summary> public static Array LerpAndNormalizeTo( this Array source, IEnumerable <WeightedIndex[]> weightedIndexArrays, Array target, int offset) { int length = Fun.Min(weightedIndexArrays.Count(), target.Length - offset); return(source.LerpAndNormalizeTo(weightedIndexArrays, target, offset, length)); }
// Note that this version of the LU factorization is mostly provided // for studying the algorithm. In practice the Matrix<double> version // is noticeably faster, since it performs incremental indexing. /// <summary> /// Perform a partially pivoting LU factorization of the supplied /// matrix, i.e A = inv(P) LU, so that any matrix equation A x = b /// can be solved using LU x = P b. The permutation matrix P is /// returns as permutation vector. WARNING: the supplied matrix A is /// overwritten with its factorization LU, both in the parameter alu. /// If the matrix is singular an ArgumentException is thrown. /// </summary> public static int[] LuFactorize(this double[,] alu) { int n = Fun.Min(alu.GetLength(0), alu.GetLength(1)); int[] perm = new int[n]; if (alu.LuFactorize(perm)) { return(perm); } throw new ArgumentException("singular matrix"); }
/// <summary> /// Perform the supplied action for all triples of items from /// each of the supplied arrays. /// The action gets the index of the item as last parameter. /// </summary> public static void ForEach <T0, T1, T2>( this T0[] array0, T1[] array1, T2[] array2, Action <T0, T1, T2, int> item0_item1_item2_i_act) { int count = Fun.Min(array0.Length, array1.Length, array2.Length); for (int i = 0; i < count; i++) { item0_item1_item2_i_act(array0[i], array1[i], array2[i], i); } }
/// <summary> /// Perform the supplied action for all pairs of items in the array /// and from the second array. /// </summary> public static void ForEach <T0, T1>( this T0[] array0, T1[] array1, Action <T0, T1> item0_item1_act) { int count = Fun.Min(array0.Length, array1.Length); for (int i = 0; i < count; i++) { item0_item1_act(array0[i], array1[i]); } }
/// <summary> /// Return the inverse inv(A) of a the supplied LU factorized matrix /// lu, where A = inv(P) LU. The permuation matrix P is supplied as /// the permutation vector p. /// </summary> public static double[,] LuInverse(this double[,] lu, int[] p) { int n = Fun.Min(lu.GetLength(0), lu.GetLength(1)); if (n != p.GetLength(0)) { throw new ArgumentException(); } double[,] inv = new double[n, n]; lu.LuInverse(p, inv); return(inv); }
public static Tr[] Map2 <T0, T1, Tr>( this IList <T0> xs0, IList <T1> xs1, Func <T0, T1, int, Tr> item0_item1_index_fun) { var len = Fun.Min(xs0.Count, xs1.Count); var result = new Tr[len]; for (var i = 0; i < len; i++) { result[i] = item0_item1_index_fun(xs0[i], xs1[i], i); } return(result); }
public static List <Tr> Map2 <T0, T1, Tr>( this List <T0> list0, List <T1> list1, Func <T0, T1, Tr> item0_item1_fun) { var count = Fun.Min(list0.Count, list1.Count); var result = new List <Tr>(count); for (var i = 0; i < count; i++) { result.Add(item0_item1_fun(list0[i], list1[i])); } return(result); }
/// <summary> /// Solve a matrix equation of the form LU x = P b. /// LU is the supplied factorized matrix lu, P is a permutation matrix /// supplied as a permutation array p, and b is the right hand side /// supplied as a vector. The returned x satisfies the equation. /// </summary> public static double[] LuSolve(this double[,] lu, int[] p, double[] b) { int n = Fun.Min(lu.GetLength(0), lu.GetLength(1)); if (n != p.GetLength(0)) { throw new ArgumentException(); } if (n > b.GetLength(0)) { throw new ArgumentException(); } var x = new double[n]; lu.LuSolve(p, b, x); return(x); }
public static bool IsTrueFor(long value) { if (value < 0) { return(false); } if (value < isPrimeArray.Length) { return(isPrimeArray[value]); } int root = (int)Fun.Sqrt(value); int directMaxPrime = Fun.Min(primeArray[primeCount - 1], root); int pi; for (pi = 0; primeArray[pi] <= directMaxPrime; pi++) { if (value % primeArray[pi] == 0) { return(false); } } if (directMaxPrime == root) { return(true); } while (true) { int p = Prime.WithIndex(pi); if (p > root) { break; } if (value % p == 0) { return(false); } pi++; } return(true); }
public void Log(LogMsg msg) { if (msg.Type == LogType.End) { if (m_state.Buffer.Length > 0 && (m_state.Type == LogType.Info || (m_state.Type != LogType.Unknown && m_state.LeftPos != msg.LeftPos))) // different indent == other job { WriteAct(m_state.TIdx, m_state.Type, m_state.Level, m_state.GetBufferLineAndClear()); } if ((msg.Opt & (LogOpt.Timed | LogOpt.NewText)) == 0) { return; // if End is not timed, suppress repeated start message } } if (msg.Type == LogType.Progress && !AllowBackspace) { msg.Opt |= LogOpt.EndLine; } if (LogCompleteLinesOnly) { if (msg.Type == LogType.Begin) { msg.Opt = msg.Opt | LogOpt.EndLine; if ((msg.Opt & LogOpt.Timed) != 0) { msg.RightText = ""; } } else if (msg.Type == LogType.Progress) { msg.Opt = msg.Opt | LogOpt.EndLine; } } else if (m_state.Type == LogType.Begin) { if (msg.Type == LogType.End) { var pos = m_state.LeftPos + m_state.PrefixLength; var len = m_state.Buffer.Length - pos; if (len > 0 && // len < 0 if we are from a different indent == other job msg.LeftText.StartsWith(m_state.Buffer.ToString(pos, len))) { msg.LeftText = msg.LeftText.Substring(len); msg.LeftPos = 0; } } else if (msg.Type == LogType.Progress) { msg.LeftText = null; } else if ((msg.Opt & LogOpt.Wrap) == 0) { if (m_state.Timed) { m_state.AddDotsText(m_state.RightPos, "", m_width); // dots to line end } WriteAct(m_state.TIdx, m_state.Type, m_state.Level, m_state.GetBufferLineAndClear()); } } else if (m_state.Type == LogType.Progress) { if (msg.Type == LogType.Progress) { if (AllowBackspace) { if (m_state.DoneCount > 0) { WriteAct(m_state.TIdx, msg.Type, msg.Level, m_state.Backspace(msg.RightText.Length)); msg.LeftText = null; } else { m_state.Buffer.Clear(); } } } else if (msg.Type == LogType.End) { if (AllowBackspace) { if (m_state.DoneCount > 0) { var len = m_state.Buffer.Length - m_state.PrefixLength - m_state.LeftPos; WriteAct(m_state.TIdx, msg.Type, msg.Level, m_state.Backspace(len)); } else { m_state.Buffer.Clear(); } } } else { WriteAct(m_state.TIdx, m_state.Type, m_state.Level, m_state.GetBufferLineAndClear()); } } if ((msg.Opt & LogOpt.Wrap) != 0) { if (m_state.Buffer.Length + msg.LeftText.Length + 1 > Width + msg.RightPos) { WriteAct(m_state.TIdx, m_state.Type, m_state.Level, m_state.GetBufferLineAndClear()); } else if (m_state.Buffer.Length > 0 && m_state.Buffer[m_state.Buffer.Length - 1] != ' ') { m_state.Buffer.Append(' '); } } if (m_state.Buffer.Length == 0) { m_state.Buffer.Append(m_state.Prefix); } if (msg.LeftText != null) { m_state.AddSpaceText(Fun.Min(msg.LeftPos, m_maxIndent), msg.LeftText); } if (msg.RightText != null) { m_state.AddDotsText(Fun.Min(msg.RightPos, m_width), msg.RightText, m_width); } if ((msg.Opt & LogOpt.EndLine) != 0) { WriteAct(m_state.TIdx, msg.Type, msg.Level, m_state.GetBufferLineAndClear()); m_state.Type = LogType.Unknown; } else { if (!LogCompleteLinesOnly) { int pos = m_state.DoneCount; int len = m_state.Buffer.Length - pos; WriteAct(m_state.TIdx, msg.Type, msg.Level, m_state.Buffer.ToString(pos, len)); m_state.DoneCount = pos + len; } m_state.Type = msg.Type; m_state.Timed = (msg.Opt & LogOpt.Timed) != 0; m_state.LeftPos = msg.LeftPos; m_state.RightPos = msg.RightPos; // remember EndPos of timed begins for dotting to lineEnd } m_state.Level = msg.Level; }
/// <summary> /// Returns the rotation of the supplied counter clockwise enumerated /// convex polygon that results in the minimum area enclosing box. /// If multiple rotations are within epsilon in their area, the one /// that is closest to an axis-aligned rotation (0, 90, 180, 270) is /// returned. O(n). /// </summary> public static M22d ComputeMinAreaEnclosingBoxRotation( this Polygon2d polygon, double epsilon = 1e-6) { polygon = polygon.WithoutMultiplePoints(epsilon); var pc = polygon.PointCount; if (pc < 2) { return(M22d.Identity); } var ea = polygon.GetEdgeArray(); ea.Apply(v => v.Normalized); int i0 = 0, i1 = 0; int i2 = 0, i3 = 0; var min = polygon[0]; var max = polygon[0]; for (int pi = 1; pi < pc; pi++) { var p = polygon[pi]; if (p.Y < min.Y) { i0 = pi; min.Y = p.Y; } else if (p.Y > max.Y) { i2 = pi; max.Y = p.Y; } if (p.X > max.X) { i1 = pi; max.X = p.X; } else if (p.X < min.X) { i3 = pi; min.X = p.X; } } V2d p0 = polygon[i0], e0 = ea[i0], p1 = polygon[i1], e1 = ea[i1]; V2d p2 = polygon[i2], e2 = ea[i2], p3 = polygon[i3], e3 = ea[i3]; int end0 = (i0 + 1) % pc, end1 = (i1 + 1) % pc; int end2 = (i2 + 1) % pc, end3 = (i3 + 1) % pc; var dir = V2d.XAxis; var best = dir; var bestArea = double.MaxValue; var bestValue = double.MaxValue; while (true) { var s0 = Fun.FastAtan2(e0.Dot90(dir), e0.Dot(dir)); var s1 = Fun.FastAtan2(e1.Dot180(dir), e1.Dot90(dir)); var s2 = Fun.FastAtan2(e2.Dot270(dir), e2.Dot180(dir)); var s3 = Fun.FastAtan2(e3.Dot(dir), e3.Dot270(dir)); int si, si01, si23; double s01, s23; if (s0 < s1) { s01 = s0; si01 = 0; } else { s01 = s1; si01 = 1; } if (s2 < s3) { s23 = s2; si23 = 2; } else { s23 = s3; si23 = 3; } if (s01 < s23) { si = si01; } else { si = si23; } if (si == 0) { dir = ea[i0]; } else if (si == 1) { dir = ea[i1].Rot270; } else if (si == 2) { dir = ea[i2].Rot180; } else { dir = ea[i3].Rot90; } double sx = (p2 - p0).Dot90(dir), sy = (p1 - p3).Dot(dir); double area = sx * sy; double value = Fun.Min(Fun.Abs(dir.X), Fun.Abs(dir.Y)); if (area < bestArea - epsilon || (area < bestArea + epsilon && value < bestValue)) { bestArea = area; bestValue = value; best = dir; } if (si == 0) { if (++i0 >= pc) { i0 -= pc; } if (i0 == end1) { break; } p0 = polygon[i0]; e0 = ea[i0]; } else if (si == 1) { if (++i1 >= pc) { i1 -= pc; } if (i1 == end2) { break; } p1 = polygon[i1]; e1 = ea[i1]; } else if (si == 2) { if (++i2 >= pc) { i2 -= pc; } if (i2 == end3) { break; } p2 = polygon[i2]; e2 = ea[i2]; } else { if (++i3 >= pc) { i3 -= pc; } if (i3 == end0) { break; } p3 = polygon[i3]; e3 = ea[i3]; } } return(new M22d(best.X, best.Y, -best.Y, best.X)); }
/// <summary> /// Perform a QR factorization of the supplied m x n matrix using /// Householder transofmations, i.e. A = QR, where Q is orthogonal /// (a product of n-2 Householder-Transformations) and R is a right /// upper n x n triangular matrix. An array of the diagonal elements /// of R is returned. WARNING: the supplied matrix A is overwritten /// with its factorization QR, both in the parameter aqr. /// </summary> public static double[] QrFactorize(this double[,] aqr) { double[] diag = new double[Fun.Min(aqr.GetLength(0), aqr.GetLength(1))]; aqr.QrFactorize(diag); return(diag); }