Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

arb_get_str() & arb_set_str() does not preserve value #2208

Open
saraedum opened this issue Mar 31, 2022 · 9 comments
Open

arb_get_str() & arb_set_str() does not preserve value #2208

saraedum opened this issue Mar 31, 2022 · 9 comments

Comments

@saraedum
Copy link
Member

saraedum commented Mar 31, 2022

Consider the following C program.

$ cat roundtrip.c
#include <arb.h>

int main() {
  arb_t a;
  arb_init(a);

  arb_load_str(a, "2bb573849d73 -2c 800031b 365d");

  arb_printn(a, 1024, ARB_STR_MORE);

  arb_set_str(a, arb_get_str(a, 1024, ARB_STR_MORE), 1024);

  arb_printn(a, 1024, ARB_STR_MORE);
}

When run (with Arb 2.22.1 from conda-forge) it prints:

[+/- 3.65e+4197][+/- 3.66e+4197]

I understand that arb_get_str() can introduce imprecision and I also understand that I should probably use arb_dump_str to serialize an arb_t; but shouldn't arb_set_str() preserve the radius?

@albinahlback
Copy link
Collaborator

Neither arb_get_str nor arb_set_str says in their documentation that they preserve the radius. It only states that the old interval is contained in the new interval.

@saraedum
Copy link
Member Author

@albinahlback Thanks, I am aware of that. I am not saying that the implementation breaks the documentation.

@albinahlback
Copy link
Collaborator

Then what is your issue? You asked if arb_set_str preserves the radius, for which I gave an answer.

@saraedum
Copy link
Member Author

saraedum commented Mar 31, 2022

My question was: Shouldn't arb_set_str() try to preserve the radius here?

@saraedum
Copy link
Member Author

Note that this is somewhat related to flintlib/arb#391. In flintlib/arb#391 arb_get_str introduces an error, here arb_set_str introduces an error.

I wonder if both methods could be more careful when it's possible not to introduce any error.

@saraedum saraedum changed the title arb_get_str() & arb_get_str() does not preserve value arb_get_str() & arb_set_str() does not preserve value Mar 31, 2022
@JeffreySarnoff
Copy link

I have been trying to get this right for a while, testing various approaches and they all end like this:

using Serialization, ArbNumerics
using Serialization: serialize_type
using ArbNumerics: @libarb, @libflint

function Serialization.serialize(s::AbstractSerializer, x::ArbFloat)
Serialization.serialize_type(s, typeof(x))
unsafestr = ccall(@libarb(arf_dump_str), Cstring, (Ref{ArbFloat},), x)
len = Int64(ccall(:strlen, Csize_t, (Cstring,), unsafestr)) + 1
write(s.io, len)
unsafe_write(s.io, pointer(unsafestr), len)
ccall(@libflint(flint_free), Cvoid, (Cstring,), unsafestr)
return nothing
end

function Serialization.deserialize(s::AbstractSerializer, ::Type{ArbFloat{P}}) where {P}
len = read(s.io, Int64)::Int64
str = Serialization.deserialize_string(s, Int(len))
# TODO: call arb_load_str to constuct arb_t from str
x = ArbFloat{P}(0)
ccall(@libarb(arf_load_str), Int, (Ref{ArbFloat{P}}, Ref{Cstring}), x, str)
return x
end

low_precision = 53
high_precision = 320

setworkingprecision(low_precision)

arf_val = log(ArbFloat(17))

2.83321334405621608

serialize_buffer = Serializer(IOBuffer())

Serializer{IOBuffer}(IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false,

size=0, maxsize=Inf, ptr=1, mark=-1), 0, IdDict{Any, Any}(),

Int64[], Dict{UInt64, Any}(), 26)

serialize(serialize_buffer, arf_val)

Serializer{IOBuffer}(IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false,

size=82, maxsize=Inf, ptr=83, mark=-1), 3, IdDict{Any, Any}(:ArbNumerics => 2, ArbFloat{64} => 0, :ArbFloat => 1),

Int64[], Dict{UInt64, Any}(), 26)

arf_val_recovered = deserialize(serialize_buffer, typeof(arf_val))
ERROR: EOFError: read end of file

@albinahlback
Copy link
Collaborator

@fredrik-johansson can you transfer this issue to FLINT?

@albinahlback
Copy link
Collaborator

@JeffreySarnoff can you provide a MWE in C for your issue? Also, please use code blocks to format the code.

@albinahlback
Copy link
Collaborator

@saraedum So the issue is that when you use string methods, you convert between a binary and a decimal representation on an inexact ring. This forces a loss of information.

@fredrik-johansson fredrik-johansson transferred this issue from flintlib/arb Jan 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants