comp.lang.ada
 help / color / mirror / Atom feed
* GNAT Community 2020 (20200818-93):   Big_Integer
@ 2023-06-30 19:28 Frank Jørgen Jørgensen
  2023-06-30 21:07 ` Dmitry A. Kazakov
  2023-07-01 12:12 ` Simon Wright
  0 siblings, 2 replies; 4+ messages in thread
From: Frank Jørgen Jørgensen @ 2023-06-30 19:28 UTC (permalink / raw)


Hi

I'm running the below program with GNAT Community 2020 (20200818-93)
on Windows 11 Home.
I have some problems trying to save big numbers to a file - so I noticed this behaviour:
If I open Test.dat in Visual Studio Hex editor,  it seems like this program saves this big number with a different bit pattern each time.
Is that as expected?
I do have some problems reading back the big numbers in my real code.
When I compile I get the warning: "Ada.Numerics.Big_Numbers.Big_Integers"  is an Ada 202x unit.

Frank

--
with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
with Ada.Numerics.Big_Numbers.Big_Integers;

procedure Test is

      B1 : Ada.Numerics.Big_Numbers.Big_Integers.Big_Integer;
      F1 : File_Type;
      S1 : Stream_Access;
   begin
      B1 := 1;

      Ada.Streams.Stream_IO.Create (F1, Out_File, "Test.dat");
      S1 := Ada.Streams.Stream_IO.Stream (F1);
      Ada.Numerics.Big_Numbers.Big_Integers.Big_Integer'Write(S1, B1);
      Ada.Numerics.Big_Numbers.Big_Integers.Big_Integer'Output(S1, B1);
      Ada.Streams.Stream_IO.Close (F1);
end Test;

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: GNAT Community 2020 (20200818-93): Big_Integer
  2023-06-30 19:28 GNAT Community 2020 (20200818-93): Big_Integer Frank Jørgen Jørgensen
@ 2023-06-30 21:07 ` Dmitry A. Kazakov
  2023-07-01 12:12 ` Simon Wright
  1 sibling, 0 replies; 4+ messages in thread
From: Dmitry A. Kazakov @ 2023-06-30 21:07 UTC (permalink / raw)


On 2023-06-30 21:28, Frank Jørgen Jørgensen wrote:

> I'm running the below program with GNAT Community 2020 (20200818-93)
> on Windows 11 Home.
> I have some problems trying to save big numbers to a file - so I noticed this behaviour:
> If I open Test.dat in Visual Studio Hex editor,  it seems like this program saves this big number with a different bit pattern each time.
> Is that as expected?
> I do have some problems reading back the big numbers in my real code.
> When I compile I get the warning: "Ada.Numerics.Big_Numbers.Big_Integers"  is an Ada 202x unit.
> 
> --
> with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
> with Ada.Numerics.Big_Numbers.Big_Integers;
> 
> procedure Test is
> 
>        B1 : Ada.Numerics.Big_Numbers.Big_Integers.Big_Integer;
>        F1 : File_Type;
>        S1 : Stream_Access;
>     begin
>        B1 := 1;
> 
>        Ada.Streams.Stream_IO.Create (F1, Out_File, "Test.dat");
>        S1 := Ada.Streams.Stream_IO.Stream (F1);
>        Ada.Numerics.Big_Numbers.Big_Integers.Big_Integer'Write(S1, B1);
>        Ada.Numerics.Big_Numbers.Big_Integers.Big_Integer'Output(S1, B1);
>        Ada.Streams.Stream_IO.Close (F1);
> end Test;

As a general rule, you should never use predefined implementations of 
stream attributes except for Stream_Element or Character. Anything else 
you must always override or else not use.

If you want to serialize signed integers use some portable format for 
it. E.g. a chained encoding.

Here is a test program for a straightforward implementation of chained 
store/restore:
-------------------------
with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
with Ada.Numerics.Big_Numbers.Big_Integers;
with Ada.Exceptions;
with Ada.IO_Exceptions;

