# Why the weird summarysize results for Rational{BigInt}

**URL:** <https://discourse.julialang.org/t/why-the-weird-summarysize-results-for-rational-bigint/86704>\
**Category:** General Usage\
**Tags:** rationals\
**Created:** [September 2, 2022, 8:44pm UTC](https://discourse.julialang.org/t/why-the-weird-summarysize-results-for-rational-bigint/86704 "2022-09-02T20:44:28Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [September 2, 2022, 8:44pm UTC](https://discourse.julialang.org/t/why-the-weird-summarysize-results-for-rational-bigint/86704/1 "2022-09-02T20:44:28Z")

</div>

```julia
julia> n = big"3"^100000;

julia> t = (n // 1, n, Rational{BigInt}(n));

julia> typeof(t)
Tuple{Rational{BigInt}, BigInt, Rational{BigInt}}

julia> map(Base.summarysize, t)
(19872, 19968, 20008)

julia> first(t) == last(t)
true

julia> n = big"3"^1000000;

julia> t = (n // 1, n, Rational{BigInt}(n));

julia> map(Base.summarysize, t)
(198184, 199272, 199312)

julia> first(t) == last(t)
true

julia> versioninfo()
Julia Version 1.9.0-DEV.1242
Commit 53bb7fb5df7 (2022-08-31 18:42 UTC)
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 8 × AMD Ryzen 3 5300U with Radeon Graphics
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-14.0.5 (ORCJIT, znver2)
  Threads: 3 on 8 virtual cores

```

When I have a `BigInt`, there’s two methods that come to mind for converting it into a rational:

1. A direct invocation of the `Rational` constructor. This causes the summarysize compared to the original `BigInt` to _increase_.
2. Creating a fraction with one as the denominator. This causes the summarysize to _decrease_ in my examples.

I wonder what could be the reason for the disparity. Something to do with GMP’s allocation strategies? What are the performance implications here?

EDIT: it definitely seems like creating a rational in the second way causes the size of the BigInt numerator to decrease, something which doesn’t happen if I just use `copy` on the BigInt:

```julia
julia> n = big"3"^1000000;

julia> m = n//1;

julia> typeof(m.num)
BigInt

julia> typeof(m.den)
BigInt

julia> map(Base.summarysize, (n, m, m.num))
(199272, 198184, 198144)

```

---

<div class="post-metadata">

**Author:** ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)\
**Post date:** [September 2, 2022, 10:29pm UTC](https://discourse.julialang.org/t/why-the-weird-summarysize-results-for-rational-bigint/86704/2 "2022-09-02T22:29:56Z")

</div>

Here is a clue

```julia
julia> n = big"3"^100000;

julia> n.alloc
2494

julia> Base.GMP.MPZ.set!(BigInt(), n).alloc
2477

julia> copy(n).alloc
2494

```

Note that `copy(n::BigInt)` dispatches to `copy(x::Number) = x`. There must be a reason for this, even though `ismutable(big(1))` is `true`.

EDIT: If you follow the code for `Base.GMP.MPZ.set!` you’ll find that it allocates memory for the target based on the `size` of the source, not the `alloc` of the source:

```julia
julia> n.alloc
2494

julia> n.size
2477

```

```cpp
void
mpz_set (mpz_ptr w, mpz_srcptr u)
{
  mp_ptr wp, up;
  mp_size_t usize, size;

  usize = SIZ(u);
  size = ABS (usize);

  wp = MPZ_NEWALLOC (w, size);

  up = PTR(u);

  MPN_COPY (wp, up, size);
  SIZ(w) = usize;
}

```

EDIT: It’s really here

```julia
julia> Rational(n).num.alloc
2494

julia> Rational(n, 1).num.alloc
2477

```

The two-arg version calls `set`, which as mentioned above, uses `size` rather than `alloc` to determine what to allocate.

And the one-arg version calls `Base.unsafe_rational`, which does no copy at all. The numerator in the rational is the same object as `n`.

---

<div class="post-metadata">

**Author:** ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)\
**Post date:** [September 3, 2022, 4:51am UTC](https://discourse.julialang.org/t/why-the-weird-summarysize-results-for-rational-bigint/86704/3 "2022-09-03T04:51:01Z")

</div>

This seems inconsistent

```julia
julia> n = big(3);

julia> numerator(Rational(n, 1)) === n
false

julia> numerator(Rational(n)) === n
true

julia> real(Complex(n, 0)) === n
true

julia> real(Complex(n)) === n
true

```

Even the behavior for `Rational` alone is inconsistent.  
The expected behavior for the constructors is not documented. I think this should be more predictable.
