Output of Float and issue #159

25 views
Skip to first unread message

Grégory Vanuxem

unread,
Apr 7, 2024, 12:06:19 AM4/7/24
to fricas...@googlegroups.com
Hello,

I was trying to return the previous setting instead of Void for the
different outputting routines in Float (outputFixed, outputGeneral and
outputFloating), so I looked more carefully at this issue.

Issue #159 => https://github.com/fricas/fricas/issues/159

Basically, and more spectacularly that what was expressed in the issue #159:

(1) -> float(17,-1)
(1) 9.0
(2) -> %*2
(2) 17.0
(3) -> float(17,-1,2)
(3) 8.5

Adding PRINT()$Lisp to the two 'float' routines (two or three args) I
saw the difference that leads to this:

(27) -> float(17,-1)
(17 . -1)
(27) 9.0
(28) -> float(17,-1,2)
(156797324626531188736 . -64)
(28) 8.5

And to coerce the Float to OutputForm convert(Float)@String is used.
But with default settings the bits(n)$Float routine is used to change
the precision in bits before performing the transformation to a string
and it uses the mantissa which is for 8.5 (17 . -1) only 5 bits So
when internal output routines do the string coercion digits() returns
1, this explains the rounding done above:

(6) -> )tr Float )ops bits digits

Packages traced:
Float
Parameterized constructors traced:
FLOAT
(6) -> float(17,-1)
1<enter Float.bits,49 :
1>exit Float.bits,49 : 68

1<enter Float.bits,60 : 5
1>exit Float.bits,60 : 68
1<enter Float.digits,91 :
1<enter Float.bits,49 :
1>exit Float.bits,49 : 5
1>exit Float.digits,91 : 1
1<enter Float.bits,49 :
1>exit Float.bits,49 : 5
1<enter Float.bits,60 : 68
1>exit Float.bits,60 : 5
(6) 9.0
Type: Float
(7) -> %*2
1<enter Float.bits,49 :
1>exit Float.bits,49 : 68
1<enter Float.bits,49 :
1>exit Float.bits,49 : 68
1<enter Float.bits,49 :
1>exit Float.bits,49 : 68
1<enter Float.bits,49 :
1>exit Float.bits,49 : 68
1<enter Float.bits,49 :
1>exit Float.bits,49 : 68
1<enter Float.bits,49 :
1>exit Float.bits,49 : 68
1<enter Float.bits,49 :
1>exit Float.bits,49 : 68
[snip]
(7) 17.0
======================

I do not know how that should be solved (output routines or the
convert(Float)@String) but removing the use of 'b' below i.e. don't
touch the precision in bits avoids this easily and show that this
precision modification is not adapted to all Float representations.

convert(f) : S ==
b : Integer :=
OUTPREC = -1 and not zero? f =>
bits(length(abs mantissa f)::PositiveInteger)
0
s :=
OUTMODE = "fixed" => fixed f
OUTMODE = "floating" => floating f
OUTMODE = "general" => general f
empty()$String
if b > 0 then bits(b::PositiveInteger)
s = empty()$String => error "bad output mode"
s

=============================
Another point:

It is possible to modify some parameters to Float output routines,
what about returning the previous settings? For example
outputSpacing(n) returns Void but if you want to temporarily modify
this setting, in Spad for example, reverting to the user setting is
not possible. I attached a proof of concept patch that implements
this. In fact, even the macro 'separator ==> underscore()$Character'
could also be parametrable, it is not in this diff though.

- Greg
float.diff

Waldek Hebisch

unread,
Apr 12, 2024, 11:16:57 PM4/12/24
to fricas...@googlegroups.com
<snip>
> I do not know how that should be solved

I am not sure what do you want to solve? Suppose that 'float(a, b)'
was purely internal and unavailable to users. Would you consider
behaviour of other functions to be a bug?

