Skip to content

Implement sign, sigbit, and copysign ufuncs and extend unary op tests #118

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

juntyr
Copy link
Contributor

@juntyr juntyr commented Jul 20, 2025

Progress on #111

  • implements the sign, signbit, and copysign ufuncs
  • extends unary unfunc tests
  • adds extra const annotations to the ops implementations

@juntyr juntyr changed the title Implement sign ufunc extend unary op tests Implement sign and copysign ufuncs and extend unary op tests Jul 20, 2025
@juntyr
Copy link
Contributor Author

juntyr commented Jul 20, 2025

Ideally, I'd also like to add signbit, but I'm unsure about how to implement it for sleef

@SwayamInSync
Copy link
Collaborator

Thanks @juntyr before proceeding to review, I did some umath refactor in my PR #116 (which isn't present in the main branch right now) so we can first progress towards merging #116 and then you can just rebase your changes

I dont think any CI change would break just some files re-arrangement

@SwayamInSync
Copy link
Collaborator

Ideally, I'd also like to add signbit, but I'm unsure about how to implement it for sleef

So there is a way to extract sign bit from sleef_quad value, I used that in dragon4.c here is the link to those lines
https://github.com/numpy/numpy-user-dtypes/blob/591481101ccf09b35b3d9ce9b282b13a10d7c5c7/quaddtype/numpy_quaddtype/src/dragon4.c#L1867C5-L1874C18
So you can simplify it as follows and it should work

static inline int32_t
quad_signbit(Sleef_quad *op)
{
    union
    {
        Sleef_quad q;
        struct
        {
            uint64_t lo;
            uint64_t hi;
        } i;
    } u;
    u.q = *op;

    // Sign bit is the MSB of the high 64 bits
    return (u.i.hi >> 63) != 0;
}

@juntyr
Copy link
Contributor Author

juntyr commented Jul 20, 2025

Is the ordering of hi and lo guaranteed independent of endianness?

@SwayamInSync
Copy link
Collaborator

Is the ordering of hi and lo guaranteed independent of endianness?

Good question, so typically Little-Endian (x86, x86_64, ARM64 in little-endian mode) are widely used and supported and compatible (I think GitHub CI uses these only). For Big-Endian (PowerPC, SPARC, some ARM) the current will fail

One way is to use compile-time directives to pick endianness but they are not standardised across compilers and build systems although C++20 has std::endian which is portable and our code also uses C++20 (windows has issues in lower versions that's why)

static inline int32_t
quad_signbit(Sleef_quad *op)
{
    union {
        Sleef_quad q;
        unsigned char bytes[16];
    } u;
    u.q = *op;
    
    if constexpr (std::endian::native == std::endian::big) {
        return (u.bytes[0] & 0x80) != 0;    // Sign bit in first byte
    } else if constexpr (std::endian::native == std::endian::little) {
        return (u.bytes[15] & 0x80) != 0;   // Sign bit in last byte
    } 
}

More simpler and direct

If you want then one other simpler and portable method could be using sleef's copysign function (docs https://sleef.org/quad.xhtml )

static inline int32_t
quad_signbit(Sleef_quad *op)
{
    Sleef_quad one = Sleef_strtoq("1.0", NULL);
    Sleef_quad result = Sleef_copysignq1(one, *op);
    Sleef_quad zero = Sleef_strtoq("0.0", NULL);
    return Sleef_icmpltq1(result, zero);
}

@SwayamInSync
Copy link
Collaborator

With that I'll also suggest when writing pytest tests, use string based inputs (casting from double sometimes give precision issues)

@ngoldbaum
Copy link
Member

We test little endian architectures in the numpy CI using PPC64le QEMU emulation. It's slow but it at least lets you do a real end-to-end test.

@juntyr
Copy link
Contributor Author

juntyr commented Jul 21, 2025

I'll start with the copysign-based implementation that @SwayamInSync suggested - once we have endianness testing in CI I'd be happy to replace it with the binary one

@juntyr juntyr changed the title Implement sign and copysign ufuncs and extend unary op tests Implement sign, sigbit, and copysign ufuncs and extend unary op tests Jul 21, 2025
@juntyr
Copy link
Contributor Author

juntyr commented Jul 21, 2025

6ffcdca adds dispatch support for (quad) -> bool ufunc "properties" like signbit, which should open the way to support isnan and friends in a follow-up PR

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

Successfully merging this pull request may close these issues.

3 participants