-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Intrinsic arithmetic function overloads #8710
Conversation
Two things: Before we merge this, it'd be nice to validate that the fast path code now aligns properly with what would happen without the fast path. To do that, can you try ripping it all out and making sure all the tests pass as expected? (We'd want the fast path back before merging, of course.) Second, although long division truncating values is what we've advertised in our documentation, it isn't what we're currently doing, and someone may have taken a dependency on 10/3 being 3.33... Can you add a ChangeWave for division? I haven't looked too closely at your code yet, but the tests you posted in your comment look great to me. Thanks for working on this! |
When testing with the fast path disabled, the Example:
produces a result of 9.22337203685478E+18 instead of the expected -9223372036854775808. I'll make a change to I'll make the ChangeWave cover integer versus real for addition, subtraction, multiplication, and division. (I also need to add tests for multiplication overflow.) |
This was a bit surprising to me, but I can see why it would do that. Rather than any overly complicated logic, can we just reorder the Add methods, for instance, such that it tries to coerce the arguments to integers, then longs, then doubles? I'm trying to minimize the impact of the change while still getting the desired outcome. |
Yes, the methods in the |
The changes are using change wave 17.8 as a placeholder pending discussion. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This mostly looks good to me. Thanks for the improvements iterations on this!
I'd only like to see the handling of attempts of large doubles to long conversions and explicit unit test(s) for integer literals outside long bounds. Then I'm ready to sign off
…g double to long; add tests for values that exceed long min/max
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the contribution and iterations on it!
I think it's good to go now (we'll just need to properly docuemnt the behavior after merging)
@JanKrivanek Was there feedback on the decimal separator? |
Not yet. I suppose we'll discuss this on Monday |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good overall. I've Added a few comments inline.
…e; add unit tests; change functions based on unit test findings
New commits to address #8798 within the scope of this work - i.e. code touched or changed by this PR now uses a different overload of double.TryParse(str, NumberStyles.Number | NumberStyles.Float, CultureInfo.InvariantCulture.NumberFormat, out arg) This may not close #8798. The issue could be in other places. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies for the delay, the changes look great. I've added one question inline. Also, when you get a chance, can you please update the description - I believe that some parts got out of sync with the change.
The description has been updated. |
Fixes #8698
Context
The MSBuild property functions for Add(), Subtract(), Multiply(), Divide(), and Modulo() have overloads for
long
anddouble
. The 'fast path' resolution for the functions supports thedouble
versions only. Both overloads should be supported.Design
The changes are focused on the 'fast path' for intrinsic functions. To determine which overload to call, the arguments are checked to see if they can be converted to a
long
or, for astring
, parsed to along
. If the arguments can belong
, thelong
overload is called. Otherwise, thedouble
overload is called.From MSBuild XML, invocation of the
double
overload can be ensured by using a real literal, e.g.$([MSBuild]::Add(1, 0.0))
invokes thedouble
overload.With the
long
overload an overflow result that wraps is kept, e.g.-9223372036854775808
is the result of the following function call.Preserve Existing Behavior for
Equals
andCompareTo
The following two code examples currently work because
Add()
always returns adouble
but there is an issue when thelong
override is invoked.The
Microsoft.Build.Evaluation.Expander<P, I>.Function<T>.Execute()
method has an existing special case for handlingEquals
andCompareTo
where the type of the argument toEquals
orCompareTo
is converted to match the type of the 'lhs' of the comparison.3.0
can't be converted to along
. To preserve the existing behavior, the argument is tested and if it is a real literal the lhs of the comparison is converted to adouble
.In the MSBuild XML the
double
todouble
comparison can be explicit by using a real literal or by converting to double as in the following examples.Changes Made
Implementation
Modified the
Microsoft.Build.Evaluation.Expander<P, I>.Function<T>
class:TryConvertToLong()
.TryConvertToInt()
andTryConvertToDouble()
.IsFloatingPointRepresentation()
.TryExecute*()
methods, e.g.TryExecuteAdd()
.TryExecuteWellKnownFunction()
to call the appropriateTryExecute*()
method.Execute()
to support existing behavior for comparisons withEquals
andCompareTo
.LateBindExecute()
to support selecting the correct overload to call.IntrinsicFunctionOverload
to provide cached comparer for sorting candidate overloads.Unit Tests
Modified the
Microsoft.Build.UnitTests.Evaluation.Expander_Tests
class:PropertyFunctionStaticMethodIntrinsicMaths()
that was commented "test for overflow wrapping" but was testing for adouble
result. Overflow wrapping is covered inPropertyFunctionMSBuildAdd()
.Medley()
to add some tests. The change toMedley()
are related to the comparison behavior withEquals
andCompareTo
.PropertyFunctionMSBuildAdd()
to testdouble
andlong
including integer overflow wrapping.PropertyFunctionMSBuildSubtract()
,PropertyFunctionMSBuildMultiply()
,PropertyFunctionMSBuildDivide()
to testlong
anddouble
.PropertyFunctionMSBuildModulo()
.Added the
ExpanderFunction_Tests
unit test class.Added the
IntrinsicFunctionOverload_Tests
unit test class.PR #8853
The changes in PR 8853 to use the InvariantCulture with double.TryParse have been included in this PR as well. If this PR is accepted and merged first, then issue #8798 and PR #8853 can also be closed based on this PR. But PR #8853 is smaller and can be accepted ahead of this PR.
Testing
Tested on Windows 11 and macOS 12.
Added new unit tests, extended existing tests, and ran all unit tests. The existing unit tests revealed the
Equals
/CompareTo
comparison behavior.Ran a test MSBuild XML project file. See below.
Notes
Negates PR #8649.
Test Project File