Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

New API for Expanded Math Library #710

Closed
wants to merge 1 commit into from
Closed

New API for Expanded Math Library #710

wants to merge 1 commit into from

Conversation

tannergooding
Copy link
Member

Fixes dotnet/corefx#1151 - New API for Expanded Math Library.

This is still a work-in-progress.

TODO:

  • Deprecate System.Math (Removed due to feedback from the community)
  • Provide the existing math APIs under the respective native types
  • Provide new math APIs for System.Double
  • Provide equivalent math APIs for System.Single
  • Provide FCALLS for all System.Single and System.Double math APIs
  • API Review
  • Changes based on API Review
  • Ensure that all FCALLS are implemented properly (as compared to
    System.Math and the CLI).
  • Provide intrinsic support for key functions (such as sincos)
  • Provide tests covering the new APIs
  • Provide documentation
  • Implement PAL changes for Linux/Mac
  • General Cleanup
  • Final Code Review

Current Work

I am currently working on fixing the Linux/MacOS build. This involves ensuring that the CLANG (or non MSVC) implementations of the cmath functions behave identically to the MSVC implementation.

Edits

  • Updated todo list to include the PAL changes required for Linux/Mac
  • Updated todo list to include the Intrinsic support for key methods
  • Updated todo list to include Provide Documentation
  • Updated todo list to exclude the deprecation of System.Math
  • Updated with a new commit fixing some spacing issues/typos and code feedback
  • Updated title to better reflect the current proposal

FCALL_CONTRACT;

// The cmath::atan2 method does not produce nan for atan2(+-inf,+-inf)
return (IS_INFINITY(y) && IS_INFINITY(x)) ? (y / x) : atan2(y, x);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code here, returning nan for atan2(+-inf,+-inf) goes against the recommended behavior in IEEE 754:2008 and what the MSVC compilers does.

A discussion should be brought up as to if this should maintain backwards compatibility or if this should follow the IEEE standard.

Recommended Behavior (IEEE 754:2008 - Page 45):

  • atan2(±∞, −∞) is ±3π/4
  • atan2(±∞, +∞) is ±π/4

This also applies to the COMSingle::Atan2 implementation

@tannergooding
Copy link
Member Author

@mikedn, Even if it is not accepted, it still gets the ball rolling to get these, or similar, changes into CoreCLR and CoreFX (which I find very exciting :D)

We have already partially discussed the changes here dotnet/corefx#1151, and the initial thoughts were positive and in favor of these (or similar) changes.

The major discussion point is still how to implement the API, but these changes are easily modified to fit whatever decision is made on that point.

@mikedn
Copy link

mikedn commented Apr 15, 2015

@tannergooding My acceptance comment was specifically targeted as obsoleting System.Math. It's difficult to convince the team to obsolete something and I don't think I've seen this detail mentioned in the issue.

@tannergooding
Copy link
Member Author

@mikedn, Ah, sorry. I missed the link in your original comment.

It was briefly discussed in the original proposal, but we could not come to a definitive answer.

