Tiny pitch: FloatingPointSign.negate()

The code I was writing when I realized that negate() is missing, is exactly like the example I gave. That’s the example I have on hand, because that’s the situation I actually encountered.

The call to negate looks like this:

if !n.isEven { sign.negate() }

And the surrounding code doesn’t really matter. It’s doing other things that don’t involve a sign (except later to initialize a value using that sign).

• • •

In any event, I’m not claiming my one particular function as motivation for this. The motivation is much more general:

FloatingPointSign exists, its purpose is to represent the sign of a number, and negating a sign is a basic and useful operation.

1 Like

You just implement that extension (as it is written in the very first post) into your own codebase and it is job done for you, no? Or do you think this functionality would actually be used frequently? From where I am this is very niche and if it requires additional 12 lines of code - so be it.

2 Likes

Why are you so averse to actually pasting that code into this thread?

Because it is

a) Not ready for publication

and

b) Completely irrelevant

The question is not, “Does Nevin have a use-case where this method is the optimal solution?”

But rather, “Should the type which represents the sign of a number, have a method to negate itself?”

• • •

To me, the answer to that question is a blindingly obvious “Yes, of course, why on earth wouldn’t you be able to negate a sign?”

But if other people don’t see it that way, then I’ll drop the pitch.

I was expecting this thread to go more like, me: “Hey, I just noticed there’s no negate method here.” Everyone else: “Oh yeah, good catch, that should definitely be there.”

This isn’t something I want to put a lot of effort into or argue about, I was just trying to help fill in a small hole I found. If other people don’t want the hole filled, then there’s nothing to do.

3 Likes

Negating a Bool also makes obvious sense, but during the API review for mutating func toggle(), the .toggled() counterpart was expressly rejected because the core team could not conceive of a non-contrived example where it was more useful than the ! operator.

Steve’s criticism is worth considering, since he happens to know a lot about numerical algorithms.

Yeah, I'd summarize the feedback (or at least mine) to be that the two questions are isomorphic: Although it is not unreasonable to envision such an API, it should be added if you (or someone else) has a use case where it is the optimal solution.

This is because there are already a variety of scenarios where use of this type is an attractive nuisance, such that I worry further APIs for manipulating its values may actively lead users to adopt less optimal solutions than they would find otherwise. :man_shrugging:

2 Likes

Both you and Steve have used that phrase, and I really don’t think it applies here.

There’s nothing “attractive” about it.

Nobody is going to suddenly start using FloatingPointSign when they wouldn’t otherwise, just because it has a negate method.

The only time anyone will ever see that method, is when they’re already working with a FloatingPointSign and they need to negate it. And at that point, from a standpoint of code readability, the sign is exactly the thing they should be negating.

When you call one of the initializers we’ve been discussing, even if negating the significand achieves the same result, it nonetheless makes the code easier to understand if all three parts—sign, exponent, and significand—are each individually made correct before putting them together, rather than having both sign and significand the opposite of what they should be.

2 Likes

I don't know about Steve, but I'm referring to FloatingPointSign as an attractive nuisance in its entirety. The proof that it's attractive is that you and I both have been inclined to use it (since it is after all the type that represents the sign of a floating-point number), but as I've said there's never been a case where I've been inclined to manipulate the value where I haven't then found a better way that doesn't require manipulating it—hence, the nuisance part.

That the type cannot be eliminated altogether is tolerable because it can still serviceably fulfill the job of passing along the sign of one value verbatim to an initializer for another. However, unless there is some use case of which I'm not aware which proves extraordinarily compelling, I'm arguing that it's actively desirable to guide users not to manipulate values of this type.

(See also the concept of floating-point interchange formats, which are meant to be used to store and exchange data but are not required to support arithmetic operations. For example, an IEEE-compliant language can offer an interchange-only Float192 that doesn't support addition or any other math. My point here is that FloatingPointSign is currently of-a-kind with such interchange types, almost like an interchange-only Float1, and my argument is that it is best kept that way unless a compelling use case to the contrary arises.)

2 Likes

If it's speed you're worried about, wouldn't a word-sized Int be way more performant though?

FloatingPointSign fits in an Int, so the compiler can always generate integer manipulation code instead of byte manipulation code if it thinks that will be faster.