Skip to content

SE-0080 (3/5) - Failable initializers for Float->Int #3356

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

Merged
merged 11 commits into from
Aug 10, 2016

Conversation

ultramiraculous
Copy link
Contributor

What's in this pull request?

Breaking out from #2742. Adds init?(exactly:) initializers for integer types from float types.

Resolved bug number: (SR-1491)


Before merging this pull request to apple/swift repository:

  • Test pull request on Swift continuous integration.

Triggering Swift CI

The swift-ci is triggered by writing a comment on this PR addressed to the GitHub user @swift-ci. Different tests will run depending on the specific comment that you use. The currently available comments are:

Smoke Testing

Platform Comment
All supported platforms @swift-ci Please smoke test
All supported platforms @swift-ci Please smoke test and merge
OS X platform @swift-ci Please smoke test OS X platform
Linux platform @swift-ci Please smoke test Linux platform

Validation Testing

Platform Comment
All supported platforms @swift-ci Please test
All supported platforms @swift-ci Please test and merge
OS X platform @swift-ci Please test OS X platform
OS X platform @swift-ci Please benchmark
Linux platform @swift-ci Please test Linux platform

Lint Testing

Language Comment
Python @swift-ci Please Python lint

Note: Only members of the Apple organization can trigger swift-ci.

@ultramiraculous ultramiraculous force-pushed the failable-float-to-int branch from a8c261a to 25bcfad Compare July 6, 2016 07:48
@ultramiraculous ultramiraculous changed the title Failable float to int SE-0080 (2/5) - Failable initializers for Float->Int Jul 6, 2016
@ultramiraculous ultramiraculous changed the title SE-0080 (2/5) - Failable initializers for Float->Int SE-0080 (3/5) - Failable initializers for Float->Int Jul 6, 2016
if value.isFinite == false || value < ${str(lower)}.0 || value > ${str(upper)}.0 {
return nil
}
self._value = Builtin.fpto${sign}i_FPIEEE${srcBits}_${BuiltinName}(value._value)
Copy link
Contributor

Choose a reason for hiding this comment

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

I see a check that value is in-range, but I don't see any check that the value is preserved by the conversion. Am I simply missing something? What happens if value is, e.g. 0.5?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Gah, yeah that was an oversight. I meant to change the .isFinite check to check if value % 1.0 == 0 and I somehow didn't notice the test failures last night.

Copy link
Contributor

Choose a reason for hiding this comment

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

FWIW, floating-point remainder is a very expensive operation. It is much cheaper to test if ${Src}(Self(value)) == value. Or once/if SE-0113 lands, it would be better still to use value.rounded(.truncate) == value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, yeah I suppose that makes sense. I think in general I'm battling a perception that converting back/forth is more expensive than it really is.

@ultramiraculous ultramiraculous force-pushed the failable-float-to-int branch 3 times, most recently from 168e271 to 30d18e7 Compare July 6, 2016 20:06
@ultramiraculous
Copy link
Contributor Author

Also it looks like one of the trapping cases isn't being handled correctly in the tests w/ is causing a failure.

@ultramiraculous ultramiraculous force-pushed the failable-float-to-int branch from 30d18e7 to a449cc9 Compare July 7, 2016 05:50
@ultramiraculous
Copy link
Contributor Author

I think I covered everything. It turns gyb wasn't using the repr version of the floats I was trying to test, which was causing some unexpected behavior.

@stephentyrone
Copy link
Contributor

@swift-ci Please test.

// Construction of integers from floating point numbers.
% for srcBits in allFloatBits:
% Src = floatName[srcBits]
% (lower, upper) = getFtoIBounds(srcBits, int(bits), signed)
Copy link
Contributor

Choose a reason for hiding this comment

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

I recommend using argument labels in the getFtoIBounds call for readability.

@ultramiraculous ultramiraculous force-pushed the failable-float-to-int branch from a449cc9 to bb5d5d8 Compare July 8, 2016 08:24
@ultramiraculous
Copy link
Contributor Author

I think I got everything. Still running tests locally, but everything seems fine.

@gribozavr
Copy link
Contributor

Thank you! I will look closely tomorrow, but let's get a CI run early:

@swift-ci Please test

@gribozavr
Copy link
Contributor

@ultramiraculous The CI has errors, would you mind taking a look?

Also, I just wanted to remind you that we have a script, utils/run-test, that allows you to run just one test.

% else:

% if testValue > selfMax:
FloatingPointConversionTraps.test("${Other}To${Self}Conversion/dest=${testValue}").crashOutputMatches(getTooLargeMessage()).code {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you wrap this line before .crashOutputMatches?

@ultramiraculous
Copy link
Contributor Author

Hah, I actually didn't know about run-tests/didn't notice when it got added, so thanks! I've been hacking together that functionality on my own.

@ultramiraculous ultramiraculous force-pushed the failable-float-to-int branch from 190d046 to c07bceb Compare July 9, 2016 03:55
@ultramiraculous
Copy link
Contributor Author

Addressed the nits and moved some helpers into a python module.

@gribozavr
Copy link
Contributor

@swift-ci Please test

return (1 << bits) - 1

def int_min(bits, signed):
return -1 * int_max(bits, signed) - 1 if signed else 0
Copy link
Contributor

Choose a reason for hiding this comment

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

To add some clarity, could you add parens around the first part of the expression? Otherwise it is not quite clear whether it's:

(-1 * int_max(bits, signed) - 1) if signed else 0

or

-1 * int_max(bits, signed) - (1 if signed else 0)

@moiseev
Copy link
Contributor

moiseev commented Jul 29, 2016

FWIW: the build failure is unrelated (it's PlaygroundLogger).
Other than the code clarity nitpicks, LGTM.
/cc @gribozavr

@ultramiraculous ultramiraculous force-pushed the failable-float-to-int branch from 828713e to b11d14a Compare July 29, 2016 15:50
@ultramiraculous
Copy link
Contributor Author

Got the nits!

@ultramiraculous
Copy link
Contributor Author

ultramiraculous commented Aug 5, 2016

@gribozavr I just dusted off the remainder of this proposal and it's like 50 lines of code, some of which depend on this PR. Any chance you could look at this :P

@lattner
Copy link
Contributor

lattner commented Aug 6, 2016

Given that SE-0080 is purely additive, it is possible that we can take this. However, @tkremenek is the ultimate gatekeeper on that decision after technical review and approval has been done.

@tkremenek
Copy link
Member

I would be strongly supportive of taking an implementation of SE-0080 if we feel comfortable with the implementation and it landed very soon.

#if !os(Windows) && (arch(i386) || arch(x86_64))
% end

/// Creates a ${Self} whose value is `value` rounded towards zero.
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you restore the original doc comment?

  /// Creates a new instance by rounding the given floating-point value toward
  /// zero.
  ///
  /// - Parameter other: A floating-point value. When `other` is rounded toward
  ///   zero, the result must be within the range `${Self}.min...${Self}.max`.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Didn't notice it changed in the mean time. Added back.

@gribozavr
Copy link
Contributor

Sorry for a delayed review! The changes LGTM!

@swift-ci Please test

@gribozavr
Copy link
Contributor

SILOptimizer/copyforward.sil issue has been fixed. Retrying.

@swift-ci Please test OS X platform

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants