@@ -95,11 +95,12 @@ public readonly partial record struct PreciseNumber
9595 /// <returns>The sine of <paramref name="x"/>.</returns>
9696 /// <remarks>
9797 /// Produced to the significant digits of <paramref name="x"/>, and never fewer than
98- /// <see cref="MinimumDivisionPrecision"/>. Use <see cref="Sin(PreciseNumber, int)"/> to choose
99- /// that precision.
98+ /// <see cref="MinimumDivisionPrecision"/>, but no more than the reduction can deliver at the
99+ /// magnitude of <paramref name="x"/>; see <see cref="DefaultReducedPrecision(PreciseNumber)"/>.
100+ /// Use <see cref="Sin(PreciseNumber, int)"/> to choose that precision.
100101 /// </remarks>
101102 public static PreciseNumber Sin ( PreciseNumber x ) =>
102- Sin ( x , DefaultTrigonometricPrecision ( x ) ) ;
103+ Sin ( x , DefaultReducedPrecision ( x ) ) ;
103104
104105 /// <summary>
105106 /// Returns the sine of an angle in radians, to a chosen number of significant digits.
@@ -123,11 +124,12 @@ public static PreciseNumber Sin(PreciseNumber x, int significantDigits) =>
123124 /// <returns>The cosine of <paramref name="x"/>.</returns>
124125 /// <remarks>
125126 /// Produced to the significant digits of <paramref name="x"/>, and never fewer than
126- /// <see cref="MinimumDivisionPrecision"/>. Use <see cref="Cos(PreciseNumber, int)"/> to choose
127- /// that precision.
127+ /// <see cref="MinimumDivisionPrecision"/>, but no more than the reduction can deliver at the
128+ /// magnitude of <paramref name="x"/>; see <see cref="DefaultReducedPrecision(PreciseNumber)"/>.
129+ /// Use <see cref="Cos(PreciseNumber, int)"/> to choose that precision.
128130 /// </remarks>
129131 public static PreciseNumber Cos ( PreciseNumber x ) =>
130- Cos ( x , DefaultTrigonometricPrecision ( x ) ) ;
132+ Cos ( x , DefaultReducedPrecision ( x ) ) ;
131133
132134 /// <summary>
133135 /// Returns the cosine of an angle in radians, to a chosen number of significant digits.
@@ -152,10 +154,10 @@ public static PreciseNumber Cos(PreciseNumber x, int significantDigits) =>
152154 /// <remarks>
153155 /// Both come from one argument reduction and one kernel, which is the reason to prefer this over a
154156 /// separate <see cref="Sin(PreciseNumber)"/> and <see cref="Cos(PreciseNumber)"/> when both are
155- /// wanted.
157+ /// wanted. The precision follows <see cref="DefaultReducedPrecision(PreciseNumber)"/>.
156158 /// </remarks>
157159 public static ( PreciseNumber Sin , PreciseNumber Cos ) SinCos ( PreciseNumber x ) =>
158- SinCos ( x , DefaultTrigonometricPrecision ( x ) ) ;
160+ SinCos ( x , DefaultReducedPrecision ( x ) ) ;
159161
160162 /// <summary>
161163 /// Returns the sine and cosine of an angle in radians, to a chosen number of significant digits.
@@ -214,11 +216,12 @@ public static (PreciseNumber Sin, PreciseNumber Cos) SinCos(PreciseNumber x, int
214216 /// <returns>The tangent of <paramref name="x"/>.</returns>
215217 /// <remarks>
216218 /// Produced to the significant digits of <paramref name="x"/>, and never fewer than
217- /// <see cref="MinimumDivisionPrecision"/>. Use <see cref="Tan(PreciseNumber, int)"/> to choose
218- /// that precision.
219+ /// <see cref="MinimumDivisionPrecision"/>, but no more than the reduction can deliver at the
220+ /// magnitude of <paramref name="x"/>; see <see cref="DefaultReducedPrecision(PreciseNumber)"/>.
221+ /// Use <see cref="Tan(PreciseNumber, int)"/> to choose that precision.
219222 /// </remarks>
220223 public static PreciseNumber Tan ( PreciseNumber x ) =>
221- Tan ( x , DefaultTrigonometricPrecision ( x ) ) ;
224+ Tan ( x , DefaultReducedPrecision ( x ) ) ;
222225
223226 /// <summary>
224227 /// Returns the tangent of an angle in radians, to a chosen number of significant digits.
@@ -736,6 +739,26 @@ public static PreciseNumber RadiansToDegrees(PreciseNumber radians, int signific
736739 private static int DefaultTrigonometricPrecision ( PreciseNumber value ) =>
737740 Math . Max ( value . SignificantDigits , MinimumDivisionPrecision ) ;
738741
742+ /// <summary>
743+ /// Gets the significant digits the circular functions produce when the caller does not choose.
744+ /// </summary>
745+ /// <param name="value">The angle being reduced.</param>
746+ /// <returns>
747+ /// <see cref="DefaultTrigonometricPrecision(PreciseNumber)"/>, capped at what reducing
748+ /// <paramref name="value"/> against <see cref="ConstantPrecision"/> digits of π can deliver, and
749+ /// never less than one.
750+ /// </returns>
751+ /// <remarks>
752+ /// The built-in constants carry <see cref="ConstantPrecision"/> digits, so the uncapped default
753+ /// asks for exactly as many digits as π holds, and a constant with an integer digit then needs
754+ /// one more than that. <see cref="RequireReducibleArgument(int, int)"/> rightly refuses such a
755+ /// request when a caller makes it, but an overload that picks its own precision must not pick one
756+ /// it will refuse, or <c>Sin(Pi)</c> throws. Only an argument too large to reduce at any
757+ /// precision, where even one digit is out of reach, still throws.
758+ /// </remarks>
759+ private static int DefaultReducedPrecision ( PreciseNumber value ) =>
760+ Math . Max ( 1 , Math . Min ( DefaultTrigonometricPrecision ( value ) , ConstantPrecision - IntegerDigitCount ( value ) ) ) ;
761+
739762 /// <summary>
740763 /// Selects the sine and cosine of an angle from those of its reduced remainder and the quadrant
741764 /// the reduction removed.
0 commit comments