Runtime: Feature Request: Math.Pow for int and uint

Created on 5 Apr 2018  路  7Comments  路  Source: dotnet/runtime

It would often be pretty neat to have an overload of Math.Pow for (int x, uint exponent) and (int x, int exponent) that returns x^exponent.

Rationale & Usage

The idea is, that there are often situations, in which the pow process by loop is faster than the current way of converting base and exponent to double, calculate the pow and then convert the result back to int, as you would have to do with the current Math.Pow.

For Example Math.Pow(3,2) would evaluate to 9, a case in which this method is much faster.

Implementation

A simplified implementation (no exceptions or doc comments) could be as follows:

public static int Pow(int x, uint exponent)
      {
          int ret = 1;
          while ( exponent != 0 )
          {
              if ( (exponent & 1) == 1 )
                  ret *= x;
              x *= x;
              exponent >>= 1;
          }
          return ret;
      }

Credit to Vilx- for the original code

This implementation scales with O(exponent)=log(exponent)

Details

The overload with an int exponent would have to check for the exponent to be positive, otherwise and ArgumentOutOfRangeException should be thrown.

In case of an overflow I would suggest to throw an OverflowException as done e.g. in Math.Abs

Note: I have deliberately called the base x, because base (how I would call it from a math POV) is already taken as a language keyword.

PR

There is no PR yet but if this feature is wanted I could create one.

area-System.Numerics

All 7 comments

@TheMinefighter, could you please update the original issue to roughly follow the "good example" listed under step 1 of our API Review Process. Not all sections are needed, but ideally you would provide the rationale and proposed API surface sections as it helps with the review process.

It would also be appreciated if you coould detail the behavior of this API with regards to overflow.

@tannergooding updated request; I hope I made it more understandable

Because existing integer values, including consts/literals, will currently call double Pow(double,double) adding this method would be a source breaking change.

@bartonjs Ok, checked it; you are correct. But I don't see why this would prevent the implementation of this feature, when there's no critic in it's necessity or usefulness. Let's call Math.IntPow then, I guess. A name shouldn't prevent a feature.

It requires a bit more thought, which is on my plate to do.

One of the primary issues is that adding new overloads here is breaking. Another issue is the name spread that would occur if we keep adding overloads. For example, it starts with Pow for integral types, but extends (theoretically) to the same for the various other methods. Likewise, it extends to more than just int and also exists for half and other types that may come in the future. Take for example if we add PowInt for int, well now if we want to add short overloads in the future, we can't use PowInt as the name because that is also breaking. We could use generics, but then it isn't strictly clear what types are supported. Likewise we could use PowInt32 but then we may eventually have 10-11 Pow* variants and that could extend to other math functions as well.

A possible solution is to begin exposing these methods on the actual types (Double, Single, Int32, etc). This would be new for the primitive types in .NET, but is how many other languages/frameworks handle this issue and would completely avoid the issue moving forward. It is also how many non-primitive types are designed. That is, if you have something like Vector4 or Color you don't define ColorMath or Vector4Math, you typically expose the new functionality as static or instance methods on the type.

However, this also requires more thought/consideration and an actual proposal before it can move forward.

If these new methods are exposed as instance methods that would introduce a weird asymmetry. There is no specific reason the first argument to pow would be designated as the instance and the second argument would be a parameter.

It's a bit like the ruby syntax 10.times. They are exposing a times method on numbers. While this reads naturally, it is an unsystematic way to structure programs and should be burned with fire.

The times function in Ruby returns all the numbers from 0 to one less than the number itself.

In my mind, 3.Pow(5) is undesirable.

I never said they would be instance methods 馃槃

They would likely just be static methods on the respective type, e.g. float.MaxNumber(x, y) or int.Pow(x, y), rather than on Math. This is how we expect most external types (such as Complex, BigInteger, Vector<T>, Color, etc) structure their math like helper methods, so it isn't really new.

That being said, it is new for the primitive types and requires more thought, investigation, etc.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nalywa picture nalywa  路  3Comments

bencz picture bencz  路  3Comments

GitAntoinee picture GitAntoinee  路  3Comments

iCodeWebApps picture iCodeWebApps  路  3Comments

EgorBo picture EgorBo  路  3Comments