procedure Test is

    use Ada.Streams;
    use Ada.Numerics.Big_Numbers.Big_Integers;
    use Ada.Exceptions;
    use Ada.Streams.Stream_IO;

    Two : constant Big_Integer := To_Big_Integer (2);

    package Conversions is new Unsigned_Conversions (Stream_Element);
    use Conversions;

    function Get
             (  Stream : in out Root_Stream_Type'Class
             )  return Big_Integer is
       Result   : Big_Integer;
       Power    : Natural := 6;
       Negative : Boolean;
       Buffer   : Stream_Element_Array (1..1);
       Last     : Stream_Element_Offset;
       This     : Stream_Element renames Buffer (1);
    begin
       Stream.Read (Buffer, Last);
       if Last /= 1 then
          raise End_Error;
       end if;
       Result   := To_Big_Integer ((This and 2#0111_1110#) / 2);
       Negative := 0 /= (This and 1);
       if 0 = (This and 16#80#) then
          if Negative then
             return -Result - 1;
          else
             return Result;
          end if;
       end if;
       loop
          Stream.Read (Buffer, Last);
          if Last /= 1 then
             raise End_Error;
          end if;
          Result := Result +
             Two**Power * To_Big_Integer (This and 16#7F#);
          if 0 = (This and 16#80#) then
             if Negative then
                return -Result - 1;
             else
                return Result;
             end if;
          end if;
          Power := Power + 7;
       end loop;
    end Get;

    procedure Put
              (  Stream : in out Root_Stream_Type'Class;
                 Value  : Big_Integer
              )  is
       Item   : Big_Integer := Value;
       Buffer : Stream_Element_Array (1..1);
       This   : Stream_Element renames Buffer (1);
    begin
       if Item >= 0 then
          Item := Value;
          This := From_Big_Integer (Item mod (16#40#)) * 2;
       else
          Item := -(Value + 1);
          This := From_Big_Integer (Item mod (16#40#)) * 2 + 1;
       end if;
       Item := Item / 16#40#;
       if Item = 0 then
          Stream.Write (Buffer);
          return;
       end if;
       This := This or 16#80#;
       Stream.Write (Buffer);
       loop
          This := From_Big_Integer (Item mod 16#80#) or 16#80#;
          Item := Item / 16#80#;
          if Item = 0 then
             This := This and 16#7F#;
             Stream.Write (Buffer);
             return;
          end if;
          Stream.Write (Buffer);
       end loop;
    end Put;

    F : File_Type;
begin
    Create (F, Out_File, "Test.dat");
    for I in -1_000_000..1_000_000 loop
       Put (Stream (F).all, To_Big_Integer (I));
    end loop;
    Close (F);
    Open (F, In_File, "Test.dat");
    for I in -1_000_000..1_000_000 loop
       declare
          Value : constant Big_Integer := Get (Stream (F).all);
       begin
          if Value /= To_Big_Integer (I) then
             raise Data_Error;
          end if;
       end;
    end loop;
    Close (F);
end Test;
-------------------------
The above could be optimized to work with buffers rather than 
reading/writing stream octets one by one. It is a long story, but 
normally you would implement some data blocks with the length count on 
top of the stream in order to avoid inefficient octet by octet reading 
and add an error correction layer.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: GNAT Community 2020 (20200818-93):   Big_Integer
  2023-06-30 19:28 GNAT Community 2020 (20200818-93): Big_Integer Frank Jørgen Jørgensen
  2023-06-30 21:07 ` Dmitry A. Kazakov
@ 2023-07-01 12:12 ` Simon Wright
  2023-07-08  2:58   ` Randy Brukardt
  1 sibling, 1 reply; 4+ messages in thread
From: Simon Wright @ 2023-07-01 12:12 UTC (permalink / raw)


Frank Jørgen Jørgensen <fjj@itema.no> writes:

> I'm running the below program with GNAT Community 2020 (20200818-93)
> on Windows 11 Home.
> I have some problems trying to save big numbers to a file - so I
> noticed this behaviour:
> If I open Test.dat in Visual Studio Hex editor, it seems like this
> program saves this big number with a different bit pattern each time.
> Is that as expected?
> I do have some problems reading back the big numbers in my real code.

Looking at the source for Big_Integer[1] I see no trace of streaming
support; what you got streamed was the address of some allocated data
used under the hood to contain the big integer.

I don't know whether the ARM requires/expects Big_Integer to be
streamable, but I think you had every reason to expect it! 

[1] https://github.com/gcc-mirror/gcc/blob/7e904d6c7f252ee947c237ed32dd43b2c248384d/gcc/ada/libgnat/a-nbnbin.ads#L171

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: GNAT Community 2020 (20200818-93):   Big_Integer
  2023-07-01 12:12 ` Simon Wright
@ 2023-07-08  2:58   ` Randy Brukardt
  0 siblings, 0 replies; 4+ messages in thread
From: Randy Brukardt @ 2023-07-08  2:58 UTC (permalink / raw)


"Simon Wright" <simon@pushface.org> wrote in message 
news:lyr0prq19e.fsf@pushface.org...
...
> I don't know whether the ARM requires/expects Big_Integer to be
> streamable, but I think you had every reason to expect it!

See 13.13.1(54/1):

For every subtype S of a language-defined nonlimited specific type T, the 
output generated by S'Output or S'Write shall be readable by S'Input or 
S'Read, respectively. This rule applies across partitions if the 
implementation conforms to the Distributed Systems Annex.

Ada.Numerics.Big_Numbers.Big_Integers.Big_integer surely is a 
language-defined nonlimited specific type, so the above applies. Streaming 
should work, if it doesn't, that's a bug.

                 Randy.


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2023-07-08  2:58 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-30 19:28 GNAT Community 2020 (20200818-93): Big_Integer Frank Jørgen Jørgensen
2023-06-30 21:07 ` Dmitry A. Kazakov
2023-07-01 12:12 ` Simon Wright
2023-07-08  2:58   ` Randy Brukardt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox