Skip to content

IntRootRem

Description

Compute an integer root and the leftover remainder.

Parameters

Name Direction Description
root out Destination for the root
remainder out Destination for the remainder
value in Input value
degree in Root degree

Usage example (from documentation)

  IntRootRem(&root, &rem, &value, 3);

Success

Returns true. *root holds floor(value^(1/degree)), *remainder holds value - root^degree.

Failure

Returns false on degree == 0 or allocator OOM. *root / *remainder are left untouched.

Usage example (Cross-references)

Usage examples (Cross-references)
    }
    
    bool IntRootRem(Int *root, Int *remainder, const Int *value, u64 degree) {
        ValidateInt(root);
        ValidateInt(remainder);
        Int remainder = IntInit(IntAllocator(result));
    
        if (!IntRootRem(&root, &remainder, value, degree)) {
            IntDeinit(&root);
            IntDeinit(&remainder);
    
    bool IntSqrtRem(Int *root, Int *remainder, const Int *value) {
        return IntRootRem(root, remainder, value, 2);
    }
            bool exact     = false;
    
            if (!IntRootRem(&root, &remainder, value, degree)) {
                IntDeinit(&root);
                IntDeinit(&remainder);
    
    bool test_int_root_rem(void) {
        WriteFmt("Testing IntRootRem\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        Int remainder = IntInit(&alloc.base);
    
        IntRootRem(&root, &remainder, &value, 3);
    
        bool result = IntToU64(&root) == 5;
        Int  root      = IntFrom(99, &alloc.base);
        Int  remainder = IntFrom(77, &alloc.base);
        bool result    = !IntRootRem(&root, &remainder, &value, 0);
    
        result = result && (IntCompare(&root, 99) == 0);
    // (lines 1712/1713) leaves the stale value and fails the assertion.
    static bool test_m2_root_rem_zero_value_resets_outputs(void) {
        WriteFmt("Testing IntRootRem zero-value resets both outputs\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        Int remainder = IntFrom(77, &alloc.base);
    
        bool ok     = IntRootRem(&root, &remainder, &value, 3);
        bool result = ok;
        result      = result && (IntCompare(&root, 0) == 0);
    // root. Also exercises the loop midpoint shift (1766).
    static bool test_m2_root_rem_perfect_square_large(void) {
        WriteFmt("Testing IntRootRem 10000^(1/2) == 100 exact\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        Int remainder = IntInit(&alloc.base);
    
        bool ok     = IntRootRem(&root, &remainder, &value, 2);
        bool result = ok;
        result      = result && (IntToU64(&root) == 100);
    // further constrain the high_shift bit-length math and the binary search.
    static bool test_m2_root_rem_perfect_cube(void) {
        WriteFmt("Testing IntRootRem 1000^(1/3) == 10 exact\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        Int remainder = IntInit(&alloc.base);
    
        bool ok     = IntRootRem(&root, &remainder, &value, 3);
        bool result = ok;
        result      = result && (IntToU64(&root) == 10);
    // the midpoint/compare path produces a wrong root or remainder.
    static bool test_m2_root_rem_nonperfect_cube_remainder(void) {
        WriteFmt("Testing IntRootRem 1001^(1/3) == 10 rem 1\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        Int remainder = IntInit(&alloc.base);
    
        bool ok     = IntRootRem(&root, &remainder, &value, 3);
        bool result = ok;
        result      = result && (IntToU64(&root) == 10);
    // search to settle one below 10 and validates the remainder subtraction path.
    static bool test_m2_root_rem_just_below_perfect_cube(void) {
        WriteFmt("Testing IntRootRem 999^(1/3) == 9 rem 270\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        Int remainder = IntInit(&alloc.base);
    
        bool ok     = IntRootRem(&root, &remainder, &value, 3);
        bool result = ok;
        result      = result && (IntToU64(&root) == 9);
    // 1000000^(1/4): 31^4=923521, 32^4=1048576 -> root 31, rem 1000000-923521=76479.
    static bool test_m2_root_rem_fourth_root_large(void) {
        WriteFmt("Testing IntRootRem 1000000^(1/4) == 31 rem 76479\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        Int remainder = IntInit(&alloc.base);
    
        bool ok     = IntRootRem(&root, &remainder, &value, 4);
        bool result = ok;
        result      = result && (IntToU64(&root) == 31);
    // mutant returns a wrong (too small) root.
    bool test_fe_1730_root_rem_large_value(void) {
        WriteFmt("Testing IntRootRem bit-length derived bound (large value)\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        Int rem  = IntFrom(9u, a);
    
        bool ok = IntRootRem(&root, &rem, &v, 3); // 100^3 = 1e6
        ok      = ok && IntToU64(&root) == 100u && IntIsZero(&rem);
        Int rem  = IntFrom(9u, a);
    
        bool ok = IntRootRem(&root, &rem, &v, 3); // cbrt(1000)=10 exact actually
        ok      = ok && IntToU64(&root) == 10u && IntIsZero(&rem);
        // and a genuinely inexact one
        Int v2 = IntFrom(999u, a);
        ok     = ok && IntRootRem(&root, &rem, &v2, 3);
        ok     = ok && IntToU64(&root) == 9u && IntToU64(&rem) == 999u - 729u;
    // the int_replace removals (1725/1726).
    static bool test_m2_root_rem_degree_one_clones_value(void) {
        WriteFmt("Testing IntRootRem degree==1 clones value, zero remainder\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        Int remainder = IntFrom(77, &alloc.base);
    
        bool ok     = IntRootRem(&root, &remainder, &value, 1);
        bool result = ok;
        result      = result && (IntToU64(&root) == 12345);
Last updated on