Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions doc/source/arb.rst
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,22 @@ Radius and interval operations
in swapping. It is recommended to check that the midpoint of *x* is
within a reasonable range before calling this method.

.. function:: int arb_get_simplest_fmpq(fmpq_t res, const arb_t x)

Sets *res* to the rational `p/q` in lowest terms, with smallest
positive denominator `q`, that lies in the closed real interval
represented by *x*, and returns 1. Among rationals with the smallest
denominator, returns the one with smallest absolute numerator (i.e.
closest to 0); if 0 lies in *x*, returns 0/1.

Returns 0 and leaves *res* unchanged if *x* is not finite.

Warning: like :func:`arb_get_unique_fmpz`, this method may allocate
a large amount of memory when the midpoint or dyadic endpoints of
*x* have very large or very small magnitude. It is recommended to
check that the midpoint of *x* is within a reasonable range before
calling this method.

.. function:: void arb_floor(arb_t y, const arb_t x, slong prec)
void arb_ceil(arb_t y, const arb_t x, slong prec)
void arb_trunc(arb_t y, const arb_t x, slong prec)
Expand Down
1 change: 1 addition & 0 deletions src/arb.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ int arb_contains_int(const arb_t x);

void arb_get_interval_fmpz_2exp(fmpz_t a, fmpz_t b, fmpz_t exp, const arb_t x);
int arb_get_unique_fmpz(fmpz_t z, const arb_t x);
int arb_get_simplest_fmpq(fmpq_t res, const arb_t x);

void arb_get_fmpz_mid_rad_10exp(fmpz_t mid, fmpz_t rad, fmpz_t exp, const arb_t x, slong n);

Expand Down
76 changes: 76 additions & 0 deletions src/arb/get_simplest_fmpq.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
Copyright (C) 2026 Edgar Costa

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 "arb.h"
#include "fmpq.h"

int
arb_get_simplest_fmpq(fmpq_t res, const arb_t x)
{
arf_t lo_arf, hi_arf;
fmpq_t lo, hi;
int negate;

if (!arb_is_finite(x))
return 0;

/* Fast path: exact ball. The midpoint is the only element of the
* interval, so it is trivially the simplest rational. arf is
* dyadic, so arf_get_fmpq produces the canonical form exactly. */
if (arb_is_exact(x))
{
arf_get_fmpq(res, arb_midref(x));
return 1;
}

/* Fast path: 0 lies in the ball. 0/1 has the smallest possible
* denominator and smallest absolute numerator, so it wins both
* sub-criteria. arb_contains_zero is an exact predicate on the
* arf/mag pair, avoiding any fmpq conversion. */
if (arb_contains_zero(x))
{
fmpq_zero(res);
return 1;
}

/* The remaining intervals are strictly positive or strictly
* negative. Reduce to the positive case so that
* fmpq_simplest_between's "smallest value" tie-break agrees with
* our "smallest absolute numerator" contract on the original. */
negate = arb_is_negative(x);

arf_init(lo_arf);
arf_init(hi_arf);
fmpq_init(lo);
fmpq_init(hi);

arb_get_lbound_arf(lo_arf, x, ARF_PREC_EXACT);
arb_get_ubound_arf(hi_arf, x, ARF_PREC_EXACT);
arf_get_fmpq(lo, lo_arf);
arf_get_fmpq(hi, hi_arf);

if (negate)
{
fmpq_neg(lo, lo);
fmpq_neg(hi, hi);
fmpq_swap(lo, hi);
}

fmpq_simplest_between(res, lo, hi);
if (negate)
fmpq_neg(res, res);

arf_clear(lo_arf);
arf_clear(hi_arf);
fmpq_clear(lo);
fmpq_clear(hi);
return 1;
}
2 changes: 2 additions & 0 deletions src/arb/test/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
#include "t-get_mpn_fixed_mod_log2.c"
#include "t-get_mpn_fixed_mod_pi4.c"
#include "t-get_rand_fmpq.c"
#include "t-get_simplest_fmpq.c"
#include "t-get_str.c"
#include "t-get_unique_fmpz.c"
#include "t-hurwitz_zeta.c"
Expand Down Expand Up @@ -328,6 +329,7 @@ test_struct tests[] =
TEST_FUNCTION(arb_get_mpn_fixed_mod_log2),
TEST_FUNCTION(arb_get_mpn_fixed_mod_pi4),
TEST_FUNCTION(arb_get_rand_fmpq),
TEST_FUNCTION(arb_get_simplest_fmpq),
TEST_FUNCTION(arb_get_str),
TEST_FUNCTION(arb_get_unique_fmpz),
TEST_FUNCTION(arb_hurwitz_zeta),
Expand Down
Loading
Loading