{"id":40402,"date":"2022-06-09T09:00:20","date_gmt":"2022-06-09T16:00:20","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=40402"},"modified":"2022-06-15T11:40:11","modified_gmt":"2022-06-15T18:40:11","slug":"dotnet-7-generic-math","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/dotnet-7-generic-math\/","title":{"rendered":".NET 7 Preview 5 &#8211; Generic Math"},"content":{"rendered":"<p>In .NET 6 we previewed a feature known as Generic Math. Since then, we have made continuous improvements to the implementation and responded to various feedback from the community in order to ensure that relevant scenarios are possible and the necessary APIs are available.<\/p>\n<p>If you missed out on the <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/preview-features-in-net-6-generic-math\/\">original blog post<\/a>, Generic Math combines the power of generics and a new feature known as <code>static virtuals in interfaces<\/code> to allow .NET developers to take advantage of static APIs, including operators, from generic code. This means that you get all the power of generics, but now with the ability to constrain the input to number like types, so you no longer need to write or maintain many near identical implementations just to support multiple types. It also means that you get access to all your favorite operators and can use them from generic contexts. That is, you can now have <code>static T Add&lt;T&gt;(T left, T right) where T : INumber&lt;T&gt; =&gt; left + right;<\/code> where-as previously it would have been impossible to define.<\/p>\n<p>Much like generics, this feature will see the most benefits by API authors where they can simplify the amount of code required they need to maintain. The .NET Libraries did <a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/68183\">just this<\/a> to simplify the <code>Enumerable.Min<\/code> and <code>Enumerable.Max<\/code> APIs exposed as part of LINQ. Other developers will benefit indirectly as the APIs they consume may start supporting more types without the requirement for each and every numeric type to get explicit support. Once an API supports <code>INumber&lt;T&gt;<\/code> then it should work with any type that implements the required interface. All devs will likewise benefit from having a more consistent API surface and having more functionality available by default. For example, all types that implement <code>IBinaryInteger&lt;T&gt;<\/code> will support operations like <code>+<\/code> (Addition), <code>-<\/code> (Subtraction), <code>&lt;&lt;<\/code> (Left Shift), and <code>LeadingZeroCount<\/code>.<\/p>\n<h2>Generic Math<\/h2>\n<p>Lets take a look at an example piece of code that computes a standard deviation. For those unfamiliar, this is a math function used in statistics that builds on two simpler methods: <code>Sum<\/code> and <code>Average<\/code>. It is basically used to determine how spread apart a set of values are.<\/p>\n<p>The first method we&#8217;ll look at is <code>Sum<\/code>, which just adds a set of values together. The method takes in an <code>IEnumerable&lt;T&gt;<\/code> where <code>T<\/code> must be a type that implements the <code>INumber&lt;T&gt;<\/code> interface. It returns a <code>TResult<\/code> with a similar constraint (it must be a type that implements <code>INumber&lt;TResult&gt;<\/code>). Because two generic parameters are here, it is allowed to return a different type than it takes as an input. This means, for example, you can do <code>Sum&lt;int, long&gt;<\/code> which would allow summing the values of an <code>int[]<\/code> and returning a 64-bit result to help avoid overflow. <code>TResult.Zero<\/code> efficiently gives the value of <code>0<\/code> as a <code>TResult<\/code> and <code>TResult.CreateChecked<\/code> converts <code>value<\/code> from a <code>T<\/code> into a <code>TResult<\/code> throwing an <code>OverflowException<\/code> if it is too large or too small to fit in the destination format. This means, for example, that <code>Sum&lt;int, byte&gt;<\/code> would throw if one of the input values was negative or greater than <code>255<\/code>.<\/p>\n<pre><code class=\"language-csharp\">public static TResult Sum&lt;T, TResult&gt;(IEnumerable&lt;T&gt; values)\r\n    where T : INumber&lt;T&gt;\r\n    where TResult : INumber&lt;TResult&gt;\r\n{\r\n    TResult result = TResult.Zero;\r\n\r\n    foreach (var value in values)\r\n    {\r\n        result += TResult.CreateChecked(value);\r\n    }\r\n\r\n    return result;\r\n}<\/code><\/pre>\n<p>The next method is <code>Average<\/code>, which just adds a set of values together (calls <code>Sum<\/code>) and then divides that by the number of values. It doesn&#8217;t introduce any additional concepts beyond what were used in <code>Sum<\/code>. It does show use of the division operator.<\/p>\n<pre><code class=\"language-csharp\">public static TResult Average&lt;T, TResult&gt;(IEnumerable&lt;T&gt; values)\r\n    where T : INumber&lt;T&gt;\r\n    where TResult : INumber&lt;TResult&gt;\r\n{\r\n    TResult sum = Sum&lt;T, TResult&gt;(values);\r\n    return TResult.CreateChecked(sum) \/ TResult.CreateChecked(values.Count());\r\n}<\/code><\/pre>\n<p><code>StandardDeviation<\/code> is the last method, as indicated above it basically determines how far apart a set of values are. For example, <code>{ 0, 50, 100 }<\/code> has a high deviation of <code>49.501<\/code>; <code>{ 0, 5, 10 }<\/code> on the other hand has a much lower deviation of just <code>4.5092<\/code>. This method introduces a different constraint of <code>IFloatingPointIeee754<\/code> which indicates the return type must be an <code>IEEE 754<\/code> floating-point type such as <code>double<\/code> (<code>System.Double<\/code>) or <code>float<\/code> (<code>System.Single<\/code>). It introduces a new API <code>CreateSaturating<\/code> which explicitly saturates, or clamps, the value on overflow. That is, for <code>byte.CreateSaturating&lt;int&gt;(value)<\/code> it would convert <code>-1<\/code> to <code>0<\/code> because <code>-1<\/code> is less than the minimum value of <code>0<\/code>. It would likewise convert <code>256<\/code> to <code>255<\/code> because <code>256<\/code> is greater than the maximum value of <code>255<\/code>. Saturation is the default behavior for <code>IEEE 754<\/code> floating-point types as they can represent positive and negative infinity as their respective minimum and maximum values. The only other new API is <code>Sqrt<\/code> which behaves just like <code>Math.Sqrt<\/code> or <code>MathF.Sqrt<\/code> and calculates the <code>square root<\/code> of the floating-point value.<\/p>\n<pre><code class=\"language-csharp\">public static TResult StandardDeviation&lt;T, TResult&gt;(IEnumerable&lt;T&gt; values)\r\n    where T : INumber&lt;T&gt;\r\n    where TResult : IFloatingPointIeee754&lt;TResult&gt;\r\n{\r\n    TResult standardDeviation = TResult.Zero;\r\n\r\n    if (values.Any())\r\n    {\r\n        TResult average = Average&lt;T, TResult&gt;(values);\r\n        TResult sum = Sum&lt;TResult, TResult&gt;(values.Select((value) =&gt; {\r\n            var deviation = TResult.CreateSaturating(value) - average;\r\n            return deviation * deviation;\r\n        }));\r\n        standardDeviation = TResult.Sqrt(sum \/ TResult.CreateSaturating(values.Count() - 1));\r\n    }\r\n\r\n    return standardDeviation;\r\n}<\/code><\/pre>\n<p>These methods can then be used with any type that implements the required interfaces and in .NET 7 preview 5 we have 20 types that implement these interfaces out of the box. The following table gives a brief description of those types, the corresponding language keyword for C# and F# when that exists, and the primary generic math interfaces they implement. More details on these interfaces and why they exist are provided later on in the <a href=\"#available-apis\">Available APIs<\/a> section.<\/p>\n<table>\n<thead>\n<tr>\n<th>.NET Type Name<\/th>\n<th>C# Keyword<\/th>\n<th>F# Keyword<\/th>\n<th>Implemented Generic Math Interfaces<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>System.Byte<\/td>\n<td>byte<\/td>\n<td>byte<\/td>\n<td>IBinaryInteger, IMinMaxValue, IUnsignedNumber<\/td>\n<\/tr>\n<tr>\n<td>System.Char<\/td>\n<td>char<\/td>\n<td>char<\/td>\n<td>IBinaryInteger, IMinMaxValue, IUnsignedNumber<\/td>\n<\/tr>\n<tr>\n<td>System.Decimal<\/td>\n<td>decimal<\/td>\n<td>decimal<\/td>\n<td>IFloatingPoint, IMinMaxValue<\/td>\n<\/tr>\n<tr>\n<td>System.Double<\/td>\n<td>double<\/td>\n<td>float, double<\/td>\n<td>IBinaryFloatingPointIeee754, IMinMaxValue<\/td>\n<\/tr>\n<tr>\n<td>System.Half<\/td>\n<td><\/td>\n<td><\/td>\n<td>IBinaryFloatingPointIeee754, IMinMaxValue<\/td>\n<\/tr>\n<tr>\n<td>System.Int16<\/td>\n<td>short<\/td>\n<td>int16<\/td>\n<td>IBinaryInteger, IMinMaxValue, ISignedNumber<\/td>\n<\/tr>\n<tr>\n<td>System.Int32<\/td>\n<td>int<\/td>\n<td>int<\/td>\n<td>IBinaryInteger, IMinMaxValue, ISignedNumber<\/td>\n<\/tr>\n<tr>\n<td>System.Int64<\/td>\n<td>long<\/td>\n<td>int64<\/td>\n<td>IBinaryInteger, IMinMaxValue, ISignedNumber<\/td>\n<\/tr>\n<tr>\n<td>System.Int128<\/td>\n<td><\/td>\n<td><\/td>\n<td>IBinaryInteger, IMinMaxValue, ISignedNumber<\/td>\n<\/tr>\n<tr>\n<td>System.IntPtr<\/td>\n<td>nint<\/td>\n<td>nativeint<\/td>\n<td>IBinaryInteger, IMinMaxValue, ISignedNumber<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.BigInteger<\/td>\n<td><\/td>\n<td><\/td>\n<td>IBinaryInteger, IUnsignedNumber<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.Complex<\/td>\n<td><\/td>\n<td><\/td>\n<td>INumberBase, ISignedNumber<\/td>\n<\/tr>\n<tr>\n<td>System.Runtime.InteropServices.NFloat<\/td>\n<td><\/td>\n<td><\/td>\n<td>IBinaryFloatingPointIeee754, IMinMaxValue<\/td>\n<\/tr>\n<tr>\n<td>System.SByte<\/td>\n<td>sbyte<\/td>\n<td>sbyte<\/td>\n<td>IBinaryInteger, IMinMaxValue, ISignedNumber<\/td>\n<\/tr>\n<tr>\n<td>System.Single<\/td>\n<td>float<\/td>\n<td>float32, single<\/td>\n<td>IBinaryFloatingPointIeee754, IMinMaxValue<\/td>\n<\/tr>\n<tr>\n<td>System.UInt16<\/td>\n<td>ushort<\/td>\n<td>uint16<\/td>\n<td>IBinaryInteger, IMinMaxValue, IUnsignedNumber<\/td>\n<\/tr>\n<tr>\n<td>System.UInt32<\/td>\n<td>uint<\/td>\n<td>uint<\/td>\n<td>IBinaryInteger, IMinMaxValue, IUnsignedNumber<\/td>\n<\/tr>\n<tr>\n<td>System.UInt64<\/td>\n<td>ulong<\/td>\n<td>uint64<\/td>\n<td>IBinaryInteger, IMinMaxValue, IUnsignedNumber<\/td>\n<\/tr>\n<tr>\n<td>System.UInt128<\/td>\n<td><\/td>\n<td><\/td>\n<td>IBinaryInteger, IMinMaxValue, IUnsignedNumber<\/td>\n<\/tr>\n<tr>\n<td>System.UIntPtr<\/td>\n<td>nuint<\/td>\n<td>unativeint<\/td>\n<td>IBinaryInteger, IMinMaxValue, IUnsignedNumber<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>This means that out of the box users get a broad set of support for Generic Math. As the community adopts these interfaces for their own types, the support will continue to grow.<\/p>\n<h3>Types Without Language Support<\/h3>\n<p>Readers might note that there are a few types here that don&#8217;t have an entry in the <code>C# Keyword<\/code> or <code>F# Keyword<\/code> column. While these types exist and are supported fully in the BCL, languages like C# and F# do not provide any additional support for them today and so users may surprised when certain language features do not work with them. Some examples are that the language won&#8217;t provide support for literals (<code>Int128 value = 0xF_FFFF_FFFF_FFFF_FFFF<\/code> isn&#8217;t valid), constants (<code>const Int128 Value = 0;<\/code> isn&#8217;t valid), constant folding (<code>Int128 value = 5;<\/code> is evaluated at runtime, not at compile time), or various other functionality that is limited to types that have corresponding language keywords.<\/p>\n<p>The types without language support are:<\/p>\n<ul>\n<li><code>System.Half<\/code> is a 16-bit binary floating-point type that implements the IEEE 754 standard much like <code>System.Double<\/code> and <code>System.Single<\/code>. It was originally introduced in .NET 5<\/li>\n<li><code>System.Numerics.BigInteger<\/code> is an arbitrary precision integer type and automatically grows to fit the value represented. It was originally introduced in .NET Framework 4.0<\/li>\n<li><code>System.Numerics.Complex<\/code> can represent the expression <code>a + bi<\/code> where <code>a<\/code> and <code>b<\/code> are <code>System.Double<\/code> and <code>i<\/code> is the imaginary unit. It was originally introduced in .NET Framework 4.0<\/li>\n<li><code>System.Runtime.InteropServices.NFloat<\/code> is a variable precision binary floating-point type that implements the IEEE 754 standard and much like <code>System.IntPtr<\/code> it is 32-bits on a 32-bit platform (equivalent to <code>System.Single<\/code>) and 64-bits on a 64-bit platform (equivalent to <code>System.Double<\/code>) It was originally introduced in .NET 6 and is primarily meant for interop purposes.<\/li>\n<li><code>System.Int128<\/code> is a 128-bit signed integer type. It is new in .NET 7<\/li>\n<li><code>System.UInt128<\/code> is a 128-bit unsigned integer type. It is new in .NET 7<\/li>\n<\/ul>\n<h3>Breaking Changes Since .NET 6<\/h3>\n<p>The feature that went out in .NET 6 was a preview and as such there have been several changes to the API surface based on community feedback. This includes, but is not limited to:<\/p>\n<ul>\n<li>Renaming <code>System.IParseable<\/code> to <code>System.IParsable<\/code><\/li>\n<li>Moving all other new numeric interfaces to the <code>System.Numerics<\/code> namespace<\/li>\n<li>Introducing <code>INumberBase<\/code> so that types like <code>System.Numerics.Complex<\/code> can be represented<\/li>\n<li>Splitting the IEEE 754 specific APIs into their own <code>IFloatingPointIeee754<\/code> interface so types like <code>System.Decimal<\/code> can be represented<\/li>\n<li>Moving various APIs lower in the type hierarchy such as the <code>IsNaN<\/code> or <code>MaxNumber<\/code> APIs\n<ul>\n<li>Many of the concepts will return a constant value or be a <code>no-op<\/code> on various type<\/li>\n<li>Despite this, it is still important that they&#8217;re available, since the exact type of a generic is unknown and many of these concepts are important for more general algorithms<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>.NET API reviews are done in the open and are livestreamed for all to view and participate in. Past API review videos can be found on our <a href=\"https:\/\/www.youtube.com\/playlist?list=PL1rZQsJPBU2S49OQPjupSJF-qeIEz9_ju\">YouTube channel<\/a>.<\/p>\n<p>The design doc for the Generic Math feature is available in the <a href=\"https:\/\/github.com\/dotnet\/designs\/tree\/main\/accepted\/2021\/statics-in-interfaces\">dotnet\/designs<\/a> repo on GitHub.<\/p>\n<p>The corresponding PRs updating the document, general discussions around the feature, and links back to the relevant API reviews are also <a href=\"https:\/\/github.com\/dotnet\/designs\/pulls?q=is%3Apr+author%3Atannergooding+is%3Aclosed\">available<\/a>.<\/p>\n<h3>Support in other languages<\/h3>\n<p>F# is getting support for static virtuals in interfaces as well and more details should be expected soon in the <a href=\"https:\/\/github.com\/fsharp\/fslang-design\">fsharp\/fslang-design<\/a> repo on GitHub.<\/p>\n<p>A fairly 1-to-1 translation of the C# <code>Sum<\/code> method using the proposed F# syntax is expected to be:<\/p>\n<pre><code class=\"language-fsharp\">let Sum&lt;'T, 'TResult when 'T :&gt; INumber&lt;'T&gt; and 'TResult :&gt; INumber&lt;'TResult&gt;&gt;(values : IEnumerable&lt;'T&gt;) =\r\n    let mutable result = 'TResult.Zero\r\n    for value in values do\r\n        result &lt;- result 'TResult.CreateChecked(value)\r\n    result<\/code><\/pre>\n<h2>Available APIs<\/h2>\n<p>Numbers and math are both fairly complex topics and the depth in which one can go is almost without limit. In programming there is often only a loose mapping to the math one may have learned in school and special rules or considerations may exist since execution happens in a system with limited resources. Languages therefore expose many operations that make sense only in the context of certain kinds of numbers or which exist primarily as a performance optimization due to how hardware actually works. The types they expose often have well-defined limits, an explicit layout of the data they are represented by, differing behaviors around rounding or conversions, and more.<\/p>\n<p>Because of this there remains a need to both support numbers in the abstract sense while also still supporting programming specific constructs such as floating-point vs integer, overflow, unrepresentable results; and so it was important as part of designing this feature that the interfaces exposed be both fine-grained enough that users could define their own interfaces built on top while also being granular enough that they were easy to consume. To that extent, there are a few core numeric interfaces that most users will interact with such as <code>System.Numerics.INumber<\/code> and <code>System.Numerics.IBinaryInteger<\/code>; there are then many more interfaces that support these types and support developers defining their own numeric interfaces for their domain such as <code>IAdditionOperators<\/code> and <code>ITrigonometricFunctions<\/code>.<\/p>\n<p>Which interfaces get used will be dependent on the needs of the declaring API and what functionality it relies on. There are a range of powerful APIs exposed to help users efficiently understand the value they&#8217;ve been and decide the appropriate way to work with it including handling edge cases (such as negatives, NaNs, infinities, or imaginary values), having correct conversions (including throwing, saturating, or truncating on overflow), and being extensible enough to version the interfaces moving forward by utilizing <a href=\"https:\/\/docs.microsoft.com\/dotnet\/csharp\/whats-new\/tutorials\/default-interface-methods-versions\">Default Interface Methods<\/a>.<\/p>\n<h3>Numeric Interfaces<\/h3>\n<p>The types most users will interact with are the <code>numeric interfaces<\/code>. These define the core interfaces describing number-like types and the functionality available to them.<\/p>\n<table>\n<thead>\n<tr>\n<th>Interface Name<\/th>\n<th>Summary<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>System.Numerics.IAdditiveIdentity<\/td>\n<td>Exposes the concept of <code>(x + T.AdditiveIdentity) == x<\/code><\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IMinMaxValue<\/td>\n<td>Exposes the concept of <code>T.MinValue<\/code> and <code>T.MaxValue<\/code> (types like BigInteger have no Min\/MaxValue)<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IMultiplicativeIdentity<\/td>\n<td>Exposes the concept of <code>(x * T.MultiplicativeIdentity) == x<\/code><\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IBinaryFloatingPointIeee754<\/td>\n<td>Exposes APIs common to binary floating-point types that implement the IEEE 754 standard<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IBinaryInteger<\/td>\n<td>Exposes APIs common to binary integers<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IBinaryNumber<\/td>\n<td>Exposes APIs common to binary numbers<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IFloatingPoint<\/td>\n<td>Exposes APIs common to floating-point types<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IFloatingPointIeee754<\/td>\n<td>Exposes APIs common to floating-point types that implement the IEEE 754 standard<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.INumber<\/td>\n<td>Exposes APIs common to comparable number types (effectively the &#8220;Real&#8221; number domain)<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.INumberBase<\/td>\n<td>Exposes APIs common to all number types (effectively the &#8220;Complex&#8221; number domain)<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.ISignedNumber<\/td>\n<td>Exposes APIs common to all signed number types (such as the concept of <code>NegativeOne<\/code>)<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IUnsignedNumber<\/td>\n<td>Exposes APIs common to all unsigned number types<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>While there are a few different types here, most users will likely work directly with <code>INumber&lt;TSelf&gt;<\/code>. This roughly corresponds to what some users may recognize as a &#8220;real&#8221; number and means the value has a sign and well-defined order, making it <code>IComparable<\/code>. <code>INumberBase&lt;TSelf&gt;<\/code> convers more advanced concepts including &#8220;complex&#8221; and &#8220;imaginary&#8221; numbers.<\/p>\n<p>Most of the other interfaces, such as <code>IBinaryNumber<\/code>, <code>IFloatingPoint<\/code>, and <code>IBinaryInteger<\/code>, exist because not all operations make sense for all numbers. That is, there are places where APIs only makes sense for values that are known to be binary-based and other places where APIs only make sense for floating-point types. The <code>IAdditiveIdentity<\/code>, <code>IMinMaxValue<\/code>, and <code>IMultiplicativeIdentity<\/code> interfaces exist to cover core properties of number like types. For <code>IMinMaxValue<\/code> in particular, it exists to allow access to the upper (<code>MaxValue<\/code>) and lower (<code>MinValue<\/code>) bounds of a type. Certain types like <code>System.Numerics.BigInteger<\/code> may not have such bounds and therefore do not implement this interface.<\/p>\n<p><code>IFloatingPoint&lt;TSelf&gt;<\/code> exists to cover both <code>IEEE 754<\/code> types such as <code>System.Double<\/code>, <code>System.Half<\/code>, and <code>System.Single<\/code> as well as other types such as <code>System.Decimal<\/code>. The number of APIs provided by it is much lesser and it is expected most users who explicitly need a floating-point-like type will use <code>IFloatingPointIeee754<\/code>. There is not currently any interface to describe &#8220;fixed-point&#8221; types but such a definition could exist in the future if there is enough demand.<\/p>\n<p>These interfaces expose APIs previously only available in <code>System.Math<\/code>, <code>System.MathF<\/code>, and <code>System.Numerics.BitOperations<\/code>. This means that functions like <code>T.Sqrt(value)<\/code> are now available to anything implementing <code>IFloatingPointIeee754&lt;T&gt;<\/code> (or more specifically the <code>IRootFunctions&lt;T&gt;<\/code> interface covered below).<\/p>\n<p>Some of the core APIs exposed by each interface includes, but is not limited to the below.<\/p>\n<table style=\"width: 51.1014%; height: 1512px;\">\n<thead>\n<tr style=\"height: 28px;\">\n<th style=\"height: 28px; width: 15.2591%;\">Interface Name<\/th>\n<th style=\"height: 28px; width: 15.9309%;\">API Name<\/th>\n<th style=\"height: 28px; width: 68.714%;\">Summary<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\">IBinaryInteger<\/td>\n<td style=\"height: 28px; width: 15.9309%;\">DivRem<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Computes the quotient and remainder simultaneously<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">LeadingZeroCount<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Counts the number of leading zero bits in the binary representation<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">PopCount<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Counts the number of set bits in the binary representation<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">RotateLeft<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Rotates bits left, sometimes also called a circular left shift<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">RotateRight<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Rotates bits right, sometimes also called a circular right shift<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">TrailingZeroCount<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Counts the number of trailing zero bits in the binary representation<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\"><\/td>\n<td style=\"height: 28px; width: 68.714%;\"><\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\">IFloatingPoint<\/td>\n<td style=\"height: 28px; width: 15.9309%;\">Ceiling<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Rounds the value towards positive infinity. +4.5 becomes +5, -4.5 becomes -4<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">Floor<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Rounds the value towards negative infinity. +4.5 becomes +4, -4.5 becomes -5<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">Round<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Rounds the value using the specified rounding mode.<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">Truncate<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Rounds the value towards zero. +4.5 becomes +4, -4.5 becomes -4<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\"><\/td>\n<td style=\"height: 28px; width: 68.714%;\"><\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\">IFloatingPointIeee754<\/td>\n<td style=\"height: 28px; width: 15.9309%;\">E<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Gets a value representing Euler&#8217;s number for the type<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">Epsilon<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Gets the smallest representable value that is greater than zero for the type<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">NaN<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Gets a value representing NaN for the type<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">NegativeInfinity<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Gets a value representing -Infinity for the type<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">NegativeZero<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Gets a value representing -Zero for the type<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">Pi<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Gets a value representing +Pi for the type<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">PositiveInfinity<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Gets a value representing +Infinity for the type<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">Tau<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Gets a value representing +Tau, or <code>2 * Pi<\/code> for the type<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">&#8211;Other&#8211;<\/td>\n<td style=\"height: 28px; width: 68.714%;\">&#8211;Implements the full set of interfaces defined under <a href=\"#functions\">Functions<\/a>\u00a0below&#8211;<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\"><\/td>\n<td style=\"height: 28px; width: 68.714%;\"><\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\">INumber<\/td>\n<td style=\"height: 28px; width: 15.9309%;\">Clamp<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Restricts a value to no more and no less than the specified min and max value<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">CopySign<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Sets the sign of a give value to the same as another specified value<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">Max<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns the greater of two values, returning NaN if either input is NaN<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">MaxNumber<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns the greater of two values, returning the number if one input is NaN<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">Min<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns the lesser of two values, returning NaN if either input is NaN<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">MinNumber<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns the lesser of two values, returning the number if one input is NaN<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">Sign<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns -1 for negative values, 0 for zero, and +1 for positive values<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\"><\/td>\n<td style=\"height: 28px; width: 68.714%;\"><\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\">INumberBase<\/td>\n<td style=\"height: 28px; width: 15.9309%;\">One<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Gets the value <code>1<\/code> for the type<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">Radix<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Gets the radix, or base, for the type. Int32 returns 2. Decimal returns 10<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">Zero<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Gets the value <code>0<\/code> for the type<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">CreateChecked<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Creates a value from another value, throwing if the other value can&#8217;t be represented<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">CreateSaturating<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Creates a value from another value, saturating if the other value can&#8217;t be represented<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">CreateTruncating<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Creates a value from another value, truncating if the other value can&#8217;t be represented<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">IsComplexNumber<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns true if the value has a non-zero real part and a non-zero imaginary part<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">IsEvenInteger<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns true if the value is an even integer. 2.0 returns true, 2.2 returns false<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">IsFinite<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns true if the value is not infinite and not NaN.<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">IsImaginaryNumber<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns true if the value has a zero real part. This means 0 is imaginary and <code>1 + 1i<\/code> is not<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">IsInfinity<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns true if the value represents infinity.<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">IsInteger<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns true if the value is an integer. 2.0 and 3.0 return true, 2.2 and 3.1 return false<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">IsNaN<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns true if the value represents NaN<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">IsNegative<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns true if the value is negative, this includes -0.0<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">IsPositive<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns true if the value is positive, this includes 0 and +0.0<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">IsRealNumber<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns true if the value has a zero imaginary part. This means 0 is real as are all <code>INumber&lt;T&gt;<\/code> types<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">IsZero<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns true if the value represents zero, this includes 0, +0.0, and -0.0<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">MaxMagnitude<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns the value with a greater absolute value, returning NaN if either input is NaN<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">MaxMagnitudeNumber<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns the value with a greater absolute value, returning the number if one input is NaN<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">MinMagnitude<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns the value with a lesser absolute value, returning NaN if either input is NaN<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\">MinMagnitudeNumber<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Returns the value with a lesser absolute value, returning the number if one input is NaN<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\"><\/td>\n<td style=\"height: 28px; width: 15.9309%;\"><\/td>\n<td style=\"height: 28px; width: 68.714%;\"><\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 15.2591%;\">ISignedNumber<\/td>\n<td style=\"height: 28px; width: 15.9309%;\">NegativeOne<\/td>\n<td style=\"height: 28px; width: 68.714%;\">Gets the value <code>-1<\/code> for the type<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Functions<\/h3>\n<p>The function interfaces define common mathematical APIs that may be more broadly applicable than to a specific numeric interface. They are currently all implemented by <code>IFloatingPointIeee754<\/code> and may also get implemented by other relevant types in the future.<\/p>\n<table>\n<thead>\n<tr>\n<th>Interface Name<\/th>\n<th>Summary<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>System.Numerics.IExponentialFunctions<\/td>\n<td>Exposes exponential functions supporting <code>e^x<\/code>, <code>e^x - 1<\/code>, <code>2^x<\/code>, <code>2^x - 1<\/code>, <code>10^x<\/code>, and <code>10^x - 1<\/code><\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IHyperbolicFunctions<\/td>\n<td>Exposes hyperbolic functions supporting <code>acosh(x)<\/code>, <code>asinh(x)<\/code>, <code>atanh(x)<\/code>, <code>cosh(x)<\/code>, <code>sinh(x)<\/code>, and <code>tanh(x)<\/code><\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.ILogarithmicFunctions<\/td>\n<td>Exposes logarithmic functions supporting <code>ln(x)<\/code>, <code>ln(x + 1)<\/code>, <code>log2(x)<\/code>, <code>log2(x + 1)<\/code>, <code>log10(x)<\/code>, and <code>log10(x + 1)<\/code><\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IPowerFunctions<\/td>\n<td>Exposes power functions supporting <code>x^y<\/code><\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IRootFunctions<\/td>\n<td>Exposes root functions supporting <code>cbrt(x)<\/code> and <code>sqrt(x)<\/code><\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.ITrigonometricFunctions<\/td>\n<td>Exposes trigonometric functions supporting <code>acos(x)<\/code>, <code>asin(x)<\/code>, <code>atan(x)<\/code>, <code>cos(x)<\/code>, <code>sin(x)<\/code>, and <code>tan(x)<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Parsing and Formatting<\/h3>\n<p>Parsing and formatting are core concepts in programming. They are typically used to support converting user input to a given type or to display a given type to the user.<\/p>\n<table>\n<thead>\n<tr>\n<th>Interface Name<\/th>\n<th>Summary<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>System.IFormattable<\/td>\n<td>Exposes support for <code>value.ToString(string, IFormatProvider)<\/code><\/td>\n<\/tr>\n<tr>\n<td>System.ISpanFormattable<\/td>\n<td>Exposes support for <code>value.TryFormat(Span&lt;char&gt;, out int, ReadOnlySpan&lt;char&gt;, IFormatProvider)<\/code><\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td>System.IParsable<\/td>\n<td>Exposes support for <code>T.Parse(string, IFormatProvider)<\/code><\/td>\n<\/tr>\n<tr>\n<td>System.ISpanParsable<\/td>\n<td>Exposes support for <code>T.Parse(ReadOnlySpan&lt;char&gt;, IFormatProvider)<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Operators<\/h3>\n<p>Central to Generic Math is the ability to expose operators as part of an interface. .NET 7 provides the following interfaces which expose the core operators supported by most languages. This also includes new functionality in the form of <code>user-defined checked operators<\/code> and <code>unsigned right shift<\/code>.<\/p>\n<table>\n<thead>\n<tr>\n<th>Interface Name<\/th>\n<th>Summary<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>System.Numerics.IAdditionOperators<\/td>\n<td>Exposes the <code>x + y<\/code> and <code>checked(x + y)<\/code> operators<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IBitwiseOperators<\/td>\n<td>Exposes the <code>x &amp; y<\/code>, <code>x | y<\/code>, <code>x ^ y<\/code>, and <code>~x<\/code> operators<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IComparisonOperators<\/td>\n<td>Exposes the <code>x &lt; y<\/code>, <code>X &gt; y<\/code>, <code>x &lt;= y<\/code>, and <code>x &gt;= y<\/code> operators<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IDecrementOperators<\/td>\n<td>Exposes the <code>--x<\/code>, <code>checked(--x)<\/code>, <code>x--<\/code>, and <code>checked(x--)<\/code> operators<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IDivisionOperators<\/td>\n<td>Exposes the <code>x \/ y<\/code> and <code>checked(x \/ y)<\/code> operators<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IEqualityOperators<\/td>\n<td>Exposes the <code>x == y<\/code> and <code>x != y<\/code> operators<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IIncrementOperators<\/td>\n<td>Exposes the <code>++x<\/code>, <code>checked(++x)<\/code>, <code>x++<\/code>, and <code>checked(x++)<\/code> operators<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IModulusOperators<\/td>\n<td>Exposes the <code>x % y<\/code> operator<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IMultiplyOperators<\/td>\n<td>Exposes the <code>x * y<\/code> and <code>checked(x * y)<\/code> operators<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IShiftOperators<\/td>\n<td>Exposes the <code>x &lt;&lt; y<\/code>, <code>x &gt;&gt; y<\/code>, and <code>x &gt;&gt;&gt; y<\/code> operators<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.ISubtractionOperators<\/td>\n<td>Exposes the <code>x - y<\/code> and <code>checked(x - y)<\/code> operators<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IUnaryNegationOperators<\/td>\n<td>Exposes the <code>-x<\/code> and <code>checked(-x)<\/code> operators<\/td>\n<\/tr>\n<tr>\n<td>System.Numerics.IUnaryPlusOperators<\/td>\n<td>Exposes the <code>+x<\/code> operator<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>User-Defined Checked Operators<\/h4>\n<p><code>User-defined checked operators<\/code> allow a different implementation to be provided which will throw <code>System.OverflowException<\/code> rather than silently truncating their result. These alternative implementations are available to C# code by using the <code>checked<\/code> keyword or setting <code>&lt;CheckForOverflowUnderflow&gt;true&lt;\/CheckForOverflowUnderflow&gt;<\/code> in your project settings. The versions that truncate are available by using the <code>unchecked<\/code> keyword or ensuring <code>CheckForOverflowUnderflow<\/code> is <code>false<\/code> (this is the default experience for new projects).<\/p>\n<p>Some types, such as floating-point types, may not have differing behavior as they <code>saturate<\/code> to <code>PositiveInfinity<\/code> and <code>NegativeInfinity<\/code> rather than truncating. <code>BigInteger<\/code> is another type that does not have differing behavior between the unchecked and checked versions of the operators as the type simply grows to fit the value. 3rd party types may also have their own unique behavior.<\/p>\n<p>Developers can declare their own <code>user-defined checked operators<\/code> by placing the <code>checked<\/code> keyword after the <code>operator<\/code> keyword. For example, <code>public static Int128 operator checked +(Int128 left, Int128 right)<\/code> declares a <code>checked addition<\/code> operator and <code>public static explicit operator checked int(Int128 value)<\/code> declares a <code>checked explicit conversion<\/code> operator.<\/p>\n<h4>Unsigned Right Shift<\/h4>\n<p><em>Unsigned right shift<\/em> (<code>&gt;&gt;&gt;<\/code>) allows shifting to occur that doesn&#8217;t carry the sign. That is, for <code>-8 &gt;&gt; 2<\/code> the result is <code>-2<\/code> while <code>-8 &gt;&gt;&gt; 2<\/code> is <code>+1073741822<\/code>.<\/p>\n<p>This is somewhat easier to visualize when looking at the hexadecimal or binary representation. For <code>x &gt;&gt; y<\/code> the sign of the value is preserved and so for positive values <code>0<\/code> is shifted in while for negative values <code>1<\/code> is shifted in instead. However, for <code>x &gt;&gt;&gt; y<\/code> the sign of the value is ignored and <code>0<\/code> is always shifted in. This is similar to first casting the value to an <code>unsigned<\/code> type of the same sign and then doing the shift, that is it is similar to <code>(int)((uint)x &gt;&gt; y)<\/code> for <code>int<\/code>.<\/p>\n<table>\n<thead>\n<tr>\n<th>Expression<\/th>\n<th>Decimal<\/th>\n<th>Hexadecimal<\/th>\n<th>Binary<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>-8<\/code><\/td>\n<td>-8<\/td>\n<td>0xFFFF_FFF8<\/td>\n<td>0b1111_1111_1111_1111_1111_1111_1111_1000<\/td>\n<\/tr>\n<tr>\n<td><code>-8 &gt;&gt; 2<\/code><\/td>\n<td>-2<\/td>\n<td>0xFFFF_FFFE<\/td>\n<td>0b1111_1111_1111_1111_1111_1111_1111_1110<\/td>\n<\/tr>\n<tr>\n<td><code>-8 &gt;&gt;&gt; 2<\/code><\/td>\n<td>+1,073,741,822<\/td>\n<td>0x3FFF_FFFE<\/td>\n<td>0b0011_1111_1111_1111_1111_1111_1111_1110<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Closing<\/h2>\n<p>The amount of functionality now available in a generic context is quite large, allowing your code to be simpler, more maintainable, and more expressive. Generic Math will empower every developer to achieve more, and we are excited to see how you decide to utilize it!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>.NET 7 Preview 5 includes significant improvements to the Generic Math feature.<\/p>\n","protected":false},"author":1650,"featured_media":40403,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,756],"tags":[],"class_list":["post-40402","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-csharp"],"acf":[],"blog_post_summary":"<p>.NET 7 Preview 5 includes significant improvements to the Generic Math feature.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/40402","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/1650"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=40402"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/40402\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/40403"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=40402"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=40402"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=40402"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}