/*
    Copyright (C) 2026 Fredrik Johansson

    This file is part of FLINT.

    FLINT is free software: you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License (LGPL) as published
    by the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.  See <https://www.gnu.org/licenses/>.
*/

#include "test_helpers.h"
#include "radix.h"
#include "gr.h"
#include "fmpz.h"

TEST_FUNCTION_START(radix_integer, state)
{
    slong iter;

    /* valuation_limbs */
    for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++)
    {
        radix_t radix;
        radix_integer_t x, y;
        slong v1, s, v2, wantv2;

        radix_init_randtest(radix, state);
        radix_integer_init(x, radix);
        radix_integer_init(y, radix);

        radix_integer_randtest_limbs(x, state, 5, radix);
        s = n_randint(state, 30);
        radix_integer_lshift_limbs(y, x, s, radix);

        v1 = radix_integer_valuation_limbs(x, radix);
        v2 = radix_integer_valuation_limbs(y, radix);
        wantv2 = radix_integer_is_zero(x, radix) ? 0 : v1 + s;

        if (v2 != wantv2)
        {
            flint_printf("FAIL: valuation_limbs\n");
            flint_printf("radix %wu ^ %u = %wu\n", DIGIT_RADIX(radix), radix->exp, LIMB_RADIX(radix));
            flint_printf("x = (%wd %wd %{ulong*})\n", x->size, x->alloc, x->d, radix_integer_size_limbs(x, radix));
            flint_printf("y = (%wd %wd %{ulong*})\n", y->size, y->alloc, y->d, radix_integer_size_limbs(y, radix));
            flint_printf("v1 = %wd, v2 = %wd\n", v1, v2);
            flint_abort();
        }

        radix_integer_clear(x, radix);
        radix_integer_clear(y, radix);
        radix_clear(radix);
    }

    /* valuation_digits */
    for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++)
    {
        radix_t radix;
        radix_integer_t x, y;
        slong v1, s, v2, wantv2;

        radix_init_randtest(radix, state);
        radix_integer_init(x, radix);
        radix_integer_init(y, radix);

        radix_integer_randtest_limbs(x, state, 5, radix);
        s = n_randint(state, 30);
        radix_integer_lshift_digits(y, x, s, radix);

        v1 = radix_integer_valuation_digits(x, radix);
        v2 = radix_integer_valuation_digits(y, radix);
        wantv2 = radix_integer_is_zero(x, radix) ? 0 : v1 + s;

        if (v2 != wantv2)
        {
            flint_printf("FAIL: valuation_digits\n");
            flint_printf("radix %wu ^ %u = %wu\n", DIGIT_RADIX(radix), radix->exp, LIMB_RADIX(radix));
            flint_printf("x = (%wd %wd %{ulong*})\n", x->size, x->alloc, x->d, radix_integer_size_limbs(x, radix));
            flint_printf("y = (%wd %wd %{ulong*})\n", y->size, y->alloc, y->d, radix_integer_size_limbs(y, radix));
            flint_printf("v1 = %wd, v2 = %wd\n", v1, v2);
            flint_abort();
        }

        radix_integer_clear(x, radix);
        radix_integer_clear(y, radix);
        radix_clear(radix);
    }

    /* lshift_digits */
    for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++)
    {
        radix_t radix;
        radix_integer_t x, y, z;
        slong n, c1, c2, want_c2;

        radix_init_randtest(radix, state);
        radix_integer_init(x, radix);
        radix_integer_init(y, radix);
        radix_integer_init(z, radix);

        radix_integer_randtest_limbs(x, state, 5, radix);
        radix_integer_randtest_limbs(y, state, 5, radix);
        n = n_randint(state, 30);

        if (n_randint(state, 2))
        {
            radix_integer_set(y, x, radix);
            radix_integer_lshift_digits(y, y, n, radix);
        }
        else
        {
            radix_integer_lshift_digits(y, x, n, radix);
        }

        if (n == 0)
        {
            radix_integer_set(z, x, radix);
        }
        else
        {
            radix_integer_set_ui(z, DIGIT_RADIX(radix), radix);
            radix_integer_mul(z, x, z, radix);
            radix_integer_lshift_digits(z, z, n - 1, radix);
        }

        c1 = radix_integer_size_digits(x, radix);
        c2 = radix_integer_size_digits(y, radix);
        want_c2 = c1 + n * (c1 != 0);

        if (!radix_integer_equal(y, z, radix) || (c2 != want_c2) || !radix_integer_is_normalised(y, radix))
        {
            flint_printf("FAIL: lshift_digits\n");
            flint_printf("radix %wu ^ %u = %wu\n", DIGIT_RADIX(radix), radix->exp, LIMB_RADIX(radix));
            flint_printf("x = (%wd %wd %{ulong*})\n", x->size, x->alloc, x->d, radix_integer_size_limbs(x, radix));
            flint_printf("y = (%wd %wd %{ulong*})\n", y->size, y->alloc, y->d, radix_integer_size_limbs(y, radix));
            flint_printf("z = (%wd %wd %{ulong*})\n", z->size, z->alloc, z->d, radix_integer_size_limbs(z, radix));
            flint_printf("n = %wd\n", n);
            flint_printf("c1 = %wd, c2 = %wd\n", c1, c2);
            flint_abort();
        }

        radix_integer_clear(x, radix);
        radix_integer_clear(y, radix);
        radix_integer_clear(z, radix);
        radix_clear(radix);
    }

    /* rshift_digits */
    for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++)
    {
        radix_t radix;
        radix_integer_t x, y, z;
        slong n, c1, c2, want_c2;

        radix_init_randtest(radix, state);
        radix_integer_init(x, radix);
        radix_integer_init(y, radix);
        radix_integer_init(z, radix);

        radix_integer_randtest_limbs(x, state, 5, radix);
        radix_integer_randtest_limbs(y, state, 5, radix);
        n = n_randint(state, 30);

        if (n_randint(state, 2))
        {
            radix_integer_set(y, x, radix);
            radix_integer_rshift_digits(y, y, n, radix);
        }
        else
        {
            radix_integer_rshift_digits(y, x, n, radix);
        }

        if (n == 0)
        {
            radix_integer_set(z, x, radix);
        }
        else
        {
            radix_integer_set_ui(z, DIGIT_RADIX(radix), radix);
            radix_integer_tdiv_q(z, x, z, radix);
            radix_integer_rshift_digits(z, z, n - 1, radix);
        }

        c1 = radix_integer_size_digits(x, radix);
        c2 = radix_integer_size_digits(y, radix);
        want_c2 = FLINT_MAX(0, c1 - n * (c1 != 0));

        if (!radix_integer_equal(y, z, radix) || (c2 != want_c2) || !radix_integer_is_normalised(y, radix))
        {
            flint_printf("FAIL: rshift_digits\n");
            flint_printf("radix %wu ^ %u = %wu\n", DIGIT_RADIX(radix), radix->exp, LIMB_RADIX(radix));
            flint_printf("x = (%wd %wd %{ulong*})\n", x->size, x->alloc, x->d, radix_integer_size_limbs(x, radix));
            flint_printf("y = (%wd %wd %{ulong*})\n", y->size, y->alloc, y->d, radix_integer_size_limbs(y, radix));
            flint_printf("z = (%wd %wd %{ulong*})\n", z->size, z->alloc, z->d, radix_integer_size_limbs(z, radix));
            flint_printf("n = %wd\n", n);
            flint_printf("c1 = %wd, c2 = %wd\n", c1, c2);
            flint_abort();
        }

        radix_integer_clear(x, radix);
        radix_integer_clear(y, radix);
        radix_integer_clear(z, radix);
        radix_clear(radix);
    }

    /* get/set_limb */
    for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++)
    {
        radix_t radix;
        radix_integer_t x, y, z;
        ulong c, d, e;
        slong i;

        radix_init_randtest(radix, state);
        radix_integer_init(x, radix);
        radix_integer_init(y, radix);
        radix_integer_init(z, radix);

        radix_integer_randtest_limbs(x, state, 5, radix);
        radix_integer_randtest_limbs(y, state, 5, radix);

        radix_randtest_limbs(&c, state, 1, radix);
        i = n_randint(state, 5);

        radix_integer_set_limb(y, x, i, c, radix);
        if (n_randint(state, 2))
            radix_integer_neg(y, y, radix);

        radix_integer_set(z, x, radix);
        if (n_randint(state, 2))
            radix_integer_neg(z, z, radix);
        radix_integer_set_limb(z, z, i, c, radix);
        if (n_randint(state, 2))
            radix_integer_neg(z, z, radix);

        d = radix_integer_get_limb(y, i, radix);
        e = radix_integer_get_limb(z, i, radix);

        if (d != c || e != c || !radix_integer_is_normalised(y, radix) ||
                                !radix_integer_is_normalised(z, radix))
        {
            flint_printf("FAIL: get/set_limb\n");
            flint_printf("radix %wu ^ %u = %wu\n", DIGIT_RADIX(radix), radix->exp, LIMB_RADIX(radix));
            flint_printf("x = (%wd %wd %{ulong*})\n", x->size, x->alloc, x->d, radix_integer_size_limbs(x, radix));
            flint_printf("y = (%wd %wd %{ulong*})\n", y->size, y->alloc, y->d, radix_integer_size_limbs(y, radix));
            flint_printf("z = (%wd %wd %{ulong*})\n", z->size, z->alloc, z->d, radix_integer_size_limbs(z, radix));
            flint_printf("i = %wd\n", i);
            flint_printf("c = %wu\n", c);
            flint_printf("d = %wu\n", d);
            flint_printf("e = %wu\n", e);
            flint_abort();
        }

        radix_integer_clear(x, radix);
        radix_integer_clear(y, radix);
        radix_integer_clear(z, radix);
        radix_clear(radix);
    }

    /* get/set_digit */
    for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++)
    {
        radix_t radix;
        radix_integer_t x, y, z;
        ulong c, d, e;
        slong i;

        radix_init_randtest(radix, state);
        radix_integer_init(x, radix);
        radix_integer_init(y, radix);
        radix_integer_init(z, radix);

        radix_integer_randtest_limbs(x, state, 5, radix);
        radix_integer_randtest_limbs(y, state, 5, radix);

        radix_randtest_digits(&c, state, 1, radix);
        i = n_randint(state, 30);

        radix_integer_set_digit(y, x, i, c, radix);
        if (n_randint(state, 2))
            radix_integer_neg(y, y, radix);

        radix_integer_set(z, x, radix);
        if (n_randint(state, 2))
            radix_integer_neg(z, z, radix);

        radix_integer_set_digit(z, z, i, c, radix);
        if (n_randint(state, 2))
            radix_integer_neg(z, z, radix);

        d = radix_integer_get_digit(y, i, radix);
        e = radix_integer_get_digit(z, i, radix);

        if (d != c || e != c || !radix_integer_is_normalised(y, radix) ||
                                !radix_integer_is_normalised(z, radix))
        {
            flint_printf("FAIL: get/set_digit\n");
            flint_printf("radix %wu ^ %u = %wu\n", DIGIT_RADIX(radix), radix->exp, LIMB_RADIX(radix));
            flint_printf("x = (%wd %wd %{ulong*})\n", x->size, x->alloc, x->d, radix_integer_size_limbs(x, radix));
            flint_printf("y = (%wd %wd %{ulong*})\n", y->size, y->alloc, y->d, radix_integer_size_limbs(y, radix));
            flint_printf("z = (%wd %wd %{ulong*})\n", z->size, z->alloc, z->d, radix_integer_size_limbs(z, radix));
            flint_printf("i = %wd\n", i);
            flint_printf("c = %wu\n", c);
            flint_printf("d = %wu\n", d);
            flint_printf("e = %wu\n", e);
            flint_abort();
        }

        radix_integer_clear(x, radix);
        radix_integer_clear(y, radix);
        radix_integer_clear(z, radix);
        radix_clear(radix);
    }

    /* lshift/rshift_limbs */
    for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++)
    {
        radix_t radix;
        radix_integer_t x, y, z;
        slong i, n;

        radix_init_randtest(radix, state);
        radix_integer_init(x, radix);
        radix_integer_init(y, radix);
        radix_integer_init(z, radix);

        radix_integer_randtest_limbs(x, state, 5, radix);
        radix_integer_randtest_limbs(y, state, 5, radix);

        if (n_randint(state, 2))
        {
            n = n_randint(state, 5);

            if (n_randint(state, 2))
            {
                radix_integer_set(y, x, radix);
                radix_integer_lshift_limbs(y, y, n, radix);
            }
            else
            {
                radix_integer_lshift_limbs(y, x, n, radix);
            }

            for (i = 0; i < n; i++)
                radix_integer_set_limb(y, y, i, 1, radix);

            if (n_randint(state, 2))
            {
                radix_integer_set(z, y, radix);
                radix_integer_rshift_limbs(z, z, n, radix);
            }
            else
            {
                radix_integer_rshift_limbs(z, y, n, radix);
            }
        }
        else
        {
            n = radix_integer_valuation_limbs(x, radix);
            radix_integer_rshift_limbs(y, x, n, radix);
            radix_integer_lshift_limbs(z, y, n, radix);
        }

        if (!radix_integer_equal(x, z, radix))
        {
            flint_printf("FAIL: lshift/rshift_limbs\n");
            flint_printf("radix %wu ^ %u = %wu\n", DIGIT_RADIX(radix), radix->exp, LIMB_RADIX(radix));
            flint_printf("x = (%wd %wd %{ulong*})\n", x->size, x->alloc, x->d, radix_integer_size_limbs(x, radix));
            flint_printf("y = (%wd %wd %{ulong*})\n", y->size, y->alloc, y->d, radix_integer_size_limbs(y, radix));
            flint_printf("z = (%wd %wd %{ulong*})\n", z->size, z->alloc, z->d, radix_integer_size_limbs(z, radix));
            flint_printf("n = %wd\n", n);
            flint_abort();
        }

        radix_integer_clear(x, radix);
        radix_integer_clear(y, radix);
        radix_integer_clear(z, radix);
        radix_clear(radix);
    }

    /* mod_limbs */
    for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++)
    {
        radix_t radix;
        radix_integer_t x, y, z;
        slong n;

        radix_init_randtest(radix, state);
        radix_integer_init(x, radix);
        radix_integer_init(y, radix);
        radix_integer_init(z, radix);

        radix_integer_randtest_limbs(x, state, 5, radix);
        radix_integer_randtest_limbs(y, state, 5, radix);
        radix_integer_randtest_limbs(z, state, 5, radix);

        n = n_randint(state, 5);

        radix_integer_mod_limbs(y, x, n, radix);
        radix_integer_lshift_limbs(z, z, n, radix);
        radix_integer_add(z, z, x, radix);
        radix_integer_mod_limbs(z, z, n, radix);

        if (!radix_integer_equal(y, z, radix) ||
            !radix_integer_is_normalised(y, radix) ||
            !radix_integer_is_normalised(z, radix) ||
            radix_integer_sgn(y, radix) < 0)
        {
            flint_printf("FAIL: mod_limbs\n");
            flint_printf("radix %wu ^ %u = %wu\n", DIGIT_RADIX(radix), radix->exp, LIMB_RADIX(radix));
            flint_printf("x = (%wd %wd %{ulong*})\n", x->size, x->alloc, x->d, radix_integer_size_limbs(x, radix));
            flint_printf("y = (%wd %wd %{ulong*})\n", y->size, y->alloc, y->d, radix_integer_size_limbs(y, radix));
            flint_printf("z = (%wd %wd %{ulong*})\n", z->size, z->alloc, z->d, radix_integer_size_limbs(z, radix));
            flint_printf("n = %wd\n", n);
            flint_abort();
        }

        radix_integer_clear(x, radix);
        radix_integer_clear(y, radix);
        radix_integer_clear(z, radix);
        radix_clear(radix);
    }

    /* smod_limbs */
    for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++)
    {
        radix_t radix;
        radix_integer_t x, y, z;
        slong n;

        radix_init_randtest(radix, state);
        radix_integer_init(x, radix);
        radix_integer_init(y, radix);
        radix_integer_init(z, radix);

        radix_integer_randtest_limbs(x, state, 5, radix);
        radix_integer_randtest_limbs(y, state, 5, radix);
        radix_integer_randtest_limbs(z, state, 5, radix);

        n = n_randint(state, 5);

        radix_integer_smod_limbs(y, x, n, radix);
        radix_integer_lshift_limbs(z, z, n, radix);
        radix_integer_add(z, z, x, radix);
        radix_integer_smod_limbs(z, z, n, radix);

        if (!radix_integer_equal(y, z, radix) ||
            !radix_integer_is_normalised(y, radix) ||
            !radix_integer_is_normalised(z, radix) ||
            radix_integer_cmpabs(y, x, radix) > 0)
        {
            flint_printf("FAIL: smod_limbs\n");
            flint_printf("radix %wu ^ %u = %wu\n", DIGIT_RADIX(radix), radix->exp, LIMB_RADIX(radix));
            flint_printf("x = (%wd %wd %{ulong*})\n", x->size, x->alloc, x->d, radix_integer_size_limbs(x, radix));
            flint_printf("y = (%wd %wd %{ulong*})\n", y->size, y->alloc, y->d, radix_integer_size_limbs(y, radix));
            flint_printf("z = (%wd %wd %{ulong*})\n", z->size, z->alloc, z->d, radix_integer_size_limbs(z, radix));
            flint_printf("n = %wd\n", n);
            flint_abort();
        }

        radix_integer_clear(x, radix);
        radix_integer_clear(y, radix);
        radix_integer_clear(z, radix);
        radix_clear(radix);
    }

    /* mullow */
    for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++)
    {
        radix_t radix;
        radix_integer_t x, y, z, w;
        slong n, zrn;

        radix_init_randtest(radix, state);
        radix_integer_init(x, radix);
        radix_integer_init(y, radix);
        radix_integer_init(z, radix);
        radix_integer_init(w, radix);

        radix_integer_randtest_limbs(x, state, 4, radix);
        radix_integer_randtest_limbs(y, state, 4, radix);
        radix_integer_randtest_limbs(z, state, 4, radix);

        n = n_randint(state, 4);

        switch (n_randint(state, 5))
        {
            case 0:
                radix_integer_mullow_limbs(z, x, y, n, radix);
                break;
            case 1:
                radix_integer_set(y, x, radix);
                radix_integer_mullow_limbs(z, x, x, n, radix);
                break;
            case 2:
                radix_integer_set(z, x, radix);
                radix_integer_mullow_limbs(z, z, y, n, radix);
                break;
            case 3:
                radix_integer_set(z, y, radix);
                radix_integer_mullow_limbs(z, x, z, n, radix);
                break;
            default:
                radix_integer_set(y, x, radix);
                radix_integer_set(z, x, radix);
                radix_integer_mullow_limbs(z, z, z, n, radix);
                break;
        }

        zrn = radix_integer_size_limbs(z, radix);
        radix_integer_smod_limbs(z, z, n, radix);

        radix_integer_mul(w, x, y, radix);
        radix_integer_smod_limbs(w, w, n, radix);

        if (zrn > n || !radix_integer_equal(w, z, radix) ||
            !radix_integer_is_normalised(w, radix))
        {
            flint_printf("FAIL: mullow_limbs\n");
            flint_printf("radix %wu ^ %u = %wu\n", DIGIT_RADIX(radix), radix->exp, LIMB_RADIX(radix));
            flint_printf("x = (%wd %wd %{ulong*})\n", x->size, x->alloc, x->d, radix_integer_size_limbs(x, radix));
            flint_printf("y = (%wd %wd %{ulong*})\n", y->size, y->alloc, y->d, radix_integer_size_limbs(y, radix));
            flint_printf("z = (%wd %wd %{ulong*})\n", z->size, z->alloc, z->d, radix_integer_size_limbs(z, radix));
            flint_printf("w = (%wd %wd %{ulong*})\n", w->size, w->alloc, w->d, radix_integer_size_limbs(w, radix));
            flint_printf("n = %wd\n", n);
            flint_abort();
        }

        radix_integer_clear(x, radix);
        radix_integer_clear(y, radix);
        radix_integer_clear(z, radix);
        radix_integer_clear(w, radix);
        radix_clear(radix);
    }

    /* invmod */
    for (iter = 0; iter < 1000 * flint_test_multiplier(); iter++)
    {
        radix_t radix;
        radix_integer_t x, y, z;
        slong n;
        int invertible;

        radix_init_randtest(radix, state);
        radix_integer_init(x, radix);
        radix_integer_init(y, radix);
        radix_integer_init(z, radix);

        radix_integer_randtest_limbs(x, state, 4, radix);
        radix_integer_randtest_limbs(y, state, 4, radix);
        radix_integer_randtest_limbs(z, state, 4, radix);

        n = n_randint(state, 4);

        if (n_randint(state, 2))
        {
            invertible = radix_integer_invmod_limbs(y, x, n, radix);
        }
        else
        {
            radix_integer_set(y, x, radix);
            invertible = radix_integer_invmod_limbs(y, y, n, radix);
        }

        if (invertible)
        {
            radix_integer_mullow_limbs(z, x, y, n, radix);

            if ((n == 0 && !radix_integer_is_zero(y, radix)) ||
                (n != 0 && (
                    !radix_integer_is_one(z, radix) ||
                    !radix_integer_is_normalised(y, radix) ||
                    radix_integer_sgn(y, radix) != radix_integer_sgn(x, radix))))
            {
                flint_printf("FAIL: invmod_limbs\n");
                flint_printf("radix %wu ^ %u = %wu\n", DIGIT_RADIX(radix), radix->exp, LIMB_RADIX(radix));
                flint_printf("x = (%wd %wd %{ulong*})\n", x->size, x->alloc, x->d, radix_integer_size_limbs(x, radix));
                flint_printf("y = (%wd %wd %{ulong*})\n", y->size, y->alloc, y->d, radix_integer_size_limbs(y, radix));
                flint_printf("z = (%wd %wd %{ulong*})\n", z->size, z->alloc, z->d, radix_integer_size_limbs(z, radix));
                flint_printf("n = %wd\n", n);
                flint_abort();
            }
        }

        radix_integer_clear(x, radix);
        radix_integer_clear(y, radix);
        radix_integer_clear(z, radix);
        radix_clear(radix);
    }

    /* tdiv_qr, fdiv_qr */
    for (iter = 0; iter < 10000 * flint_test_multiplier(); iter++)
    {
        radix_t radix;
        radix_integer_t a, b, q, r, q2, r2;
        fmpz_t fa, fb;
        int rnd = n_randint(state, 3);

        radix_init_randtest(radix, state);
        radix_integer_init(a, radix);
        radix_integer_init(b, radix);
        radix_integer_init(q, radix);
        radix_integer_init(r, radix);
        radix_integer_init(q2, radix);
        radix_integer_init(r2, radix);
        fmpz_init(fa);
        fmpz_init(fb);

        radix_integer_randtest_limbs(a, state, 4, radix);
        do {
            radix_integer_randtest_limbs(b, state, 4, radix);
        } while (b->size == 0);

        radix_integer_randtest_limbs(q, state, 2, radix);
        radix_integer_randtest_limbs(r, state, 2, radix);

        if (rnd == 0)
            radix_integer_tdiv_qr(q, r, a, b, radix);
        else if (rnd == 1)
            radix_integer_fdiv_qr(q, r, a, b, radix);
        else
            radix_integer_cdiv_qr(q, r, a, b, radix);

        radix_integer_get_fmpz(fa, a, radix);
        radix_integer_get_fmpz(fb, b, radix);

        if (rnd == 0)
            fmpz_tdiv_qr(fa, fb, fa, fb);
        else if (rnd == 1)
            fmpz_fdiv_qr(fa, fb, fa, fb);
        else
            fmpz_cdiv_qr(fa, fb, fa, fb);

        radix_integer_set_fmpz(q2, fa, radix);
        radix_integer_set_fmpz(r2, fb, radix);

        if (!radix_integer_equal(q, q2, radix) || !radix_integer_equal(r, r2, radix))
        {
            flint_printf("FAIL: div_qr\n");
            flint_printf("rnd = %d\n", rnd);
            flint_printf("radix %wu ^ %u = %wu\n", DIGIT_RADIX(radix), radix->exp, LIMB_RADIX(radix));
            flint_printf("a = (%wd %wd %{ulong*})\n", a->size, a->alloc, a->d, radix_integer_size_limbs(a, radix));
            flint_printf("b = (%wd %wd %{ulong*})\n", b->size, b->alloc, b->d, radix_integer_size_limbs(b, radix));
            flint_printf("q = (%wd %wd %{ulong*})\n", q->size, q->alloc, q->d, radix_integer_size_limbs(q, radix));
            flint_printf("r = (%wd %wd %{ulong*})\n", r->size, r->alloc, r->d, radix_integer_size_limbs(r, radix));
            flint_printf("q2 = (%wd %wd %{ulong*})\n", q2->size, q2->alloc, q2->d, radix_integer_size_limbs(q2, radix));
            flint_printf("r2 = (%wd %wd %{ulong*})\n", r2->size, r2->alloc, r2->d, radix_integer_size_limbs(r2, radix));
            flint_abort();
        }

        radix_integer_clear(a, radix);
        radix_integer_clear(b, radix);
        radix_integer_clear(q, radix);
        radix_integer_clear(r, radix);
        radix_integer_clear(q2, radix);
        radix_integer_clear(r2, radix);
        fmpz_clear(fa);
        fmpz_clear(fb);
        radix_clear(radix);
    }

    for (iter = 0; iter < 100 * flint_test_multiplier(); iter++)
    {
        radix_t radix;
        gr_ctx_t ctx;

        radix_init_randtest(radix, state);
        gr_ctx_init_radix_integer(ctx, DIGIT_RADIX(radix), radix->exp);

        gr_test_ring(ctx, 10, 0);

        gr_ctx_clear(ctx);
        radix_clear(radix);
    }

    TEST_FUNCTION_END(state);
}