> Another point:
>
> It is possible to modify some parameters to Float output routines,
> what about returning the previous settings? For example
> outputSpacing(n) returns Void but if you want to temporarily modify
> this setting, in Spad for example, reverting to the user setting is
> not possible. I attached a proof of concept patch that implements
> this. In fact, even the macro 'separator ==> underscore()$Character'
> could also be parametrable, it is not in this diff though.

Such change looks desirable. I will apply the patch after fixing
a few formatting issues.

--
Waldek Hebisch

Grégory Vanuxem

unread,
Apr 13, 2024, 4:18:28 AM4/13/24
to fricas...@googlegroups.com
Hello Waldek,
,
> > And to coerce the Float to OutputForm convert(Float)@String is used.
> > But with default settings the bits(n)$Float routine is used to change
> > the precision in bits before performing the transformation to a string
> > and it uses the mantissa which is for 8.5 (17 . -1) only 5 bits So
> > when internal output routines do the string coercion digits() returns
> > 1, this explains the rounding done above:
> <snip>
> > I do not know how that should be solved
>
> I am not sure what do you want to solve? Suppose that 'float(a, b)'
> was purely internal and unavailable to users. Would you consider
> behaviour of other functions to be a bug?

Yes, I agree, if it was purely internal that would not cause problems.
The main point is that mathematically speaking, not computationally
because of hardware limitations, a floating point number in base 2 can
have probably an infinity of representations, but the output routine
does take into account that. When it use bits/digits to coerce it to
OutputForm it assumes its internal way of representing it, apparently,
that is, the Float domain always uses the three args constructor and
it is not internally similar to what can be done if you use yourself
the two args float constructor. So what I consider problematic is:

(1) -> mantissa 8.5
(1) 156797324626531188736
(2) -> float(17,-1)
(2) 9.0
(3) -> %*2
(3) 17.0
(4) -> mantissa float(17,-1)
(4) 17.
(5) -> float(34,-2)
(5) 9.0
(6) -> %*2
(6) 17.0
(7) -> mantissa float(34,-2)
(7) 34

There was an interesting question of someone about bits used for
floating point numbers in the flint-devel mailing list:
https://groups.google.com/g/flint-devel/c/Qr3YGgQxE2o/m/YDlnWDeRAQAJ?utm_medium=email&utm_source=footer
i.e. the number of bits used to store the mantissa for a given
floating point number. For example, I would not be surprised if the
MPFR library uses 17 as mantissa for 8.5. This is not the way the
Float domain constructs floating point numbers, and, again, I agree
that the two args float constructor, if it was not public, I would not
have seen displayed: 9*2=17 :-)

>
> > Another point:
> >
> > It is possible to modify some parameters to Float output routines,
> > what about returning the previous settings? For example
> > outputSpacing(n) returns Void but if you want to temporarily modify
> > this setting, in Spad for example, reverting to the user setting is
> > not possible. I attached a proof of concept patch that implements
> > this. In fact, even the macro 'separator ==> underscore()$Character'
> > could also be parametrable, it is not in this diff though.
>
> Such change looks desirable. I will apply the patch after fixing
> a few formatting issues.

Ok, thanks, I think so.

Best regards,
- Greg.

Waldek Hebisch

unread,
Apr 13, 2024, 3:05:52 PM4/13/24
to fricas...@googlegroups.com
On Sun, Apr 07, 2024 at 06:05:39AM +0200, Grégory Vanuxem wrote:
>
> It is possible to modify some parameters to Float output routines,
> what about returning the previous settings? For example
> outputSpacing(n) returns Void but if you want to temporarily modify
> this setting, in Spad for example, reverting to the user setting is
> not possible. I attached a proof of concept patch that implements
> this. In fact, even the macro 'separator ==> underscore()$Character'
> could also be parametrable, it is not in this diff though.

Thinking more about this: it should be possible to restore _whole_
previous settings. So probably we need something like:

get_output_mode : () -> Record(mode : String, prec : String)

