• Re: New milestone float formatting [LoL] (Was: Request for comments, No

    From Mild Shock@21:1/5 to Mild Shock on Sun Jul 28 14:38:17 2024
    Further test cases are:

    ?- X is 370370367037037036703703703670 / 123456789012345678901234567890.
    X = 3.0000000000000004.

    ?- X is 0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1.
    X = 0.7999999999999999.

    The first test case doesn't work in SWI-Prolog
    since recently it has improve its realization of
    (/)/2 arithemetic function. While in most Prolog

    systems we should have the above result, since
    neither the division equals 3.0 nor the sum equals
    0.8 when we use floating point numbers, and

    when we convert first to floating point number
    before doing the division. The adaptive algorithm
    is more expensive than just calling num.toPrecision(17).

    It will in mimimum call num.toPrecision(16) and do
    the back conversion, i.e. Number(res). So unparsing
    has a parsing cost. And for critical numbers, it

    has a second unparsing via num.toPrecision(17) cost.
    But I guess we can accept this little slow down.

    Mild Shock schrieb:
    Hi,

    To capture some critical examples of float to string
    conversion I went with this kind of little excess
    precision and had this float to string conversion:

             return shape_number(num.toPrecision(17));

    Which gives this unfortunate result, still in release
    1.2.1 of Dogelog Player for JavaScript seen:

    ?- between(1,10,N), X is (20+N)/10, write(X), nl, fail; true. 2.1000000000000001
    2.2000000000000002
    2.2999999999999998
    2.3999999999999999
    2.5
    2.6000000000000001
    2.7000000000000002
    2.7999999999999998
    2.8999999999999999
    3.0

    One work around is to check whether precision 16 would
    also work. Like this code here:

            let res = num.toPrecision(16);
            if (Number(res) === num) {
                return shape_number(res);
            } else {
                return shape_number(num.toPrecision(17));
            }

    The results are much more eye friendly:

    ?- between(1,10,N), X is (20+N)/10, write(X), nl, fail; true.
    2.1
    2.2
    2.3
    2.4
    2.5
    2.6
    2.7
    2.8
    2.9
    3.0
    true.

    Can we accept this solution? Will it slow down printing?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mild Shock@21:1/5 to Mild Shock on Sun Jul 28 16:42:47 2024
    GNU Prolog seems to still use the non-adaptive
    algorithm with 17 decimal precision. It could
    profit from the adaptive algorithm that arbitrates

    between 16 and 17 decimal precision:

    /* GNU Prolog 1.5.0 */

    ?- X is 0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1.
    X = 0.79999999999999993

    ?- 0.79999999999999993 == 0.7999999999999999.
    Yes

    ?- X is 23/10.
    X = 2.2999999999999998

    ?- 2.2999999999999998 == 2.3.
    Yes

    All discrepancies are not incorrect displays,
    since reparsing decimal numbers shows that they
    hit the same floating point values.

    But 2.3 would be cuter!

    Mild Shock schrieb:

    Further test cases are:

    ?- X is 370370367037037036703703703670 / 123456789012345678901234567890.
    X = 3.0000000000000004.

    ?- X is 0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1.
    X = 0.7999999999999999.

    The first test case doesn't work in SWI-Prolog
    since recently it has improve its realization of
    (/)/2 arithemetic function. While in most Prolog

    systems we should have the above result, since
    neither the division equals 3.0 nor the sum equals
    0.8 when we use floating point numbers, and

    when we convert first to floating point number
    before doing the division. The adaptive algorithm
    is more expensive than just calling num.toPrecision(17).

    It will in mimimum call num.toPrecision(16) and do
    the back conversion, i.e. Number(res). So unparsing
    has a parsing cost. And for critical numbers, it

    has a second unparsing via num.toPrecision(17) cost.
    But I guess we can accept this little slow down.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mild Shock@21:1/5 to Mild Shock on Tue Sep 24 17:20:33 2024
    Here some results on a Lenovo Yoga with
    Windows 11 for xbetween:

    /* SWI-Prolog 9.3.11 */
    ?- time((xbetween1(1,1000000000,_),fail)).
    % 2,000,000,002 inferences, 72.688 CPU in 72.790 seconds (100% CPU,
    27515047 Lips)
    false.

    /* Dogelog Player 1.2.3, WSL2, JDK 21 */
    ?- time((xbetween1(1,1000000000,_),fail)).
    % Time 160451 ms, GC 4 ms, Lips 24929729, Wall 24/09/2024 17:01
    fail.

    Dang, still ca. 2x times slower. But no
    memory problem at all. Prolog specific GC is
    very low, only 4 ms, because the Prolog system
    doesn't allocate some logical variables for

    this example. The extended neck here is semi-det
    builtins, that are already evaluated only using
    native stack and no Prolog stack, when the

    clause is instantiated:

    xbetween1(L, U, N) :- L < U, M is L+1, xbetween1(M, U, N).
    \---- neck ----/

    So overhead in Dogelog compared to SWI-Prolog
    is among the fact that it abandons and creates a choice
    point in every backtracking. Haven't found a way

    yet to elegantly avoid this unecessary effort.

    Mild Shock schrieb:
    Here are two test cases for memory
    management of a Prolog system:

    /* bomb */

    app([], X, X).
    app([X|Y], Z, [X|T]) :- app(Y, Z, T).
    garbage(0, [0]) :- !.
    garbage(N, L) :- M is N-1, garbage(M, R), app(R, R, L).
    foo :- garbage(12,_), foo.

    /* xbetween */
    xbetween1(L, _, L).
    xbetween1(L, U, N) :- L < U, M is L+1, xbetween1(M, U, N).

    They test possibly something different. xbetween does
    not produce a lot of objects during tail recursion,
    it only decrements one integer. The xbetween example

    might be ok, wherea the bomb example might be neverthelesss
    not ok, especially since unlike in the xbetween example,
    the bomb example has also an "intermediate" variables.

    The "intermediate" variable is "_":

    foo :- garbage(12,_), foo.

    The xbetween example has no such variable. All
    variables in the xbetween example are either in
    the head or in the tail recursive call, making

    it a more trivial example than the bomb example.



    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mild Shock@21:1/5 to All on Thu Sep 26 13:22:24 2024
    This became a rather lengthy subproject,
    but still a rewarding one. Here are the
    changes:

    - atom_time/3: Renamed sys_time_atom/3 to
    atom_time/3. Changed signature a little bit,
    this is to format and scan local times.

    - atom_utctime/3: Landed in library(util/spin).
    This is to format and scan local times.

    Can other Prolog systems implement atom_utctime/3
    correctly. SWI-Prolog lacks the mode scan mode,
    and formatting goes wrong:

    /* SWI-Prolog 9.3.11 */
    ?- format_time(atom(X), '%a, %d %b %Y %H:%M:%S', 1725635101.000, posix).
    X = 'Fri, 06 Sep 2024 17:05:01'.

    /* Dogelog Player 1.2.3 */
    ?- atom_utctime(X, '%a, %d %b %Y %H:%M:%S', 1725635101000).
    X = 'Fri, 06 Sep 2024 15:05:01'.

    The above is from a machine without locale 'C'.
    Its not suitable for rfc1123. What does SWI-Prolog
    do, it uses weekday and month names from GMT,

    but otherwise it uses local hours:

    1725635101 Timestamp to Human date [batch convert]
    Supports Unix timestamps in seconds,
    milliseconds, microseconds and nanoseconds.
    Assuming that this timestamp is in seconds:
    GMT: Friday, 6. September 2024 15:05:01
    Your time zone: Freitag, 6. September 2024 17:05:01 GMT+02:00 DST
    Relative: 20 days ago
    https://www.epochconverter.com/

    See also:

    All HTTP date/time stamps MUST be represented in
    Greenwich Mean Time (GMT), without exception. https://datatracker.ietf.org/doc/html/rfc2616#section-3.3.1

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)