Skip to content
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

[Feature Request]: copysign(x, y) - transfer the algebraic sign of y to |x| #26605

Open
damianmoz opened this issue Jan 27, 2025 · 1 comment

Comments

@damianmoz
Copy link

Has anybody had a need for such a routine? I thought of putting this question on discourse but did not want to clutter things up. Not sure the reach I will achieve by posting an issue by let's try it anyway.

Technically, a compiler is not IEEE 754 compliant unless it supports this operation. It is a basic, i.e. fundamental, IEEE 754 arithmetic operation, not a library routine even though it might look like it is normally implemented as such (and indeed it might even be on something like X86-64. Some newer ISAs jabe a single instruction to do it. As an operation ranks up there with the arithmetic operations +, -, / and * and is part of the family of operations which messes or otherwise with the sign bit when making a duplicate or clone of the (primary) operand:

copy y to x, i.e. x := y
negate x, i.e. -x
absolute value of x, i.e. abs(x)

I implement it as a routine and quite happy with the approach. I am curious if I should share what I have if there is a demand, or advocate for the LLVM built-in to be accessible which I guess means putting a new primitive into the compiler: See

https://llvm.org/docs/LangRef.html

I would assume that the preferred path is to use the LLVM built-in.

I can live with what I have forever so I am not asking that anything change but I thought I would just throw this into the mix of low priority tasks. This is not a heavy use routine or a performance killer.

For something like an x86-64, you can come up with a pretty good library routine of varying degrees of complexity and performance and readability using the transmute() feature. For
something like a RISC-V and (maybe) POWER architecture, you might want to use the built-in to get access to the single machine instruction which does the same job. Not sure about ARM.

@damianmoz
Copy link
Author

damianmoz commented Jan 30, 2025

In the absence of a primitive for this operation, here is a slightly sub-optimal implementation, one which highlights the use of the transmute() method:

inline proc copysign(x : real(?w), y : real(w))
{
    const _x = x.transmute(uint(w));
    const _y = y.transmute(uint(w));

    //  compute the exclusive OR but only look
    //  i.e. the result of the most significant bit, the
    //  negative bit, or what some call the sign bit

    return if ((_x ^ _y) >> (w - 1)) == 0 then x else -x;
}

There are other ways to do this task.

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

No branches or pull requests

2 participants