othewise, after

outputFixed()
n := outputGeneral(12)

we have no clue that previous mode was "fixed". Also, '-1' is
valid as precion, but to set arbitrary valid precision one
would have to use code like

if prec = -1 then
outputFixed()
else
outputFixed(prec::NonNegativeInteger)

And to set desired mode we would need chain of tests. So it seems
that we need funtion

set_output_mode : (Stiring, Integer) -> Record(mode : String, prec : String)

which sets desired mode. I wrote above version that returns old settings,
but in principle version that returns Void is enough given 'get_output_mode'.

--
Waldek Hebisch

Grégory Vanuxem

unread,
Apr 14, 2024, 5:01:11 AM4/14/24
to fricas...@googlegroups.com
Hello,

Le sam. 13 avr. 2024 à 21:05, Waldek Hebisch <de...@fricas.org> a écrit :
>
> On Sun, Apr 07, 2024 at 06:05:39AM +0200, Grégory Vanuxem wrote:
> >
> > It is possible to modify some parameters to Float output routines,
> > what about returning the previous settings? For example
> > outputSpacing(n) returns Void but if you want to temporarily modify
> > this setting, in Spad for example, reverting to the user setting is
> > not possible. I attached a proof of concept patch that implements
> > this. In fact, even the macro 'separator ==> underscore()$Character'
> > could also be parametrable, it is not in this diff though.
>
> Thinking more about this: it should be possible to restore _whole_
> previous settings. So probably we need something like:
>
> get_output_mode : () -> Record(mode : String, prec : String)
>
> othewise, after
>
> outputFixed()
> n := outputGeneral(12)
>
> we have no clue that previous mode was "fixed".

Yes, exactly.

> Also, '-1' is
> valid as precision, but to set arbitrary valid precision one
> would have to use code like
>
> if prec = -1 then
> outputFixed()
> else
> outputFixed(prec::NonNegativeInteger)

Yes, and as -1 is not documented and only "settable" via output*
without arguments I guess you are thinking about an Integer argument
to set the precision, am I right?

> And to set desired mode we would need chain of tests. So it seems
> that we need funtion
>
> set_output_mode : (Stiring, Integer) -> Record(mode : String, prec : String)

So a general routine, just some checks to do. I agree that it could be
handy, and, even, an error message can be displayed, in case of a typo
for example, that helps the user in the interpreter for the different
mode available (no full explanation of course). It just remains from
my point of view the previous spacing setting as suggested in the
previous diff.

> which sets desired mode. I wrote above version that returns old settings,
> but in principle version that returns Void is enough given 'get_output_mode'.

Agreed.

- Greg

Waldek Hebisch

unread,
Apr 26, 2024, 12:56:49 PM4/26/24
to fricas...@googlegroups.com
On Sun, Apr 14, 2024 at 11:00:33AM +0200, Grégory Vanuxem wrote:
> Le sam. 13 avr. 2024 à 21:05, Waldek Hebisch <de...@fricas.org> a écrit :
> >
> > On Sun, Apr 07, 2024 at 06:05:39AM +0200, Grégory Vanuxem wrote:
> > >
> > > It is possible to modify some parameters to Float output routines,
> > > what about returning the previous settings? For example
> > > outputSpacing(n) returns Void but if you want to temporarily modify
> > > this setting, in Spad for example, reverting to the user setting is
> > > not possible.
<snip>
> > Thinking more about this: it should be possible to restore _whole_
> > previous settings.
<snip>
> > that we need funtion
> >
> > set_output_mode : (Stiring, Integer) -> Record(mode : String, prec : String)
<snip>
> > which sets desired mode. I wrote above version that returns old settings,
> > but in principle version that returns Void is enough given 'get_output_mode'.
>
> Agreed.

Attached is possible patch.

--
Waldek Hebisch
sum6a1.diff
Reply all
Reply to author
Forward
0 new messages