However, It was brought down to essentially three options:

  • Break backwards compatibility (if only there was some way to notify users of the API change when recompiling the code, already compiled code shouldn't be an issue unless you are using Reflection - but using Reflection with the Math libraries seems a terrible idea).
  • Make it hard to refactor (meaning having the new APIs implemented/moved to in the respective primitive type - float Single.Sqrt(float) ).
  • Have a secondary static math class (with a less than optimal name) that will not break backwards compatibility ( System.Mathf , System.MathHelp , System.MathHelper , System.Numerics.Math , etc...).

I opted to go with the second as it seemed to be the best route overall (The first option seems the most unlikely, and the third seemed illogical because we could potentially come across the same issue in the future if a new type was added).

@KrzysztofCwalina
Copy link
Member

@tannergooding Thanks for doing this work. It's a lot of good stuff.
Some early comments/feedback:

  1. Could you add "Provide documentation" to your TODO list. It will come vary handy for the API reviewers?
  2. I really worry about deprecating System.Math. System.Math is such commonly used API and there is nothing fundamentally wrong with it. We usually deprecate only APIs that have code correctness issues, not APIs that are being superseded by newer alternatives.
  3. Although I think adding very common operations to the primitive types might be the right approach (need to think about it more), some of the operations you are proposing to add are a bit exotic. Maybe they belong somewhere else. And more generally, where does the pattern end, i.e. we surely cannot add all possible math operations directly to the primitive types. I think it would be useful to articulate the rules here, i.e. what APIs should be on primitive types, what APIs should not be, and what to do with these that won't be on the primitive types.

@tannergooding
Copy link
Member Author

@KrzysztofCwalina Thanks!

  1. I have updated the todo list to include "Provide Documentation"
  2. The community seems to agree Reddit Post - CoreCLR Proposal for Expanded Math Library :). It is definitely something that needs to be discussed (and is easily reverted in any case). The only real issue with System.Math is that it is not easily extensible and Math.Atan2() doesn't follow one of the IEEE 754:2008 recommendations. If only static extension methods were a thing sigh
  3. Great point, I would imagine the elementary functions - WIKI (exponentials, logarithms, square roots, and trigonometric operations) should be included. The remaining opertions, which are special functions - WIKI (erf, erfc, tgamma, lgamma, etc...) are useful, but do fall into a more niche category and could probably be provided elsewhere.

This is definitely still a WIP, but most of the hard work (getting the runtime backing for these) can be done (thankfully) before the API decisions of where to place the functions in the Framework are made.

@tannergooding
Copy link
Member Author

The PR was just updated with a small set of fixes to the original.

  • System.Math is no longer marked with System.Obsolete
  • Fixed the spacing issues/typos in the original commit
  • Modified some code based on the code comments

I am currently working on fixing the Linux/MacOS build.

@tannergooding tannergooding changed the title New API for single-precision math (P1) New API for single-precision math (P2) Apr 16, 2015
@MattWhilden
Copy link

@josteink as fyi. There may be some eventual collision with the freebsd bring up he's been working on.

@josteink
Copy link
Member

@MattWhilden As far as I can see, nothing of this collides with my PAL-modifications for FreBSD. Without looking further into it than that, I'm OK with it.

@KrzysztofCwalina
Copy link
Member

@tannergooding, one more piece of feedback. As you know, we have a portability story for CoreCLR and the .Net "desktop" CLR. If your changes get added to CoreCLR, but not to the desktop CLR, it will create a friction for portable libraries. Adding such significant feature to the desktop CLR will be very difficult (schedule, deployment, and compatibility wise). This is the reason we often prefer out-of-band features. I will think about this issue more and we can discuss during the API review, but I wanted to make sure you are aware of this issue/tradeoff.

@tannergooding
Copy link
Member Author

@josteink Do your PAL-modifications include changes to src\pal\inc\pal.h or src\pal\src\cruntime\finite.cpp or src\pal\src\include\palinternal.h?

I am currently working to ensure the behavior of the CMATH functions for Linux/MacOS (CLANG) correspond to the behavior for the Windows (MSVC) versions and it will require modifications to those three files.

@tannergooding
Copy link
Member Author

@KrzysztofCwalina Thanks for the heads up. Perhaps there is a way to make the FCALL changes to the desktop and portable CLR (which should be similar) and provide the API through a separate library (similar to the System.Numerics.Vectors features)?

@josteink
Copy link
Member

Not at all. My commit is one new line in pal's context.h. That's all.

Jostein Kjønigsen
http://jostein.kjonigsen.net
On 17 Apr 2015 17:48, Tanner Gooding [email protected] wrote:@josteink Do your PAL-modifications include changes to src\pal\inc\pal.h or src\pal\src\cruntime\finite.cpp or src\pal\src\include\palinternal.h?

I am currently working to ensure the behavior of the CMATH functions for Linux/MacOS (CLANG) correspond to the behavior for the Windows (MSVC) versions and it will require modifications to those three files.

