From e0751f16b82305f525c6f385961c673e0347ce05 Mon Sep 17 00:00:00 2001 From: Matthias Gessinger Date: Fri, 5 Jul 2024 20:20:36 +0200 Subject: [PATCH 1/9] Implement summation of powers of an integer --- src/fmpz.h | 4 +++ src/fmpz/sum_powers.c | 68 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 src/fmpz/sum_powers.c diff --git a/src/fmpz.h b/src/fmpz.h index 140d0fc299..35c88cb752 100644 --- a/src/fmpz.h +++ b/src/fmpz.h @@ -440,6 +440,10 @@ slong fmpz_flog_ui(const fmpz_t x, ulong b); double fmpz_get_d_2exp(slong * exp, const fmpz_t f); void fmpz_set_d_2exp(fmpz_t f, double m, slong exp); +void fmpz_sum_powers_horner(fmpz_t f, const fmpz_t g, ulong exp); +void fmpz_sum_powers_div(fmpz_t f, const fmpz_t g, ulong exp); +void fmpz_sum_powers(fmpz_t f, const fmpz_t g, ulong exp); + #if FLINT_HAVE_FFT_SMALL #define MPZ_WANT_FLINT_DIVISION(a, b) (mpz_size(b) >= 1250 && mpz_size(a) - mpz_size(b) >= 1250) #else diff --git a/src/fmpz/sum_powers.c b/src/fmpz/sum_powers.c new file mode 100644 index 0000000000..6a0401519f --- /dev/null +++ b/src/fmpz/sum_powers.c @@ -0,0 +1,68 @@ +/* + Copyright (C) 2024 Matthias Gessinger + + 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 . +*/ + +#include "fmpz.h" + +void +fmpz_sum_powers_horner(fmpz_t f, const fmpz_t g, ulong exp) +{ + fmpz_t t; + fmpz_init_set_ui(t, 1); + + for (ulong i = 1; i < exp; i++) + { + fmpz_mul(t, t, g); + fmpz_add_ui(t, t, 1); + } + + fmpz_swap(f, t); + fmpz_clear(t); +} + +void +fmpz_sum_powers_div(fmpz_t f, const fmpz_t g, ulong exp) +{ + fmpz_t t; + fmpz_init(t); + + // t = g^(e + 1) - 1 + fmpz_pow_ui(t, g, exp + 1); + fmpz_sub_ui(t, t, 1); + + // f = g - 1 + fmpz_sub_ui(f, g, 1); + + // f = (g^(e + 1) - 1) / (g - 1) + fmpz_tdiv(f, t, g); + + fmpz_clear(t); +} + +void +fmpz_sum_powers(fmpz_t f, const fmpz_t g, ulong exp) +{ + if (exp == 0) + { + fmpz_zero(f); + } + else if (exp == 1) + { + fmpz_add_ui(f, g, 1); + } + else if (exp <= 100) + { + _fmpz_sum_powers_horner(f, g, exp); + } + else + { + _fmpz_sum_powers_div(f, g, exp); + } +} From a4d747b76feb614da4f11cccb5d02ab0664463f7 Mon Sep 17 00:00:00 2001 From: Matthias Gessinger Date: Fri, 5 Jul 2024 21:38:28 +0200 Subject: [PATCH 2/9] Add test for sum of powers --- src/fmpz/test/main.c | 2 + src/fmpz/test/t-sum_powers.c | 89 ++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 src/fmpz/test/t-sum_powers.c diff --git a/src/fmpz/test/main.c b/src/fmpz/test/main.c index 17381eff6d..4ecf5e1362 100644 --- a/src/fmpz/test/main.c +++ b/src/fmpz/test/main.c @@ -190,6 +190,7 @@ #include "t-xgcd_canonical_bezout.c" #include "t-xgcd_partial.c" #include "t-xor.c" +#include "t-sum_powers.c" /* Array of test functions ***************************************************/ @@ -360,6 +361,7 @@ test_struct tests[] = TEST_FUNCTION(fmpz_xgcd_canonical_bezout), TEST_FUNCTION(fmpz_xgcd_partial), TEST_FUNCTION(fmpz_xor) + TEST_FUNCTION(fmpz_sum_powers) }; /* main function *************************************************************/ diff --git a/src/fmpz/test/t-sum_powers.c b/src/fmpz/test/t-sum_powers.c new file mode 100644 index 0000000000..4b066fa645 --- /dev/null +++ b/src/fmpz/test/t-sum_powers.c @@ -0,0 +1,89 @@ +/* + Copyright (C) 2024 Matthias Gessinger + + 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 . +*/ + +#include "test_helpers.h" +#include "ulong_extras.h" +#include "fmpz.h" + +void _sum_powers_naive(fmpz_t f, const fmpz_t g, ulong exp); +{ + fmpz_t t; + fmpz_init(t); + + fmpz_zero(f); + + for (ulong i = 0; i < exp; i++) + { + fmpz_pow_ui(t, g, i); + fmpz_add(f, f, t); + } + + fmpz_clear(t); +} + +TEST_FUNCTION_START(fmpz_sum_powers, state) +{ + int i, result; + + for (i = 0; i < 1000 * flint_test_multiplier(); i++) + { + fmpz_t a, b, c; + ulong exp; + int aliasing; + + fmpz_init(a); + fmpz_init(b); + fmpz_init(c); + + fmpz_randtest(a, state, 200); + fmpz_randtest(b, state, 200); + + exp = n_randint(state, 1<<10); + + aliasing = n_randint(state, 2); + + if (aliasing == 1) + { + fmpz_sum_powers(a, a, exp); + fmpz_set(b, a); + } + else + { + fmpz_sum_powers(b, a, exp); + } + + _fmpz_sum_powers_naive(c, a, exp); + + result = fmpz_cmp(c, b); + + if (!result) + { + flint_printf("FAIL:\n"); + + flint_printf("Expected: "); + fmpz_print(c); + flint_printf("\n"); + + flint_printf("Actual: "); + fmpz_print(b); + flint_printf("\n"); + + fflush(stdout); + flint_abort(); + } + + fmpz_clear(a); + fmpz_clear(b); + fmpz_clear(c); + } + + TEST_FUNCTION_END(state); +} From 36be38cb4567bebdca94f1e26a06758c0e376cc4 Mon Sep 17 00:00:00 2001 From: Matthias Gessinger Date: Fri, 5 Jul 2024 22:43:12 +0200 Subject: [PATCH 3/9] Fix sum_powers after testing --- src/fmpz/sum_powers.c | 94 ++++++++++++++++++----------- src/fmpz/test/main.c | 6 +- src/fmpz/test/t-sum_powers.c | 19 +++--- src/fmpz/test/t-sum_powers_div.c | 90 +++++++++++++++++++++++++++ src/fmpz/test/t-sum_powers_horner.c | 90 +++++++++++++++++++++++++++ 5 files changed, 254 insertions(+), 45 deletions(-) create mode 100644 src/fmpz/test/t-sum_powers_div.c create mode 100644 src/fmpz/test/t-sum_powers_horner.c diff --git a/src/fmpz/sum_powers.c b/src/fmpz/sum_powers.c index 6a0401519f..32df74f6af 100644 --- a/src/fmpz/sum_powers.c +++ b/src/fmpz/sum_powers.c @@ -14,55 +14,79 @@ void fmpz_sum_powers_horner(fmpz_t f, const fmpz_t g, ulong exp) { - fmpz_t t; - fmpz_init_set_ui(t, 1); + fmpz_t t; - for (ulong i = 1; i < exp; i++) - { - fmpz_mul(t, t, g); - fmpz_add_ui(t, t, 1); - } + if (exp == 0 || fmpz_is_zero(g)) + { + fmpz_one(f); + } + else if (fmpz_is_one(g)) + { + fmpz_set_ui(f, exp + 1); + } + else + { + fmpz_init_set_ui(t, 1); - fmpz_swap(f, t); - fmpz_clear(t); + for (ulong i = 1; i <= exp; i++) + { + fmpz_mul(t, t, g); + fmpz_add_ui(t, t, 1); + } + + fmpz_swap(f, t); + fmpz_clear(t); + } } void fmpz_sum_powers_div(fmpz_t f, const fmpz_t g, ulong exp) { - fmpz_t t; - fmpz_init(t); + fmpz_t t; + + if (exp == 0 || fmpz_is_zero(g)) + { + fmpz_one(f); + } + else if (fmpz_is_one(g)) + { + fmpz_set_ui(f, exp + 1); + } + else + { + fmpz_init(t); - // t = g^(e + 1) - 1 - fmpz_pow_ui(t, g, exp + 1); - fmpz_sub_ui(t, t, 1); + // t = g - 1 + fmpz_sub_ui(t, g, 1); - // f = g - 1 - fmpz_sub_ui(f, g, 1); + // f = g^(e + 1) - 1 + fmpz_pow_ui(f, g, exp + 1); + fmpz_sub_ui(f, f, 1); - // f = (g^(e + 1) - 1) / (g - 1) - fmpz_tdiv(f, t, g); + // f = (g^(e + 1) - 1) / (g - 1) + fmpz_tdiv_q(f, f, t); - fmpz_clear(t); + fmpz_clear(t); + } } void fmpz_sum_powers(fmpz_t f, const fmpz_t g, ulong exp) { - if (exp == 0) - { - fmpz_zero(f); - } - else if (exp == 1) - { - fmpz_add_ui(f, g, 1); - } - else if (exp <= 100) - { - _fmpz_sum_powers_horner(f, g, exp); - } - else - { - _fmpz_sum_powers_div(f, g, exp); - } + if (exp == 0 || fmpz_is_zero(g)) + { + fmpz_one(f); + } + else if (exp == 1) + { + fmpz_add_ui(f, g, 1); + } + else if (exp <= 100) + { + fmpz_sum_powers_horner(f, g, exp); + } + else + { + fmpz_sum_powers_div(f, g, exp); + } } diff --git a/src/fmpz/test/main.c b/src/fmpz/test/main.c index 4ecf5e1362..d2338062a6 100644 --- a/src/fmpz/test/main.c +++ b/src/fmpz/test/main.c @@ -190,6 +190,8 @@ #include "t-xgcd_canonical_bezout.c" #include "t-xgcd_partial.c" #include "t-xor.c" +#include "t-sum_powers_horner.c" +#include "t-sum_powers_div.c" #include "t-sum_powers.c" /* Array of test functions ***************************************************/ @@ -360,7 +362,9 @@ test_struct tests[] = TEST_FUNCTION(fmpz_xgcd), TEST_FUNCTION(fmpz_xgcd_canonical_bezout), TEST_FUNCTION(fmpz_xgcd_partial), - TEST_FUNCTION(fmpz_xor) + TEST_FUNCTION(fmpz_xor), + TEST_FUNCTION(fmpz_sum_powers_horner), + TEST_FUNCTION(fmpz_sum_powers_div), TEST_FUNCTION(fmpz_sum_powers) }; diff --git a/src/fmpz/test/t-sum_powers.c b/src/fmpz/test/t-sum_powers.c index 4b066fa645..7d23402ccb 100644 --- a/src/fmpz/test/t-sum_powers.c +++ b/src/fmpz/test/t-sum_powers.c @@ -13,14 +13,14 @@ #include "ulong_extras.h" #include "fmpz.h" -void _sum_powers_naive(fmpz_t f, const fmpz_t g, ulong exp); +void _fmpz_sum_powers_naive(fmpz_t f, const fmpz_t g, ulong exp) { fmpz_t t; fmpz_init(t); fmpz_zero(f); - for (ulong i = 0; i < exp; i++) + for (ulong i = 0; i <= exp; i++) { fmpz_pow_ui(t, g, i); fmpz_add(f, f, t); @@ -43,13 +43,16 @@ TEST_FUNCTION_START(fmpz_sum_powers, state) fmpz_init(b); fmpz_init(c); - fmpz_randtest(a, state, 200); - fmpz_randtest(b, state, 200); + fmpz_randtest(a, state, 100); - exp = n_randint(state, 1<<10); + exp = n_randint(state, 250); aliasing = n_randint(state, 2); + /* The reference result */ + _fmpz_sum_powers_naive(c, a, exp); + + /* general function */ if (aliasing == 1) { fmpz_sum_powers(a, a, exp); @@ -60,13 +63,11 @@ TEST_FUNCTION_START(fmpz_sum_powers, state) fmpz_sum_powers(b, a, exp); } - _fmpz_sum_powers_naive(c, a, exp); - - result = fmpz_cmp(c, b); + result = (fmpz_cmp(c, b) == 0); if (!result) { - flint_printf("FAIL:\n"); + flint_printf("FAIL in general method:\n"); flint_printf("Expected: "); fmpz_print(c); diff --git a/src/fmpz/test/t-sum_powers_div.c b/src/fmpz/test/t-sum_powers_div.c new file mode 100644 index 0000000000..79c1df8f76 --- /dev/null +++ b/src/fmpz/test/t-sum_powers_div.c @@ -0,0 +1,90 @@ +/* + Copyright (C) 2024 Matthias Gessinger + + 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 . +*/ + +#include "test_helpers.h" +#include "ulong_extras.h" +#include "fmpz.h" + +void _fmpz_sum_powers_naive_div(fmpz_t f, const fmpz_t g, ulong exp) +{ + fmpz_t t; + fmpz_init(t); + + fmpz_zero(f); + + for (ulong i = 0; i <= exp; i++) + { + fmpz_pow_ui(t, g, i); + fmpz_add(f, f, t); + } + + fmpz_clear(t); +} + +TEST_FUNCTION_START(fmpz_sum_powers_div, state) +{ + int i, result; + + for (i = 0; i < 1000 * flint_test_multiplier(); i++) + { + fmpz_t a, b, c; + ulong exp; + int aliasing; + + fmpz_init(a); + fmpz_init(b); + fmpz_init(c); + + fmpz_randtest(a, state, 100); + + exp = n_randint(state, 250); + + aliasing = n_randint(state, 2); + + /* The reference result */ + _fmpz_sum_powers_naive_div(c, a, exp); + + /* polynomial division method */ + if (aliasing == 1) + { + fmpz_sum_powers_div(a, a, exp); + fmpz_set(b, a); + } + else + { + fmpz_sum_powers_div(b, a, exp); + } + + result = (fmpz_cmp(c, b) == 0); + + if (!result) + { + flint_printf("FAIL in polynomial division method:\n"); + + flint_printf("Expected: "); + fmpz_print(c); + flint_printf("\n"); + + flint_printf("Actual: "); + fmpz_print(b); + flint_printf("\n"); + + fflush(stdout); + flint_abort(); + } + + fmpz_clear(a); + fmpz_clear(b); + fmpz_clear(c); + } + + TEST_FUNCTION_END(state); +} diff --git a/src/fmpz/test/t-sum_powers_horner.c b/src/fmpz/test/t-sum_powers_horner.c new file mode 100644 index 0000000000..7d39f0c70d --- /dev/null +++ b/src/fmpz/test/t-sum_powers_horner.c @@ -0,0 +1,90 @@ +/* + Copyright (C) 2024 Matthias Gessinger + + 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 . +*/ + +#include "test_helpers.h" +#include "ulong_extras.h" +#include "fmpz.h" + +void _fmpz_sum_powers_naive_horner(fmpz_t f, const fmpz_t g, ulong exp) +{ + fmpz_t t; + fmpz_init(t); + + fmpz_zero(f); + + for (ulong i = 0; i <= exp; i++) + { + fmpz_pow_ui(t, g, i); + fmpz_add(f, f, t); + } + + fmpz_clear(t); +} + +TEST_FUNCTION_START(fmpz_sum_powers_horner, state) +{ + int i, result; + + for (i = 0; i < 1000 * flint_test_multiplier(); i++) + { + fmpz_t a, b, c; + ulong exp; + int aliasing; + + fmpz_init(a); + fmpz_init(b); + fmpz_init(c); + + fmpz_randtest(a, state, 100); + + exp = n_randint(state, 250); + + aliasing = n_randint(state, 2); + + /* The reference result */ + _fmpz_sum_powers_naive_horner(c, a, exp); + + /* Horner-style evaluation */ + if (aliasing == 1) + { + fmpz_sum_powers_horner(a, a, exp); + fmpz_set(b, a); + } + else + { + fmpz_sum_powers_horner(b, a, exp); + } + + result = (fmpz_cmp(c, b) == 0); + + if (!result) + { + flint_printf("FAIL in horner evaluation:\n"); + + flint_printf("Expected: "); + fmpz_print(c); + flint_printf("\n"); + + flint_printf("Actual: "); + fmpz_print(b); + flint_printf("\n"); + + fflush(stdout); + flint_abort(); + } + + fmpz_clear(a); + fmpz_clear(b); + fmpz_clear(c); + } + + TEST_FUNCTION_END(state); +} From 48ef3d3fe1d6f723f10b1643560b3787e064e4e0 Mon Sep 17 00:00:00 2001 From: Matthias Gessinger Date: Fri, 5 Jul 2024 23:46:59 +0200 Subject: [PATCH 4/9] Add fmpz_sum_divisors and tests --- src/fmpz.h | 11 +-- src/fmpz/sum_divisors.c | 75 +++++++++++++++++++++ src/fmpz/sum_powers.c | 114 +++++++++++++++---------------- src/fmpz/test/main.c | 4 +- src/fmpz/test/t-sum_divisors.c | 120 +++++++++++++++++++++++++++++++++ 5 files changed, 262 insertions(+), 62 deletions(-) create mode 100644 src/fmpz/sum_divisors.c create mode 100644 src/fmpz/test/t-sum_divisors.c diff --git a/src/fmpz.h b/src/fmpz.h index 35c88cb752..52a5b6c711 100644 --- a/src/fmpz.h +++ b/src/fmpz.h @@ -378,6 +378,13 @@ void fmpz_pow_ui(fmpz_t f, const fmpz_t g, ulong exp); void fmpz_ui_pow_ui(fmpz_t x, ulong b, ulong e); int fmpz_pow_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t e); +void fmpz_sum_powers(fmpz_t f, const fmpz_t g, ulong exp); +void fmpz_sum_powers_horner(fmpz_t f, const fmpz_t g, ulong exp); +void fmpz_sum_powers_div(fmpz_t f, const fmpz_t g, ulong exp); + +void fmpz_sum_divisors(fmpz_t f, const fmpz_t g); +void fmpz_sum_divisors_proper(fmpz_t f, const fmpz_t g); + void fmpz_sqrt(fmpz_t f, const fmpz_t g); void fmpz_sqrtrem(fmpz_t f, fmpz_t r, const fmpz_t g); @@ -440,10 +447,6 @@ slong fmpz_flog_ui(const fmpz_t x, ulong b); double fmpz_get_d_2exp(slong * exp, const fmpz_t f); void fmpz_set_d_2exp(fmpz_t f, double m, slong exp); -void fmpz_sum_powers_horner(fmpz_t f, const fmpz_t g, ulong exp); -void fmpz_sum_powers_div(fmpz_t f, const fmpz_t g, ulong exp); -void fmpz_sum_powers(fmpz_t f, const fmpz_t g, ulong exp); - #if FLINT_HAVE_FFT_SMALL #define MPZ_WANT_FLINT_DIVISION(a, b) (mpz_size(b) >= 1250 && mpz_size(a) - mpz_size(b) >= 1250) #else diff --git a/src/fmpz/sum_divisors.c b/src/fmpz/sum_divisors.c new file mode 100644 index 0000000000..c3465f91d3 --- /dev/null +++ b/src/fmpz/sum_divisors.c @@ -0,0 +1,75 @@ +/* + Copyright (C) 2024 Matthias Gessinger + + 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 . +*/ + +#include "fmpz.h" +#include "fmpz_factor.h" + +void +fmpz_sum_divisors(fmpz_t f, const fmpz_t g) +{ + fmpz_factor_t factors; + fmpz * temp; + ulong exp; + ulong i; + + fmpz * p; + + if (fmpz_is_zero(g) || fmpz_is_pm1(g)) + { + fmpz_set(f, g); + } + else + { + fmpz_factor_init(factors); + + fmpz_factor(factors, g); + i = 0; + + temp = factors->p + i; + exp = factors->exp[i]; + + fmpz_sum_powers(temp, temp, exp); + + for (i = 1; i < factors->num; i++) + { + p = factors->p + i; + exp = factors->exp[i]; + + fmpz_sum_powers(p, p, exp); + + fmpz_mul(temp, temp, p); + } + + if (factors->sign == -1) + { + fmpz_neg(f, temp); + } + else + { + fmpz_swap(f, temp); + } + + fmpz_factor_clear(factors); + } +} + +void +fmpz_sum_divisors_proper(fmpz_t f, const fmpz_t g) +{ + fmpz_t temp; + fmpz_init(temp); + + fmpz_sum_divisors(temp, g); + + fmpz_sub(f, temp, g); + + fmpz_clear(temp); +} diff --git a/src/fmpz/sum_powers.c b/src/fmpz/sum_powers.c index 32df74f6af..50f71611b2 100644 --- a/src/fmpz/sum_powers.c +++ b/src/fmpz/sum_powers.c @@ -14,79 +14,79 @@ void fmpz_sum_powers_horner(fmpz_t f, const fmpz_t g, ulong exp) { - fmpz_t t; + fmpz_t t; - if (exp == 0 || fmpz_is_zero(g)) - { - fmpz_one(f); - } - else if (fmpz_is_one(g)) - { - fmpz_set_ui(f, exp + 1); - } - else - { - fmpz_init_set_ui(t, 1); + if (exp == 0 || fmpz_is_zero(g)) + { + fmpz_one(f); + } + else if (fmpz_is_one(g)) + { + fmpz_set_ui(f, exp + 1); + } + else + { + fmpz_init_set_ui(t, 1); - for (ulong i = 1; i <= exp; i++) - { - fmpz_mul(t, t, g); - fmpz_add_ui(t, t, 1); - } + for (ulong i = 1; i <= exp; i++) + { + fmpz_mul(t, t, g); + fmpz_add_ui(t, t, 1); + } - fmpz_swap(f, t); - fmpz_clear(t); - } + fmpz_swap(f, t); + fmpz_clear(t); + } } void fmpz_sum_powers_div(fmpz_t f, const fmpz_t g, ulong exp) { - fmpz_t t; + fmpz_t t; - if (exp == 0 || fmpz_is_zero(g)) - { - fmpz_one(f); - } - else if (fmpz_is_one(g)) - { - fmpz_set_ui(f, exp + 1); - } - else - { - fmpz_init(t); + if (exp == 0 || fmpz_is_zero(g)) + { + fmpz_one(f); + } + else if (fmpz_is_one(g)) + { + fmpz_set_ui(f, exp + 1); + } + else + { + fmpz_init(t); - // t = g - 1 - fmpz_sub_ui(t, g, 1); + /* t = g - 1 */ + fmpz_sub_ui(t, g, 1); - // f = g^(e + 1) - 1 - fmpz_pow_ui(f, g, exp + 1); - fmpz_sub_ui(f, f, 1); + /* f = g^(e + 1) - 1 */ + fmpz_pow_ui(f, g, exp + 1); + fmpz_sub_ui(f, f, 1); - // f = (g^(e + 1) - 1) / (g - 1) - fmpz_tdiv_q(f, f, t); + /* f = (g^(e + 1) - 1) / (g - 1) */ + fmpz_tdiv_q(f, f, t); - fmpz_clear(t); - } + fmpz_clear(t); + } } void fmpz_sum_powers(fmpz_t f, const fmpz_t g, ulong exp) { - if (exp == 0 || fmpz_is_zero(g)) - { - fmpz_one(f); - } - else if (exp == 1) - { - fmpz_add_ui(f, g, 1); - } - else if (exp <= 100) - { - fmpz_sum_powers_horner(f, g, exp); - } - else - { - fmpz_sum_powers_div(f, g, exp); - } + if (exp == 0 || fmpz_is_zero(g)) + { + fmpz_one(f); + } + else if (exp == 1) + { + fmpz_add_ui(f, g, 1); + } + else if (exp <= 100) + { + fmpz_sum_powers_horner(f, g, exp); + } + else + { + fmpz_sum_powers_div(f, g, exp); + } } diff --git a/src/fmpz/test/main.c b/src/fmpz/test/main.c index d2338062a6..c6a4b8b0a4 100644 --- a/src/fmpz/test/main.c +++ b/src/fmpz/test/main.c @@ -193,6 +193,7 @@ #include "t-sum_powers_horner.c" #include "t-sum_powers_div.c" #include "t-sum_powers.c" +#include "t-sum_divisors.c" /* Array of test functions ***************************************************/ @@ -365,7 +366,8 @@ test_struct tests[] = TEST_FUNCTION(fmpz_xor), TEST_FUNCTION(fmpz_sum_powers_horner), TEST_FUNCTION(fmpz_sum_powers_div), - TEST_FUNCTION(fmpz_sum_powers) + TEST_FUNCTION(fmpz_sum_powers), + TEST_FUNCTION(fmpz_sum_divisors) }; /* main function *************************************************************/ diff --git a/src/fmpz/test/t-sum_divisors.c b/src/fmpz/test/t-sum_divisors.c new file mode 100644 index 0000000000..536d2f613a --- /dev/null +++ b/src/fmpz/test/t-sum_divisors.c @@ -0,0 +1,120 @@ +/* + Copyright (C) 2024 Matthias Gessinger + + 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 . +*/ + +#include "test_helpers.h" +#include "ulong_extras.h" +#include "fmpz.h" + +void _fmpz_sum_divisors_naive(fmpz_t f, fmpz_t g) +{ + fmpz_t sqrt, temp1, temp2, temp3, out; + + fmpz_init(sqrt); + fmpz_init(temp1); + fmpz_init(temp2); + fmpz_init(temp3); + fmpz_init(out); + + int is_neg = fmpz_cmp_ui(g, 0) < 1; + + fmpz_abs(f, g); + fmpz_sqrt(sqrt, f); + + fmpz_set_si(temp1, 1); + while (fmpz_cmp(temp1, sqrt) != 1) + { + fmpz_tdiv_qr(temp3, temp2, f, temp1); + + if (fmpz_is_zero(temp2)) + { + fmpz_add(out, out, temp3); + + if (fmpz_cmp(temp1, temp3) != 0) + { + fmpz_add(out, out, temp1); + } + } + + fmpz_add_si(temp1, temp1, 1); + } + + if (is_neg) + { + fmpz_neg(f, out); + } + else + { + fmpz_set(f, out); + } + + fmpz_clear(out); + fmpz_clear(temp1); + fmpz_clear(temp2); + fmpz_clear(temp3); + fmpz_clear(sqrt); +} + +TEST_FUNCTION_START(fmpz_sum_divisors, state) +{ + int i, result; + + for (i = 0; i < 1000 * flint_test_multiplier(); i++) + { + fmpz_t a, b, c; + int aliasing; + + fmpz_init(a); + fmpz_init(b); + fmpz_init(c); + + fmpz_randtest(a, state, 32); + + aliasing = n_randint(state, 2); + + /* The reference result */ + _fmpz_sum_divisors_naive(c, a); + + /* general function */ + if (aliasing == 1) + { + fmpz_sum_divisors(a, a); + fmpz_set(b, a); + } + else + { + fmpz_sum_divisors(b, a); + } + + result = (fmpz_cmp(c, b) == 0); + + if (!result) + { + flint_printf("FAIL:\n"); + + flint_printf("Expected: "); + fmpz_print(c); + flint_printf("\n"); + + flint_printf("Actual: "); + fmpz_print(b); + flint_printf("\n"); + + fflush(stdout); + flint_abort(); + } + + fmpz_clear(a); + fmpz_clear(b); + fmpz_clear(c); + } + + TEST_FUNCTION_END(state); +} From 0f8c263e703c74e769ebfa584d6aaed6d4d41336 Mon Sep 17 00:00:00 2001 From: Matthias Gessinger Date: Sat, 6 Jul 2024 09:18:47 +0200 Subject: [PATCH 5/9] Add documentation --- doc/source/fmpz.rst | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/doc/source/fmpz.rst b/doc/source/fmpz.rst index fdae8a70cc..2732961a13 100644 --- a/doc/source/fmpz.rst +++ b/doc/source/fmpz.rst @@ -959,6 +959,29 @@ Basic arithmetic Assumes that `m \neq 0`, raises an ``abort`` signal otherwise. +.. function:: void fmpz_sum_powers_horner(fmpz_t f, const fmpz_t g, ulong e) + +.. function:: void fmpz_sum_powers_div(fmpz_t f, const fmpz_t g, ulong e) + +.. function:: void fmpz_sum_powers(fmpz_t f, const fmpz_t g, ulong e) + + Sets `f` to the sum of powers of g, starting at `g^0 = 1` up to and + including `p^e`. + + The `horner` method uses a horner-style method to evaluate the sum. + + The `div` method uses polynomial division to evaluate the sum with a + single exponentiation and a single division. + +.. function:: void fmpz_sum_divisors(fmpz_t f, const fmpz_t g) + + Sets `f` to the sum of divisors of `g`, including 1 and `g` itself. + +.. function:: void fmpz_sum_divisors_proper(fmpz_t f, const fmpz_t g) + + Sets `f` to the sum of proper divisors of `g`, including 1 but excluding + `g` itself. + .. function:: slong fmpz_clog(const fmpz_t x, const fmpz_t b) slong fmpz_clog_ui(const fmpz_t x, ulong b) From 7d627bbb1f3982dd83f6fdb511461740563fc15a Mon Sep 17 00:00:00 2001 From: Matthias Gessinger Date: Sat, 6 Jul 2024 09:40:19 +0200 Subject: [PATCH 6/9] Add example program to compute aliquot sequence --- AUTHORS | 2 ++ examples/aliquot.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 examples/aliquot.c diff --git a/AUTHORS b/AUTHORS index 9da22903ae..484cf66ca2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -446,6 +446,8 @@ David Berghaus Matthias Gessinger Graeffe transforms. + Sums of powers and sums of divisors of integers. + Aliquot sequences. Erik Postma diff --git a/examples/aliquot.c b/examples/aliquot.c new file mode 100644 index 0000000000..53229bd8b5 --- /dev/null +++ b/examples/aliquot.c @@ -0,0 +1,47 @@ +/* + Copyright (C) 2024 Matthias Gessinger + + 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 . +*/ + +#include +#include + +int +main(int argc, char * argv[]) +{ + fmpz_t n; + ulong num_iterations = 0; + + fmpz_init_set_si(n, 138); + + flint_printf("Computing aliquot sequence\n"); + flint_printf("%3wu : ", 0); + fmpz_print(n); + flint_printf("\n"); + + TIMEIT_ONCE_START + + while (!fmpz_is_one(n)) + { + fmpz_sum_divisors_proper(n, n); + num_iterations++; + + flint_printf("%3wu : ", num_iterations); + fmpz_print(n); + flint_printf("\n"); + } + + flint_printf("Sequence terminated after %wu iterations.\n", num_iterations); + + TIMEIT_ONCE_STOP + SHOW_MEMORY_USAGE + + fmpz_clear(n); + return 0; +} From 639dfd9255f63a4e8ba769a88a0b23b254eaff29 Mon Sep 17 00:00:00 2001 From: Matthias Gessinger Date: Sat, 6 Jul 2024 09:48:36 +0200 Subject: [PATCH 7/9] Fix formatting --- examples/aliquot.c | 42 ++++++------ src/fmpz/sum_divisors.c | 10 +-- src/fmpz/test/t-sum_powers.c | 102 ++++++++++++++-------------- src/fmpz/test/t-sum_powers_div.c | 102 ++++++++++++++-------------- src/fmpz/test/t-sum_powers_horner.c | 102 ++++++++++++++-------------- 5 files changed, 179 insertions(+), 179 deletions(-) diff --git a/examples/aliquot.c b/examples/aliquot.c index 53229bd8b5..c467591319 100644 --- a/examples/aliquot.c +++ b/examples/aliquot.c @@ -15,33 +15,33 @@ int main(int argc, char * argv[]) { - fmpz_t n; - ulong num_iterations = 0; + fmpz_t n; + ulong num_iterations = 0; - fmpz_init_set_si(n, 138); + fmpz_init_set_si(n, 138); - flint_printf("Computing aliquot sequence\n"); - flint_printf("%3wu : ", 0); - fmpz_print(n); - flint_printf("\n"); + flint_printf("Computing aliquot sequence\n"); + flint_printf("%3wu : ", 0); + fmpz_print(n); + flint_printf("\n"); - TIMEIT_ONCE_START + TIMEIT_ONCE_START - while (!fmpz_is_one(n)) - { - fmpz_sum_divisors_proper(n, n); - num_iterations++; + while (!fmpz_is_one(n)) + { + fmpz_sum_divisors_proper(n, n); + num_iterations++; - flint_printf("%3wu : ", num_iterations); - fmpz_print(n); - flint_printf("\n"); - } + flint_printf("%3wu : ", num_iterations); + fmpz_print(n); + flint_printf("\n"); + } - flint_printf("Sequence terminated after %wu iterations.\n", num_iterations); + flint_printf("Sequence terminated after %wu iterations.\n", num_iterations); - TIMEIT_ONCE_STOP - SHOW_MEMORY_USAGE + TIMEIT_ONCE_STOP + SHOW_MEMORY_USAGE - fmpz_clear(n); - return 0; + fmpz_clear(n); + return 0; } diff --git a/src/fmpz/sum_divisors.c b/src/fmpz/sum_divisors.c index c3465f91d3..de286e302d 100644 --- a/src/fmpz/sum_divisors.c +++ b/src/fmpz/sum_divisors.c @@ -64,12 +64,12 @@ fmpz_sum_divisors(fmpz_t f, const fmpz_t g) void fmpz_sum_divisors_proper(fmpz_t f, const fmpz_t g) { - fmpz_t temp; - fmpz_init(temp); + fmpz_t temp; + fmpz_init(temp); - fmpz_sum_divisors(temp, g); + fmpz_sum_divisors(temp, g); - fmpz_sub(f, temp, g); + fmpz_sub(f, temp, g); - fmpz_clear(temp); + fmpz_clear(temp); } diff --git a/src/fmpz/test/t-sum_powers.c b/src/fmpz/test/t-sum_powers.c index 7d23402ccb..fcb3accde6 100644 --- a/src/fmpz/test/t-sum_powers.c +++ b/src/fmpz/test/t-sum_powers.c @@ -15,76 +15,76 @@ void _fmpz_sum_powers_naive(fmpz_t f, const fmpz_t g, ulong exp) { - fmpz_t t; - fmpz_init(t); + fmpz_t t; + fmpz_init(t); - fmpz_zero(f); + fmpz_zero(f); - for (ulong i = 0; i <= exp; i++) - { - fmpz_pow_ui(t, g, i); - fmpz_add(f, f, t); - } + for (ulong i = 0; i <= exp; i++) + { + fmpz_pow_ui(t, g, i); + fmpz_add(f, f, t); + } - fmpz_clear(t); + fmpz_clear(t); } TEST_FUNCTION_START(fmpz_sum_powers, state) { - int i, result; + int i, result; - for (i = 0; i < 1000 * flint_test_multiplier(); i++) - { - fmpz_t a, b, c; - ulong exp; - int aliasing; + for (i = 0; i < 1000 * flint_test_multiplier(); i++) + { + fmpz_t a, b, c; + ulong exp; + int aliasing; - fmpz_init(a); - fmpz_init(b); - fmpz_init(c); + fmpz_init(a); + fmpz_init(b); + fmpz_init(c); - fmpz_randtest(a, state, 100); + fmpz_randtest(a, state, 100); - exp = n_randint(state, 250); + exp = n_randint(state, 250); - aliasing = n_randint(state, 2); + aliasing = n_randint(state, 2); - /* The reference result */ - _fmpz_sum_powers_naive(c, a, exp); + /* The reference result */ + _fmpz_sum_powers_naive(c, a, exp); - /* general function */ - if (aliasing == 1) - { - fmpz_sum_powers(a, a, exp); - fmpz_set(b, a); - } - else - { - fmpz_sum_powers(b, a, exp); - } + /* general function */ + if (aliasing == 1) + { + fmpz_sum_powers(a, a, exp); + fmpz_set(b, a); + } + else + { + fmpz_sum_powers(b, a, exp); + } - result = (fmpz_cmp(c, b) == 0); + result = (fmpz_cmp(c, b) == 0); - if (!result) - { - flint_printf("FAIL in general method:\n"); + if (!result) + { + flint_printf("FAIL:\n"); - flint_printf("Expected: "); - fmpz_print(c); - flint_printf("\n"); + flint_printf("Expected: "); + fmpz_print(c); + flint_printf("\n"); - flint_printf("Actual: "); - fmpz_print(b); - flint_printf("\n"); + flint_printf("Actual: "); + fmpz_print(b); + flint_printf("\n"); - fflush(stdout); - flint_abort(); - } + fflush(stdout); + flint_abort(); + } - fmpz_clear(a); - fmpz_clear(b); - fmpz_clear(c); - } + fmpz_clear(a); + fmpz_clear(b); + fmpz_clear(c); + } - TEST_FUNCTION_END(state); + TEST_FUNCTION_END(state); } diff --git a/src/fmpz/test/t-sum_powers_div.c b/src/fmpz/test/t-sum_powers_div.c index 79c1df8f76..38e1728888 100644 --- a/src/fmpz/test/t-sum_powers_div.c +++ b/src/fmpz/test/t-sum_powers_div.c @@ -15,76 +15,76 @@ void _fmpz_sum_powers_naive_div(fmpz_t f, const fmpz_t g, ulong exp) { - fmpz_t t; - fmpz_init(t); + fmpz_t t; + fmpz_init(t); - fmpz_zero(f); + fmpz_zero(f); - for (ulong i = 0; i <= exp; i++) - { - fmpz_pow_ui(t, g, i); - fmpz_add(f, f, t); - } + for (ulong i = 0; i <= exp; i++) + { + fmpz_pow_ui(t, g, i); + fmpz_add(f, f, t); + } - fmpz_clear(t); + fmpz_clear(t); } TEST_FUNCTION_START(fmpz_sum_powers_div, state) { - int i, result; + int i, result; - for (i = 0; i < 1000 * flint_test_multiplier(); i++) - { - fmpz_t a, b, c; - ulong exp; - int aliasing; + for (i = 0; i < 1000 * flint_test_multiplier(); i++) + { + fmpz_t a, b, c; + ulong exp; + int aliasing; - fmpz_init(a); - fmpz_init(b); - fmpz_init(c); + fmpz_init(a); + fmpz_init(b); + fmpz_init(c); - fmpz_randtest(a, state, 100); + fmpz_randtest(a, state, 100); - exp = n_randint(state, 250); + exp = n_randint(state, 250); - aliasing = n_randint(state, 2); + aliasing = n_randint(state, 2); - /* The reference result */ - _fmpz_sum_powers_naive_div(c, a, exp); + /* The reference result */ + _fmpz_sum_powers_naive_div(c, a, exp); - /* polynomial division method */ - if (aliasing == 1) - { - fmpz_sum_powers_div(a, a, exp); - fmpz_set(b, a); - } - else - { - fmpz_sum_powers_div(b, a, exp); - } + /* polynomial division method */ + if (aliasing == 1) + { + fmpz_sum_powers_div(a, a, exp); + fmpz_set(b, a); + } + else + { + fmpz_sum_powers_div(b, a, exp); + } - result = (fmpz_cmp(c, b) == 0); + result = (fmpz_cmp(c, b) == 0); - if (!result) - { - flint_printf("FAIL in polynomial division method:\n"); + if (!result) + { + flint_printf("FAIL:\n"); - flint_printf("Expected: "); - fmpz_print(c); - flint_printf("\n"); + flint_printf("Expected: "); + fmpz_print(c); + flint_printf("\n"); - flint_printf("Actual: "); - fmpz_print(b); - flint_printf("\n"); + flint_printf("Actual: "); + fmpz_print(b); + flint_printf("\n"); - fflush(stdout); - flint_abort(); - } + fflush(stdout); + flint_abort(); + } - fmpz_clear(a); - fmpz_clear(b); - fmpz_clear(c); - } + fmpz_clear(a); + fmpz_clear(b); + fmpz_clear(c); + } - TEST_FUNCTION_END(state); + TEST_FUNCTION_END(state); } diff --git a/src/fmpz/test/t-sum_powers_horner.c b/src/fmpz/test/t-sum_powers_horner.c index 7d39f0c70d..8a61de4d77 100644 --- a/src/fmpz/test/t-sum_powers_horner.c +++ b/src/fmpz/test/t-sum_powers_horner.c @@ -15,76 +15,76 @@ void _fmpz_sum_powers_naive_horner(fmpz_t f, const fmpz_t g, ulong exp) { - fmpz_t t; - fmpz_init(t); + fmpz_t t; + fmpz_init(t); - fmpz_zero(f); + fmpz_zero(f); - for (ulong i = 0; i <= exp; i++) - { - fmpz_pow_ui(t, g, i); - fmpz_add(f, f, t); - } + for (ulong i = 0; i <= exp; i++) + { + fmpz_pow_ui(t, g, i); + fmpz_add(f, f, t); + } - fmpz_clear(t); + fmpz_clear(t); } TEST_FUNCTION_START(fmpz_sum_powers_horner, state) { - int i, result; + int i, result; - for (i = 0; i < 1000 * flint_test_multiplier(); i++) - { - fmpz_t a, b, c; - ulong exp; - int aliasing; + for (i = 0; i < 1000 * flint_test_multiplier(); i++) + { + fmpz_t a, b, c; + ulong exp; + int aliasing; - fmpz_init(a); - fmpz_init(b); - fmpz_init(c); + fmpz_init(a); + fmpz_init(b); + fmpz_init(c); - fmpz_randtest(a, state, 100); + fmpz_randtest(a, state, 100); - exp = n_randint(state, 250); + exp = n_randint(state, 250); - aliasing = n_randint(state, 2); + aliasing = n_randint(state, 2); - /* The reference result */ - _fmpz_sum_powers_naive_horner(c, a, exp); + /* The reference result */ + _fmpz_sum_powers_naive_horner(c, a, exp); - /* Horner-style evaluation */ - if (aliasing == 1) - { - fmpz_sum_powers_horner(a, a, exp); - fmpz_set(b, a); - } - else - { - fmpz_sum_powers_horner(b, a, exp); - } + /* Horner-style evaluation */ + if (aliasing == 1) + { + fmpz_sum_powers_horner(a, a, exp); + fmpz_set(b, a); + } + else + { + fmpz_sum_powers_horner(b, a, exp); + } - result = (fmpz_cmp(c, b) == 0); + result = (fmpz_cmp(c, b) == 0); - if (!result) - { - flint_printf("FAIL in horner evaluation:\n"); + if (!result) + { + flint_printf("FAIL:\n"); - flint_printf("Expected: "); - fmpz_print(c); - flint_printf("\n"); + flint_printf("Expected: "); + fmpz_print(c); + flint_printf("\n"); - flint_printf("Actual: "); - fmpz_print(b); - flint_printf("\n"); + flint_printf("Actual: "); + fmpz_print(b); + flint_printf("\n"); - fflush(stdout); - flint_abort(); - } + fflush(stdout); + flint_abort(); + } - fmpz_clear(a); - fmpz_clear(b); - fmpz_clear(c); - } + fmpz_clear(a); + fmpz_clear(b); + fmpz_clear(c); + } - TEST_FUNCTION_END(state); + TEST_FUNCTION_END(state); } From 92c40aba3977889e12970a02beb016d15ad869f3 Mon Sep 17 00:00:00 2001 From: Matthias Gessinger Date: Sat, 6 Jul 2024 13:30:00 +0200 Subject: [PATCH 8/9] Style fixes --- doc/source/fmpz.rst | 5 +++-- src/fmpz/test/main.c | 18 +++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/doc/source/fmpz.rst b/doc/source/fmpz.rst index 2732961a13..34e06f3f5f 100644 --- a/doc/source/fmpz.rst +++ b/doc/source/fmpz.rst @@ -965,10 +965,11 @@ Basic arithmetic .. function:: void fmpz_sum_powers(fmpz_t f, const fmpz_t g, ulong e) - Sets `f` to the sum of powers of g, starting at `g^0 = 1` up to and + Sets `f` to the sum of powers of `g`, starting at `g^0 = 1` up to and including `p^e`. - The `horner` method uses a horner-style method to evaluate the sum. + The `horner` method uses a horner-style method to evaluate the sum + iteratively. The `div` method uses polynomial division to evaluate the sum with a single exponentiation and a single division. diff --git a/src/fmpz/test/main.c b/src/fmpz/test/main.c index c6a4b8b0a4..09b0569e11 100644 --- a/src/fmpz/test/main.c +++ b/src/fmpz/test/main.c @@ -176,6 +176,10 @@ #include "t-submul.c" #include "t-submul_si.c" #include "t-submul_ui.c" +#include "t-sum_powers_horner.c" +#include "t-sum_powers_div.c" +#include "t-sum_powers.c" +#include "t-sum_divisors.c" #include "t-swap.c" #include "t-tdiv_q_2exp.c" #include "t-tdiv_q.c" @@ -190,10 +194,6 @@ #include "t-xgcd_canonical_bezout.c" #include "t-xgcd_partial.c" #include "t-xor.c" -#include "t-sum_powers_horner.c" -#include "t-sum_powers_div.c" -#include "t-sum_powers.c" -#include "t-sum_divisors.c" /* Array of test functions ***************************************************/ @@ -350,6 +350,10 @@ test_struct tests[] = TEST_FUNCTION(fmpz_submul), TEST_FUNCTION(fmpz_submul_si), TEST_FUNCTION(fmpz_submul_ui), + TEST_FUNCTION(fmpz_sum_powers_horner), + TEST_FUNCTION(fmpz_sum_powers_div), + TEST_FUNCTION(fmpz_sum_powers), + TEST_FUNCTION(fmpz_sum_divisors), TEST_FUNCTION(fmpz_swap), TEST_FUNCTION(fmpz_tdiv_q_2exp), TEST_FUNCTION(fmpz_tdiv_q), @@ -363,11 +367,7 @@ test_struct tests[] = TEST_FUNCTION(fmpz_xgcd), TEST_FUNCTION(fmpz_xgcd_canonical_bezout), TEST_FUNCTION(fmpz_xgcd_partial), - TEST_FUNCTION(fmpz_xor), - TEST_FUNCTION(fmpz_sum_powers_horner), - TEST_FUNCTION(fmpz_sum_powers_div), - TEST_FUNCTION(fmpz_sum_powers), - TEST_FUNCTION(fmpz_sum_divisors) + TEST_FUNCTION(fmpz_xor) }; /* main function *************************************************************/ From dd7748386948a99d5fea8efd93048640263226d9 Mon Sep 17 00:00:00 2001 From: Matthias Gessinger Date: Sat, 6 Jul 2024 14:44:17 +0200 Subject: [PATCH 9/9] Fix formatting and check example Add aliquot example in check_examples.sh Fix indentation to use spaces instead of tabs Fix test failure to use TEST_FUNCTION_FAIL macro --- dev/check_examples.sh | 17 +++ doc/source/fmpz.rst | 6 +- src/fmpz/sum_divisors.c | 2 +- src/fmpz/test/t-sum_divisors.c | 188 +++++++++++++--------------- src/fmpz/test/t-sum_powers.c | 16 +-- src/fmpz/test/t-sum_powers_div.c | 16 +-- src/fmpz/test/t-sum_powers_horner.c | 16 +-- 7 files changed, 122 insertions(+), 139 deletions(-) diff --git a/dev/check_examples.sh b/dev/check_examples.sh index 356c348ddc..418f2d2cfc 100755 --- a/dev/check_examples.sh +++ b/dev/check_examples.sh @@ -298,6 +298,23 @@ then fi echo "PASS" exit 0 +elif test "$1" = "aliquot"; +then + echo -n "aliquot...." + res=$($2/aliquot) + if test "$?" != "0"; + then + echo "FAIL" + exit 1 + fi + echo "$res" | perl -0ne 'if (/\b117 : 179931895322\b/) { $found=1; last } END { exit !$found }' + if test "$?" != "0"; + then + echo "FAIL" + exit 2 + fi + echo "PASS" + exit 0 else exit 3 fi diff --git a/doc/source/fmpz.rst b/doc/source/fmpz.rst index 34e06f3f5f..45d8530ad8 100644 --- a/doc/source/fmpz.rst +++ b/doc/source/fmpz.rst @@ -960,10 +960,8 @@ Basic arithmetic Assumes that `m \neq 0`, raises an ``abort`` signal otherwise. .. function:: void fmpz_sum_powers_horner(fmpz_t f, const fmpz_t g, ulong e) - -.. function:: void fmpz_sum_powers_div(fmpz_t f, const fmpz_t g, ulong e) - -.. function:: void fmpz_sum_powers(fmpz_t f, const fmpz_t g, ulong e) + void fmpz_sum_powers_div(fmpz_t f, const fmpz_t g, ulong e) + void fmpz_sum_powers(fmpz_t f, const fmpz_t g, ulong e) Sets `f` to the sum of powers of `g`, starting at `g^0 = 1` up to and including `p^e`. diff --git a/src/fmpz/sum_divisors.c b/src/fmpz/sum_divisors.c index de286e302d..defe88e3be 100644 --- a/src/fmpz/sum_divisors.c +++ b/src/fmpz/sum_divisors.c @@ -18,7 +18,7 @@ fmpz_sum_divisors(fmpz_t f, const fmpz_t g) fmpz_factor_t factors; fmpz * temp; ulong exp; - ulong i; + slong i; fmpz * p; diff --git a/src/fmpz/test/t-sum_divisors.c b/src/fmpz/test/t-sum_divisors.c index 536d2f613a..073406c32a 100644 --- a/src/fmpz/test/t-sum_divisors.c +++ b/src/fmpz/test/t-sum_divisors.c @@ -15,106 +15,98 @@ void _fmpz_sum_divisors_naive(fmpz_t f, fmpz_t g) { - fmpz_t sqrt, temp1, temp2, temp3, out; - - fmpz_init(sqrt); - fmpz_init(temp1); - fmpz_init(temp2); - fmpz_init(temp3); - fmpz_init(out); - - int is_neg = fmpz_cmp_ui(g, 0) < 1; - - fmpz_abs(f, g); - fmpz_sqrt(sqrt, f); - - fmpz_set_si(temp1, 1); - while (fmpz_cmp(temp1, sqrt) != 1) - { - fmpz_tdiv_qr(temp3, temp2, f, temp1); - - if (fmpz_is_zero(temp2)) - { - fmpz_add(out, out, temp3); - - if (fmpz_cmp(temp1, temp3) != 0) - { - fmpz_add(out, out, temp1); - } - } - - fmpz_add_si(temp1, temp1, 1); - } - - if (is_neg) - { - fmpz_neg(f, out); - } - else - { - fmpz_set(f, out); - } - - fmpz_clear(out); - fmpz_clear(temp1); - fmpz_clear(temp2); - fmpz_clear(temp3); - fmpz_clear(sqrt); + fmpz_t sqrt, temp1, temp2, temp3, out; + + fmpz_init(sqrt); + fmpz_init(temp1); + fmpz_init(temp2); + fmpz_init(temp3); + fmpz_init(out); + + int is_neg = fmpz_cmp_ui(g, 0) < 1; + + fmpz_abs(f, g); + fmpz_sqrt(sqrt, f); + + fmpz_set_si(temp1, 1); + while (fmpz_cmp(temp1, sqrt) != 1) + { + fmpz_tdiv_qr(temp3, temp2, f, temp1); + + if (fmpz_is_zero(temp2)) + { + fmpz_add(out, out, temp3); + + if (fmpz_cmp(temp1, temp3) != 0) + { + fmpz_add(out, out, temp1); + } + } + + fmpz_add_si(temp1, temp1, 1); + } + + if (is_neg) + { + fmpz_neg(f, out); + } + else + { + fmpz_set(f, out); + } + + fmpz_clear(out); + fmpz_clear(temp1); + fmpz_clear(temp2); + fmpz_clear(temp3); + fmpz_clear(sqrt); } TEST_FUNCTION_START(fmpz_sum_divisors, state) { - int i, result; - - for (i = 0; i < 1000 * flint_test_multiplier(); i++) - { - fmpz_t a, b, c; - int aliasing; - - fmpz_init(a); - fmpz_init(b); - fmpz_init(c); - - fmpz_randtest(a, state, 32); - - aliasing = n_randint(state, 2); - - /* The reference result */ - _fmpz_sum_divisors_naive(c, a); - - /* general function */ - if (aliasing == 1) - { - fmpz_sum_divisors(a, a); - fmpz_set(b, a); - } - else - { - fmpz_sum_divisors(b, a); - } - - result = (fmpz_cmp(c, b) == 0); - - if (!result) - { - flint_printf("FAIL:\n"); - - flint_printf("Expected: "); - fmpz_print(c); - flint_printf("\n"); - - flint_printf("Actual: "); - fmpz_print(b); - flint_printf("\n"); - - fflush(stdout); - flint_abort(); - } - - fmpz_clear(a); - fmpz_clear(b); - fmpz_clear(c); - } - - TEST_FUNCTION_END(state); + int i, result; + + for (i = 0; i < 1000 * flint_test_multiplier(); i++) + { + fmpz_t a, b, c; + int aliasing; + + fmpz_init(a); + fmpz_init(b); + fmpz_init(c); + + fmpz_randtest(a, state, 32); + + aliasing = n_randint(state, 2); + + /* The reference result */ + _fmpz_sum_divisors_naive(c, a); + + /* general function */ + if (aliasing == 1) + { + fmpz_sum_divisors(a, a); + fmpz_set(b, a); + } + else + { + fmpz_sum_divisors(b, a); + } + + result = (fmpz_cmp(c, b) == 0); + + if (!result) + { + TEST_FUNCTION_FAIL( + "Expected: %{fmpz}\n" + "Got: %{fmpz}\n", + c, b); + } + + fmpz_clear(a); + fmpz_clear(b); + fmpz_clear(c); + } + + TEST_FUNCTION_END(state); } diff --git a/src/fmpz/test/t-sum_powers.c b/src/fmpz/test/t-sum_powers.c index fcb3accde6..30d651ca93 100644 --- a/src/fmpz/test/t-sum_powers.c +++ b/src/fmpz/test/t-sum_powers.c @@ -67,18 +67,10 @@ TEST_FUNCTION_START(fmpz_sum_powers, state) if (!result) { - flint_printf("FAIL:\n"); - - flint_printf("Expected: "); - fmpz_print(c); - flint_printf("\n"); - - flint_printf("Actual: "); - fmpz_print(b); - flint_printf("\n"); - - fflush(stdout); - flint_abort(); + TEST_FUNCTION_FAIL( + "Expected: %{fmpz}\n" + "Got: %{fmpz}\n", + c, b); } fmpz_clear(a); diff --git a/src/fmpz/test/t-sum_powers_div.c b/src/fmpz/test/t-sum_powers_div.c index 38e1728888..b4cee271f8 100644 --- a/src/fmpz/test/t-sum_powers_div.c +++ b/src/fmpz/test/t-sum_powers_div.c @@ -67,18 +67,10 @@ TEST_FUNCTION_START(fmpz_sum_powers_div, state) if (!result) { - flint_printf("FAIL:\n"); - - flint_printf("Expected: "); - fmpz_print(c); - flint_printf("\n"); - - flint_printf("Actual: "); - fmpz_print(b); - flint_printf("\n"); - - fflush(stdout); - flint_abort(); + TEST_FUNCTION_FAIL( + "Expected: %{fmpz}\n" + "Got: %{fmpz}\n", + c, b); } fmpz_clear(a); diff --git a/src/fmpz/test/t-sum_powers_horner.c b/src/fmpz/test/t-sum_powers_horner.c index 8a61de4d77..53fda5cc33 100644 --- a/src/fmpz/test/t-sum_powers_horner.c +++ b/src/fmpz/test/t-sum_powers_horner.c @@ -67,18 +67,10 @@ TEST_FUNCTION_START(fmpz_sum_powers_horner, state) if (!result) { - flint_printf("FAIL:\n"); - - flint_printf("Expected: "); - fmpz_print(c); - flint_printf("\n"); - - flint_printf("Actual: "); - fmpz_print(b); - flint_printf("\n"); - - fflush(stdout); - flint_abort(); + TEST_FUNCTION_FAIL( + "Expected: %{fmpz}\n" + "Got: %{fmpz}\n", + c, b); } fmpz_clear(a);