/// <summary> /// Construct ellipse from two conjugate diameters, and set /// Axis0 to the major axis and Axis1 to the minor axis. /// The algorithm was constructed from first principles. /// Also computes the squared lengths of the major and minor /// half axis. /// </summary> public static __et__ FromConjugateDiameters(__vt__ center, /*# if (d == 3) { */ __vt__ normal, /*# } */ __vt__ a, __vt__ b, out double major2, out double minor2) { var ab = __vt__.Dot(a, b); double a2 = a.LengthSquared, b2 = b.LengthSquared; if (ab.IsTiny()) { if (a2 >= b2) { major2 = a2; minor2 = b2; return(new __et__(center, /*# if (d == 3) { */ normal, /*# } */ a, b)); } else { major2 = b2; minor2 = a2; return(new __et__(center, /*# if (d == 3) { */ normal, /*# } */ b, a)); } } else { var t = 0.5 * Fun.Atan2(2 * ab, a2 - b2); double ct = Fun.Cos(t), st = Fun.Sin(t); __vt__ v0 = a * ct + b * st, v1 = b * ct - a * st; a2 = v0.LengthSquared; b2 = v1.LengthSquared; if (a2 >= b2) { major2 = a2; minor2 = b2; return(new __et__(center, /*# if (d == 3) { */ normal, /*# } */ v0, v1)); } else { major2 = b2; minor2 = a2; return(new __et__(center, /*# if (d == 3) { */ normal, /*# } */ v1, v0)); } } }
public static Tup6 <float> Lanczos3f(double x) { const double a = 1.0 / 3.0; double px = Constant.Pi * x, pxa = px * a; if (pxa.IsTiny()) { return(new Tup6 <float>(0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f)); } double p1mx = Constant.Pi - px, p1mxa = p1mx * a; if (p1mxa.IsTiny()) { return(new Tup6 <float>(0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f)); } double p1px = Constant.Pi + px, p2px = Constant.PiTimesTwo + px; double p2mx = Constant.PiTimesTwo - px, p3mx = Constant.PiTimesThree - px; double spx = Fun.Sin(px), spxa = Fun.Sin(pxa); double sp1pxa = Fun.Sin(p1px * a), sp2pxa = Fun.Sin(p2px * a); return(new Tup6 <float>((float)(spx * sp2pxa / (p2px * p2px * a)), (float)(-spx * sp1pxa / (p1px * p1px * a)), (float)((spx / px) * (spxa / pxa)), (float)((spx / p1mx) * (sp2pxa / p1mxa)), (float)(-spx * sp1pxa / (p2mx * p2mx * a)), (float)(spx * spxa / (p3mx * p3mx * a)))); }
/// <summary> /// Creates a 2D rotation matrix with the specified angle in radians. /// </summary> /// <returns>2D Rotation Matrix</returns> public static M22d Rotation(double angleInRadians) { double cos = Fun.Cos(angleInRadians); double sin = Fun.Sin(angleInRadians); return(new M22d(cos, -sin, sin, cos)); }
/// <summary> /// Creates a 2D rotation matrix with the specified angle in radians. /// </summary> /// <returns>2D Rotation Matrix</returns> public static M22f Rotation(float angleInRadians) { float cos = Fun.Cos(angleInRadians); float sin = Fun.Sin(angleInRadians); return(new M22f(cos, -sin, sin, cos)); }
/// <summary> /// Creates a 2D rotation matrix with the specified angle in radians. /// </summary> /// <returns>2D Rotation Matrix</returns> public static M2__x2t__ Rotation(__ft__ angleInRadians) { __ft__ cos = Fun.Cos(angleInRadians); __ft__ sin = Fun.Sin(angleInRadians); return(new M2__x2t__(cos, -sin, sin, cos)); }
/// <summary> /// Creates new rotational matrix for "float value"-radians around Z-Axis. /// </summary> /// <returns>Rotational matrix.</returns> public static M44f RotationZ(float angleRadians) { float cos = Fun.Cos(angleRadians); float sin = Fun.Sin(angleRadians); return(new M44f(cos, -sin, 0, 0, sin, cos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)); }
/// <summary> /// Creates new rotational matrix for "double value"-radians around Z-Axis. /// </summary> /// <returns>Rotational matrix.</returns> public static M44d RotationZ(double angleRadians) { double cos = Fun.Cos(angleRadians); double sin = Fun.Sin(angleRadians); return(new M44d(cos, -sin, 0, 0, sin, cos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)); }
/// <summary> /// Creates new rotational matrix for "__ft__ value"-radians around Z-Axis. /// </summary> /// <returns>Rotational matrix.</returns> public static M4__x4t__ RotationZ(__ft__ angleRadians) { __ft__ cos = Fun.Cos(angleRadians); __ft__ sin = Fun.Sin(angleRadians); return(new M4__x4t__(cos, -sin, 0, 0, sin, cos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)); }
/// <summary> /// Generates normal distributed random variable with given mean and standard deviation. /// Uses the Box-Muller Transformation to transform two uniform distributed random variables to one normal distributed value. /// NOTE: If multiple normal distributed random values are required, consider using <see cref="RandomGaussian"/>. /// </summary> public static double Gaussian(this IRandomUniform rnd, double mean = 0.0, double stdDev = 1.0) { // Box-Muller Transformation var u1 = 1.0 - rnd.UniformDouble(); // uniform (0,1] -> log requires > 0 var u2 = rnd.UniformDouble(); // uniform [0,1) var randStdNormal = Fun.Sqrt(-2.0 * Fun.Log(u1)) * Fun.Sin(Constant.PiTimesTwo * u2); return(mean + stdDev * randStdNormal); }
/// <summary> /// Perform the supplied action for each of count vectors from the center /// of the ellipse to the circumference. /// </summary> public void ForEachVector(int count, Action <int, __vt__> index_vector_act) { double d = Constant.PiTimesTwo / count; double a = Fun.Sin(d * 0.5).Square() * 2.0, b = Fun.Sin(d); // init trig. recurrence double ct = 1.0, st = 0.0; index_vector_act(0, Axis0); for (int i = 1; i < count; i++) { double dct = a * ct + b * st, dst = a * st - b * ct;; // trig. recurrence ct -= dct; st -= dst; // cos (t + d), sin (t + d) index_vector_act(i, Axis0 * ct + Axis1 * st); } }
/// <summary> /// Create from Rodrigues axis-angle vactor /// </summary> public static __rot3t__ FromAngleAxis(__v3t__ angleAxis) { __ft__ theta2 = angleAxis.LengthSquared; if (theta2 > Constant <__ft__> .PositiveTinyValue) { var theta = Fun.Sqrt(theta2); var thetaHalf = theta / 2; var k = Fun.Sin(thetaHalf) / theta; return(new __rot3t__(Fun.Cos(thetaHalf), k * angleAxis)); } else { return(new __rot3t__(1, 0, 0, 0)); } }
/// <summary> /// Return an IEnumerable of points on the circle's circumference, optionally repeating the first point as the last. /// </summary> /// <param name="tesselation">number of distinct points to generate. the actual number of points returned depends on the <para>duplicateClosePoint</para> parameter. must be 3 or larger.</param> /// <param name="duplicateClosePoint">if true, the first point is repeated as the last</param> /// <returns>IEnumerable of points on the circle's circumference. if diplicateClosePoint is true, <para>tesselation</para>+1 points are returned.</returns> public IEnumerable <V3d> Points(int tesselation, bool duplicateClosePoint = false) { if (tesselation < 3) { throw new ArgumentOutOfRangeException("tesselation", "tesselation must be at least 3."); } var off = 0; if (duplicateClosePoint) { off = 1; } for (int i = 0; i < tesselation + off; i++) { var angle = ((double)i) / tesselation * Constant.PiTimesTwo; yield return(Center + AxisU * Fun.Cos(angle) + AxisV * Fun.Sin(angle)); } }
public __vt__ GetPoint(double alpha) { return(Center + Axis0 * Fun.Cos(alpha) + Axis1 * Fun.Sin(alpha)); }
public __vt__ GetVector(double alpha) { return(Axis0 * Fun.Cos(alpha) + Axis1 * Fun.Sin(alpha)); }
private static void FastHartleyTransformRaw( this double[] v, long start, long size) { if (size < 2) { return; } /* --------------------------------------------------------------- * The transforming part of the function. It assumes that all * indices are already bit-reversed. For successive evaluation * of the trigonometric functions the following recurrence is * used: * * a = 2 sin(square(d/2)) * b = sin d * * cos(t + d) = cos t - [ a * cos t + b sin t ] * sin(t + d) = sin t - [ a * sin t - b cos t ] * * The algorithm is based on the following recursion: * * H[f] = Heven[f] + cos(2 PI f / n) Hodd[f] + sin(2 PI f / n) Hodd[n-f] f in [0, n-1] + + Heven[n/2 + g] = Heven[g] + Hodd [n/2 + g] = Hodd [g] g in [0, n/2-1] + --------------------------------------------------------------- */ long end = start + size; for (long i = start; i < end; i += 2) { double h0 = v[i], h1 = v[i + 1]; v[i] = h0 + h1; v[i + 1] = h0 - h1; // f = 0, PI } if (size < 4) { return; } for (long i = start; i < end; i += 4) { double h0 = v[i], h2 = v[i + 2]; v[i] = h0 + h2; v[i + 2] = h0 - h2; // f = 0, PI double h1 = v[i + 1], h3 = v[i + 3]; v[i + 1] = h1 + h3; v[i + 3] = h1 - h3; // f = PI/2, 3 * PI/2 } if (size < 8) { return; } for (long i = start; i < end; i += 8) { double h0 = v[i], h4 = v[i + 4]; v[i] = h0 + h4; v[i + 4] = h0 - h4; // f = 0, PI double one = Constant.Sqrt2Half * (v[i + 5] + v[i + 7]); double two = Constant.Sqrt2Half * (v[i + 7] - v[i + 5]); double h1 = v[i + 1], h3 = v[i + 3]; v[i + 1] = h1 + one; v[i + 5] = h1 - one; v[i + 3] = h3 - two; v[i + 7] = h3 + two; double h2 = v[i + 2], h6 = v[i + 6]; v[i + 2] = h2 + h6; v[i + 6] = h2 - h6; // f = PI/2, 3 * PI/2 } if (size < 16) { return; } var sTable = new double[size / 4]; var cTable = new double[size / 4]; for (long len = 8, lenDiv2 = 4, lenMul2 = 16; len < size; lenDiv2 = len, len = lenMul2, lenMul2 = 2 * len) { double d = Constant.PiTimesTwo / lenMul2; double a = Fun.Sin(d * 0.5).Square() * 2.0; // init trig. recurrence double b = Fun.Sin(d); double ct = 1.0, st = 0.0; for (long f = 1; f < lenDiv2; f++) // all freqs in the first quadrant { double dct = a * ct + b * st, dst = a * st - b * ct; // trig. rec ct -= dct; st -= dst; // cos (t + d), sin (t + d) cTable[f] = ct; sTable[f] = st; } for (long i0 = start; i0 < end; i0 += lenMul2) { long i4 = i0 + len; double h0 = v[i0], h4 = v[i4]; v[i0] = h0 + h4; v[i4] = h0 - h4; // f = 0, PI for (long f = 1; f < lenDiv2; f++) // all freqs in the first quadrant { long i1 = i0 + f, i3 = i0 + len - f; long i5 = i1 + len, i7 = i3 + len; double one = cTable[f] * v[i5] + sTable[f] * v[i7]; double two = cTable[f] * v[i7] - sTable[f] * v[i5]; double h1 = v[i1], h3 = v[i3]; v[i1] = h1 + one; v[i5] = h1 - one; // all four quadrants v[i3] = h3 - two; v[i7] = h3 + two; // } long i2 = i0 + lenDiv2, i6 = i4 + lenDiv2; double h2 = v[i2], h6 = v[i6]; v[i2] = h2 + h6; v[i6] = h2 - h6; // f = PI/2, 3 * PI/2 } } }