—Reply to this email directly or view it on GitHub.

@tannergooding
Copy link
Member Author

Sorry for the noise... My branch didn't rebase properly and resetting it somehow closed the PR.

@tannergooding tannergooding changed the title New API for single-precision math (P2) New API for Expanded Math Library Apr 29, 2015
@tannergooding
Copy link
Member Author

Updated the PR with some intrinsic support. Initial tests show float.Sqrt() has a 25% performance increase on average (as compared to Math.Sqrt or double.Sqrt).

@ghost
Copy link

ghost commented May 3, 2015

Would it make sense to calculate square root and derivative using Newton-Raphson method?

Here is an example API for .deriv(..): http://octave.sourceforge.net/optim/function/deriv.html.

Also, see this JS implementation: http://jsperf.com/math-sqrt-vs-newton-raphson-method (IE11 perform worse in Math.sqrt and best in calculating with Newton-Raphson algo)

@tannergooding
Copy link
Member Author

@jasonwilliams200OK, I wouldn't imagine that any implementation would be as accurate as, or faster than, the hardware provided intrinsic instruction 'sqrtsd' and 'sqrtss' (which is what calls to Math.Sqrt boil down to).

Also, in my own benchmarks and the tables for the JS implementation you gave above, Math.Sqrt outperforms the Newton-Raphson method in all browsers.

@hadibrais
Copy link

@tannergooding I don't think adding these functions to the primitive types results in the best design for several reasons. First, this reduces the maintainability of the code because the types of arguments depend on which function to use. Second, mscorlib.dll is supposed to only contain the functionality that would be required by many applications. Other not-so-essential functionalities should be in other assemblies, loaded only when needed. Of course, mscorlib is already a mess, but we shouldn't make things worse. Most of these math functions will have very limited usage scenarios. If we include them now in mscorlib, the size of the assembly will increase a tiny bit. Then later, we might add more functions and its size will further increase another bit. Eventually, the new functions will have to be added to another assembly. Third, this can easily confuse those developers that have already implemented many of these functions as extension methods to the primitive types.

Another issue is the intention of supporting all math functions that are supported in C++. In that case, we might have to make sure that not only the APIs are identical but also the input/output relation is identical. Otherwise, this can introduce very nasty bugs for those who are converting their codebases between the languages. But then we have this problem of different C++ std implementations with many subtle differences. Finally, what would be the long term plan? When more math functions are added to C++, are we going to stay inline? The C++ APIs may not even be designed in the best way anyway.

@tannergooding
Copy link
Member Author

@hadibrais. I appreciate the feedback and have been working on simplifying the scope of the first change, which should be about adding single-precision floating-point functions to match the existing double-precision functions. The first change should also bring the existing double-precision functions inline with current compiler output (there were several FCALLs which could be greatly simplified as various compiler bugs were fixed).

As for where they are implemented, I'm afraid that the functions will end up split unless the CoreCLR team decides to take a breaking change. As such, I believe it more intuitive to have them re implemented in the primitive types, where (moving forward) the functions can continue growing and changing without worrying about breaking backwards compatibility. The original functions would continue existing in System.Math and you can still have function overloads moving forward if you have using static System.Double; using static System.Single;

@tannergooding
Copy link
Member Author

All the original changes are in tannergooding/coreclr#math-changes-original. I am currently working on breaking this up into several commits and reducing the scope to better match the feedback given.

@tannergooding
Copy link
Member Author

Am currently working on getting the PAL layer done, including the full set of C Math functions. Even if some of the functions aren't provided via managed code, it is still useful to have them functioning and tested for future scenarios.

The Trigonometric and Hyperbolic functions should be done at this point, with a broader and more accurate test coverage. The only interesting scenario I came across was that tan(pi / 2) does not result in INFINITY (on all supported platforms).

@tannergooding
Copy link
Member Author

Closing. This has been entirely replaced by #5492, which implements the approved API.

@tannergooding tannergooding deleted the math-changes branch February 5, 2017 20:15
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

New API for single-precision math
9 participants