/* Source: https://github.com/glitchub/arith64 */
#define arith64_u64 unsigned long long int
#define arith64_s64 signed long long int
#define arith64_u32 unsigned int
#define arith64_s32 int

typedef union
{
    arith64_u64 u64;
    arith64_s64 s64;
    struct
    {
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
        arith64_u32 hi;
        arith64_u32 lo;
#else
        arith64_u32 lo;
        arith64_u32 hi;
#endif
    } u32;
    struct
    {
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
        arith64_s32 hi;
        arith64_s32 lo;
#else
        arith64_s32 lo;
        arith64_s32 hi;
#endif
    } s32;
} arith64_word;

#define arith64_hi(n) (arith64_word){.u64 = n}.u32.hi
#define arith64_lo(n) (arith64_word){.u64 = n}.u32.lo
#define arith64_neg(a, b) (((a) ^ ((((arith64_s64)(b)) >= 0) - 1)) + (((arith64_s64)(b)) < 0))
#define arith64_abs(a) arith64_neg(a, a)

arith64_s64 __absvdi2(arith64_s64 a)
{
    return arith64_abs(a);
}

arith64_s64 __ashldi3(arith64_s64 a, int b)
{
    arith64_word w = {.s64 = a};

    b &= 63;

    if (b >= 32)
    {
        w.u32.hi = w.u32.lo << (b - 32);
        w.u32.lo = 0;
    }
    else if (b)
    {
        w.u32.hi = (w.u32.lo >> (32 - b)) | (w.u32.hi << b);
        w.u32.lo <<= b;
    }
    return w.s64;
}

arith64_s64 __ashrdi3(arith64_s64 a, int b)
{
    arith64_word w = {.s64 = a};

    b &= 63;

    if (b >= 32)
    {
        w.s32.lo = w.s32.hi >> (b - 32);
        w.s32.hi >>= 31; // 0xFFFFFFFF or 0
    }
    else if (b)
    {
        w.u32.lo = (w.u32.hi << (32 - b)) | (w.u32.lo >> b);
        w.s32.hi >>= b;
    }
    return w.s64;
}

int __clzsi2(arith64_u32 a)
{
    int b, n = 0;
    b = !(a & 0xffff0000) << 4;
    n += b;
    a <<= b;
    b = !(a & 0xff000000) << 3;
    n += b;
    a <<= b;
    b = !(a & 0xf0000000) << 2;
    n += b;
    a <<= b;
    b = !(a & 0xc0000000) << 1;
    n += b;
    a <<= b;
    return n + !(a & 0x80000000);
}

int __clzdi2(arith64_u64 a)
{
    int b, n = 0;
    b = !(a & 0xffffffff00000000ULL) << 5;
    n += b;
    a <<= b;
    b = !(a & 0xffff000000000000ULL) << 4;
    n += b;
    a <<= b;
    b = !(a & 0xff00000000000000ULL) << 3;
    n += b;
    a <<= b;
    b = !(a & 0xf000000000000000ULL) << 2;
    n += b;
    a <<= b;
    b = !(a & 0xc000000000000000ULL) << 1;
    n += b;
    a <<= b;
    return n + !(a & 0x8000000000000000ULL);
}

int __ctzsi2(arith64_u32 a)
{
    int b, n = 0;
    b = !(a & 0x0000ffff) << 4;
    n += b;
    a >>= b;
    b = !(a & 0x000000ff) << 3;
    n += b;
    a >>= b;
    b = !(a & 0x0000000f) << 2;
    n += b;
    a >>= b;
    b = !(a & 0x00000003) << 1;
    n += b;
    a >>= b;
    return n + !(a & 0x00000001);
}

int __ctzdi2(arith64_u64 a)
{
    int b, n = 0;
    b = !(a & 0x00000000ffffffffULL) << 5;
    n += b;
    a >>= b;
    b = !(a & 0x000000000000ffffULL) << 4;
    n += b;
    a >>= b;
    b = !(a & 0x00000000000000ffULL) << 3;
    n += b;
    a >>= b;
    b = !(a & 0x000000000000000fULL) << 2;
    n += b;
    a >>= b;
    b = !(a & 0x0000000000000003ULL) << 1;
    n += b;
    a >>= b;
    return n + !(a & 0x0000000000000001ULL);
}

arith64_u64 __divmoddi4(arith64_u64 a, arith64_u64 b, arith64_u64 *c)
{
    if (b > a) //
    {
        if (c)
            *c = a;
        return 0;   
    }
    if (!arith64_hi(b)) 
    {
        if (b == 0) 
        {
            volatile char x = 0;
            x = 1 / x; 
        }
        if (b == 1) 
        {
            if (c)
                *c = 0; 
            return a;   
        }
        if (!arith64_hi(a)) 
        {
            if (c) 
                *c = arith64_lo(a) % arith64_lo(b);
            return arith64_lo(a) / arith64_lo(b);
        }
    }

    
    char bits = __clzdi2(b) - __clzdi2(a) + 1; 
    arith64_u64 rem = a >> bits;               
    a <<= 64 - bits;                           
    arith64_u64 wrap = 0;                      
    while (bits-- > 0)                         
    {
        rem = (rem << 1) | (a >> 63);              
        a = (a << 1) | (wrap & 1);                 
        wrap = ((arith64_s64)(b - rem - 1) >> 63); 
        rem -= b & wrap;                           
    }
    if (c)
        *c = rem;                 
    return (a << 1) | (wrap & 1); 
}


arith64_s64 __divdi3(arith64_s64 a, arith64_s64 b)
{
    arith64_u64 q = __divmoddi4(arith64_abs(a), arith64_abs(b), (void *)0);
    return arith64_neg(q, a ^ b); 
}



int __ffsdi2(arith64_u64 a)
{
    return a ? __ctzdi2(a) + 1 : 0;
}


arith64_u64 __lshrdi3(arith64_u64 a, int b)
{
    arith64_word w = {.u64 = a};

    b &= 63;

    if (b >= 32)
    {
        w.u32.lo = w.u32.hi >> (b - 32);
        w.u32.hi = 0;
    }
    else if (b)
    {
        w.u32.lo = (w.u32.hi << (32 - b)) | (w.u32.lo >> b);
        w.u32.hi >>= b;
    }
    return w.u64;
}


arith64_s64 __moddi3(arith64_s64 a, arith64_s64 b)
{
    arith64_u64 r;
    __divmoddi4(arith64_abs(a), arith64_abs(b), &r);
    return arith64_neg(r, a); 
}


int __popcountsi2(arith64_u32 a)
{
    
    a = a - ((a >> 1) & 0x55555555);
    a = ((a >> 2) & 0x33333333) + (a & 0x33333333);
    a = (a + (a >> 4)) & 0x0F0F0F0F;
    a = (a + (a >> 16));
    
    return (a + (a >> 8)) & 63;
}


int __popcountdi2(arith64_u64 a)
{
    
    a = a - ((a >> 1) & 0x5555555555555555ULL);
    a = ((a >> 2) & 0x3333333333333333ULL) + (a & 0x3333333333333333ULL);
    a = (a + (a >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
    a = (a + (a >> 32));
    a = (a + (a >> 16));
    
    return (a + (a >> 8)) & 127;
}


arith64_u64 __udivdi3(arith64_u64 a, arith64_u64 b)
{
    return __divmoddi4(a, b, (void *)0);
}


arith64_u64 __umoddi3(arith64_u64 a, arith64_u64 b)
{
    arith64_u64 r;
    __divmoddi4(a, b, &r);
    return r;
}