diff --git a/doc/source/ca.rst b/doc/source/ca.rst index 31bbe44830..3381dc3463 100644 --- a/doc/source/ca.rst +++ b/doc/source/ca.rst @@ -349,6 +349,11 @@ Special values Sets *res* to Euler's constant `\gamma`. This creates an element of the (transcendental?) number field `\mathbb{Q}(\gamma)`. +.. function:: void ca_tetranacci_constant(ca_t res, ca_ctx_t ctx) + + Sets *res* to the Tetranacci constant `T_t`. This creates an element + of the algebraic number field `\mathbb{Q}(T_t)`. + .. function:: void ca_unknown(ca_t res, ca_ctx_t ctx) Sets *res* to the meta-value *Unknown*. diff --git a/doc/source/fexpr_builtin.rst b/doc/source/fexpr_builtin.rst index 2a45cc7bff..1544bf3a97 100644 --- a/doc/source/fexpr_builtin.rst +++ b/doc/source/fexpr_builtin.rst @@ -326,6 +326,10 @@ Particular numbers ``GoldenRatio`` is the golden ratio `\varphi`. +.. macro:: TetranacciConstant + + ``TetranacciConstant`` is the Tetranacci constant `T_t`. + .. macro:: Euler ``Euler`` is Euler's constant `\gamma`. diff --git a/doc/source/qqbar.rst b/doc/source/qqbar.rst index 547bb04b34..b055271d30 100644 --- a/doc/source/qqbar.rst +++ b/doc/source/qqbar.rst @@ -199,6 +199,10 @@ Special values Sets *res* to the golden ratio `\varphi = \tfrac{1}{2}(\sqrt{5} + 1)`. +.. function:: void qqbar_tetranacci_constant(qqbar_t res) + + Sets *res* to the Tetranacci constant `T_t`. + Input and output ------------------------------------------------------------------------------- @@ -811,7 +815,7 @@ Symbolic expressions and conversion to radicals * Arithmetic operations with algebraic operands * Square roots of algebraic numbers * Powers with algebraic base and exponent an explicit rational number - * NumberI, GoldenRatio, RootOfUnity + * NumberI, GoldenRatio, TetranacciConstant, RootOfUnity * Floor, Ceil, Abs, Sign, Csgn, Conjugate, Re, Im, Max, Min * Trigonometric functions with argument an explicit rational number times Pi * Exponentials with argument an explicit rational number times Pi * NumberI diff --git a/examples/tetranacci.c b/examples/tetranacci.c new file mode 100644 index 0000000000..6756aab92d --- /dev/null +++ b/examples/tetranacci.c @@ -0,0 +1,65 @@ +/* This file is public domain. Author: Raoul Bourquin. */ + +#include +#include "ca.h" + + +void main_fexpr() +{ + fexpr_t T; + fexpr_init(T); + + flint_printf("Evaluating Tt as fexpr:\n"); + + fexpr_set_symbol_str(T, "TetranacciConstant"); + + fexpr_print(T); + printf("\n\n"); + + fexpr_clear(T); +} + + +void main_ca() +{ + ca_ctx_t ctx; + ca_t T; + ca_ctx_init(ctx); + ca_init(T, ctx); + + flint_printf("Evaluating Tt as ca:\n"); + + ca_tetranacci_constant(T, ctx); + + ca_print(T, ctx); + printf("\n\n"); + + ca_clear(T, ctx); +} + + +void main_qqbar() +{ + qqbar_t T; + qqbar_init(T); + + flint_printf("Evaluating Tt as qqbar:\n"); + + qqbar_tetranacci_constant(T); + + qqbar_printn(T, 50); + printf("\n"); + + qqbar_clear(T); +} + + +int main(int argc, char *argv[]) +{ + main_fexpr(); + main_ca(); + main_qqbar(); + + flint_cleanup(); + return EXIT_SUCCESS; +} diff --git a/src/ca.h b/src/ca.h index f9caa499ee..2838f11e91 100644 --- a/src/ca.h +++ b/src/ca.h @@ -314,6 +314,8 @@ void ca_pi(ca_t res, ca_ctx_t ctx); void ca_pi_i(ca_t res, ca_ctx_t ctx); void ca_euler(ca_t res, ca_ctx_t ctx); +void ca_tetranacci_constant(ca_t res, ca_ctx_t ctx); + void ca_unknown(ca_t x, ca_ctx_t ctx); void ca_undefined(ca_t x, ca_ctx_t ctx); diff --git a/src/ca/set_fexpr.c b/src/ca/set_fexpr.c index 69fabc67a9..0057ecbf9e 100644 --- a/src/ca/set_fexpr.c +++ b/src/ca/set_fexpr.c @@ -79,6 +79,9 @@ _ca_set_fexpr(ca_t res, fexpr_vec_t inputs, ca_vec_t outputs, const fexpr_t expr ca_add_ui(res, res, 1, ctx); ca_div_ui(res, res, 2, ctx); return 1; + case FEXPR_TetranacciConstant: + ca_tetranacci_constant(res, ctx); + return 1; case FEXPR_Infinity: ca_pos_inf(res, ctx); return 1; diff --git a/src/ca/tetranacci.c b/src/ca/tetranacci.c new file mode 100644 index 0000000000..1d2793840c --- /dev/null +++ b/src/ca/tetranacci.c @@ -0,0 +1,24 @@ +/* + Copyright (C) 2022 Raoul Bourquin + + This file is part of Calcium. + + Calcium 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 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "ca.h" + +void +ca_tetranacci_constant(ca_t res, ca_ctx_t ctx) +{ + qqbar_t tc; + qqbar_init(tc); + qqbar_tetranacci_constant(tc); + + ca_set_qqbar(res, tc, ctx); + + qqbar_clear(tc); +} diff --git a/src/fexpr/numerical_enclosure.c b/src/fexpr/numerical_enclosure.c index e56d4f4841..92dffa726d 100644 --- a/src/fexpr/numerical_enclosure.c +++ b/src/fexpr/numerical_enclosure.c @@ -129,6 +129,92 @@ fexpr_get_acb_raw(acb_t res, const fexpr_t expr, slong prec) return 1; } + if (op == FEXPR_TetranacciConstant) + { + /* Subexpressions */ + arb_t t1, t2, l1, p1; + + /* Init */ + arb_init(t1); + arb_init(t2); + arb_init(l1); + arb_init(p1); + + /* t1 := 3*sqrt(1689) */ + arb_sqrt_ui(t1, 1689, prec); + arb_mul_ui(t1, t1, 3, prec); + + /* l1 := (cbrt(t1 - 65) - cbrt(t1 + 65)) / (12 * cbrt(2)) */ + arb_zero(l1); + + /* First part of l1 */ + arb_sub_ui(t2, t1, 65, prec); + arb_root_ui(t2, t2, 3, prec); + + arb_add(l1, l1, t2, prec); + + /* Second part of l1 */ + arb_add_ui(t2, t1, 65, prec); + arb_root_ui(t2, t2, 3, prec); + + arb_sub(l1, l1, t2, prec); + + /* Denominator of l1 */ + arb_set_ui(t2, 2); + arb_root_ui(t2, t2, 3, prec); + arb_mul_ui(t2, t2, 12, prec); + + /* Combine l1 */ + arb_div(l1, l1, t2, prec); + + /* p1 := sqrt(l1 + 11/48) */ + arb_set_ui(p1, 11); + arb_div_ui(p1, p1, 48, prec); + + arb_add(p1, p1, l1, prec); + arb_sqrt(p1, p1, prec); + + /* t2 := 1/4 - p1 */ + arb_one(t2); + arb_mul_2exp_si(t2, t2, -2); + arb_add(t2, t2, p1, prec); + + /* Invert p1 */ + arb_inv(p1, p1, prec); + + /* Final result */ + arb_one(acb_realref(res)); + arb_div_ui(acb_realref(res), acb_realref(res), 6, prec); + + arb_set_ui(t1, 7); + arb_div_ui(t1, t1, 24, prec); + arb_mul(t1, t1, p1, prec); + arb_add(acb_realref(res), acb_realref(res), t1, prec); + + arb_sqr(t1, t2, prec); + arb_add(acb_realref(res), acb_realref(res), t1, prec); + + arb_mul_ui(t1, t2, 2, prec); + arb_mul(t1, t1, l1, prec); + arb_mul(t1, t1, p1, prec); + arb_sub(acb_realref(res), acb_realref(res), t1, prec); + + arb_sqrt(acb_realref(res), acb_realref(res), prec); + + arb_add(acb_realref(res), acb_realref(res), t2, prec); + + /* zero imag part */ + arb_zero(acb_imagref(res)); + + /* Free */ + arb_clear(t1); + arb_clear(t2); + arb_clear(l1); + arb_clear(p1); + + return 1; + } + acb_indeterminate(res); return 0; } diff --git a/src/fexpr_builtin.h b/src/fexpr_builtin.h index 307dacf3e7..31f6b729e3 100644 --- a/src/fexpr_builtin.h +++ b/src/fexpr_builtin.h @@ -431,6 +431,7 @@ typedef enum FEXPR_SymmetricPolynomial, FEXPR_Tan, FEXPR_Tanh, + FEXPR_TetranacciConstant, FEXPR_Theta, FEXPR_Theta_, FEXPR_True, diff --git a/src/fexpr_builtin/table.c b/src/fexpr_builtin/table.c index b0546e0fbe..3aa6e3878f 100644 --- a/src/fexpr_builtin/table.c +++ b/src/fexpr_builtin/table.c @@ -413,6 +413,7 @@ const fexpr_symbol_info fexpr_builtin_table[FEXPR_BUILTIN_LENGTH] = { { FEXPR_SymmetricPolynomial, "SymmetricPolynomial", "e", fexpr_write_latex_subscript_call, }, { FEXPR_Tan, "Tan", "\\tan", NULL, }, { FEXPR_Tanh, "Tanh", "\\tanh", NULL, }, + { FEXPR_TetranacciConstant, "TetranacciConstant", "T_t", NULL, }, { FEXPR_Theta, "Theta", "\\Theta", NULL }, { FEXPR_Theta_, "Theta_", "\\Theta", fexpr_write_latex_subscript }, { FEXPR_True, "True", "\\operatorname{True}", NULL, }, diff --git a/src/qqbar.h b/src/qqbar.h index 22c4103b1d..f7766369d2 100644 --- a/src/qqbar.h +++ b/src/qqbar.h @@ -202,6 +202,8 @@ void qqbar_i(qqbar_t res); void qqbar_phi(qqbar_t res); +void qqbar_tetranacci_constant(qqbar_t res); + /* Random generation */ void qqbar_randtest(qqbar_t res, flint_rand_t state, slong deg, slong bits); diff --git a/src/qqbar/set_fexpr.c b/src/qqbar/set_fexpr.c index 957a274f61..1e59da3a04 100644 --- a/src/qqbar/set_fexpr.c +++ b/src/qqbar/set_fexpr.c @@ -609,6 +609,12 @@ qqbar_set_fexpr(qqbar_t res, const fexpr_t expr) return 1; } + if (fexpr_is_builtin_symbol(expr, FEXPR_TetranacciConstant)) + { + qqbar_tetranacci_constant(res); + return 1; + } + return 0; } diff --git a/src/qqbar/tetranacci.c b/src/qqbar/tetranacci.c new file mode 100644 index 0000000000..eb90239a2b --- /dev/null +++ b/src/qqbar/tetranacci.c @@ -0,0 +1,105 @@ +/* + Copyright (C) 2022 Raoul Bourquin + + This file is part of Calcium. + + Calcium 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 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "fmpz_poly.h" +#include "qqbar.h" + +void +qqbar_tetranacci_constant(qqbar_t res) +{ + /* Subexpressions */ + arb_t t1, t2, l1, p1; + + fmpz_poly_zero(QQBAR_POLY(res)); + fmpz_poly_set_coeff_si(QQBAR_POLY(res), 4, 1); + fmpz_poly_set_coeff_si(QQBAR_POLY(res), 3, -1); + fmpz_poly_set_coeff_si(QQBAR_POLY(res), 2, -1); + fmpz_poly_set_coeff_si(QQBAR_POLY(res), 1, -1); + fmpz_poly_set_coeff_si(QQBAR_POLY(res), 0, -1); + + /* Init */ + arb_init(t1); + arb_init(t2); + arb_init(l1); + arb_init(p1); + + /* t1 := 3*sqrt(1689) */ + arb_sqrt_ui(t1, 1689, QQBAR_DEFAULT_PREC); + arb_mul_ui(t1, t1, 3, QQBAR_DEFAULT_PREC); + + /* l1 := (cbrt(t1 - 65) - cbrt(t1 + 65)) / (12 * cbrt(2)) */ + arb_zero(l1); + + /* First part of l1 */ + arb_sub_ui(t2, t1, 65, QQBAR_DEFAULT_PREC); + arb_root_ui(t2, t2, 3, QQBAR_DEFAULT_PREC); + + arb_add(l1, l1, t2, QQBAR_DEFAULT_PREC); + + /* Second part of l1 */ + arb_add_ui(t2, t1, 65, QQBAR_DEFAULT_PREC); + arb_root_ui(t2, t2, 3, QQBAR_DEFAULT_PREC); + + arb_sub(l1, l1, t2, QQBAR_DEFAULT_PREC); + + /* Denominator of l1 */ + arb_set_ui(t2, 2); + arb_root_ui(t2, t2, 3, QQBAR_DEFAULT_PREC); + arb_mul_ui(t2, t2, 12, QQBAR_DEFAULT_PREC); + + /* Combine l1 */ + arb_div(l1, l1, t2, QQBAR_DEFAULT_PREC); + + /* p1 := sqrt(l1 + 11/48) */ + arb_set_ui(p1, 11); + arb_div_ui(p1, p1, 48, QQBAR_DEFAULT_PREC); + + arb_add(p1, p1, l1, QQBAR_DEFAULT_PREC); + arb_sqrt(p1, p1, QQBAR_DEFAULT_PREC); + + /* t2 := 1/4 - p1 */ + arb_one(t2); + arb_mul_2exp_si(t2, t2, -2); + arb_add(t2, t2, p1, QQBAR_DEFAULT_PREC); + + /* Invert p1 */ + arb_inv(p1, p1, QQBAR_DEFAULT_PREC); + + /* Final result */ + arb_one(acb_realref(QQBAR_ENCLOSURE(res))); + arb_div_ui(acb_realref(QQBAR_ENCLOSURE(res)), acb_realref(QQBAR_ENCLOSURE(res)), 6, QQBAR_DEFAULT_PREC); + + arb_set_ui(t1, 7); + arb_div_ui(t1, t1, 24, QQBAR_DEFAULT_PREC); + arb_mul(t1, t1, p1, QQBAR_DEFAULT_PREC); + arb_add(acb_realref(QQBAR_ENCLOSURE(res)), acb_realref(QQBAR_ENCLOSURE(res)), t1, QQBAR_DEFAULT_PREC); + + arb_sqr(t1, t2, QQBAR_DEFAULT_PREC); + arb_add(acb_realref(QQBAR_ENCLOSURE(res)), acb_realref(QQBAR_ENCLOSURE(res)), t1, QQBAR_DEFAULT_PREC); + + arb_mul_ui(t1, t2, 2, QQBAR_DEFAULT_PREC); + arb_mul(t1, t1, l1, QQBAR_DEFAULT_PREC); + arb_mul(t1, t1, p1, QQBAR_DEFAULT_PREC); + arb_sub(acb_realref(QQBAR_ENCLOSURE(res)), acb_realref(QQBAR_ENCLOSURE(res)), t1, QQBAR_DEFAULT_PREC); + + arb_sqrt(acb_realref(QQBAR_ENCLOSURE(res)), acb_realref(QQBAR_ENCLOSURE(res)), QQBAR_DEFAULT_PREC); + + arb_add(acb_realref(QQBAR_ENCLOSURE(res)), acb_realref(QQBAR_ENCLOSURE(res)), t2, QQBAR_DEFAULT_PREC); + + /* zero imag part */ + arb_zero(acb_imagref(QQBAR_ENCLOSURE(res))); + + /* Free */ + arb_clear(t1); + arb_clear(t2); + arb_clear(l1); + arb_clear(p1); +}