On 22.06.2016 20:07, Colin Macdonald wrote:

> [moving to maintainers list]

>

> Summary: if you do `sym(1/3)` instead of `sym(1)/3`, we give a warning.

How do you decide whether to give a warning? If the parameter is no

integer? There are some fractions which have no rounding errors, e. g.

0.5, 0.25, 0.125, … and sums thereof.

On 22.06.2016 23:34, Colin Macdonald wrote:

> On 22/06/16 11:26, Reik Reid wrote:

>> If vpa() behaved the same way as sym(), would leaving out the quotes be

>> safe for all cases of constant numerical expressions? Is that a

>> desirable behavior?

>

> There is a relatively small set of values were its safe to leave off the

> quotes, for both sym and vpa. That set is "small" integers, inf, nan,

> and pi. The latter just for convenience (might have been a bad idea).

It's a difficult topic:

1. Even small integers might be the result of lost digits, e. g.

1.0000000000000001.

2. Experts might argue that inf is not infinity, but overflow of a big

value, e. g. 1e309.

3. nans are complicated already, e. g. 1e-324 / 1e-324.

4. yeah, pi might be problematic as well if the user expects to use the

approximate floating point value returned by pi () instead of π.

> On 22/06/16 08:48, Oliver Heimlich wrote:

>> There is the exactly same issue in the interval package. If you want

>> to implement this feature in the construtors (maybe with a regexp

>> to identify fractions and decimal numbers) we should use the same

>> warning id.

>

> Good idea. Do you think its appropriate to use the "Octave" namespace?

>

> Maybe something lke:

>

> 2. warning("Octave:possible-precision-loss", <custom message>)

> 3. warning("Octave:lossy-object-from-double", ...)

>

> For `sym` objects its currently:

>

> warning('OctSymPy:sym:rationalapprox', ...

> 'Using rat() heuristics for double-precision input (is this what you

> wanted?)');

>

> (but I'm happy to change it).

>

> Colin

We could stick to the official naming from IEEE 754, which is the

“inexact” exception. I propose one of the following:

warning("Octave:inexact-argument", …)

warning("numeric:inexact-argument", …)

warning("double:inexact-argument", …)

I am still not sure how do decide whether to trigger the warning.

Basically, we want to trigger the warning if some expression for the

input argument has triggered the “inexact” floating point exception.

However, we have no access to this information. What we have:

a. the floating point value of the input argument,

b. the expression for the input argument as a string (“argn” variable)

The argn variable might hide that the inexactness has happened before

calling the function. However, in this case I would not want to have a

warning. For example,

x = 0.1

sym (x)

Also the argn variable might be a complicated expression which produces

inexactness, e. g. 1 / (2 + 8). We don't want to handle these cases.

However, we want to handle basic matrix expressions like [1 2; 3 0.1]

Points 1 – 4 from above show that it is not possible to conclude from

the parameter's value alone, whether inexactness has occurred. If in

addition, we use the parameter's expression (argn), we can detect simple

cases at least. So what do we have to do to eliminate false positives?

1. Check if the parameter has a scalar value of type double (binary64).

2. Check if the parameter expression is either a decimal number of the

form [+-]d[.]d[[eE][+-]d] or a fraction of the form [+-]d / d. Matrix

expressions with square brackets, comma, and semicolon must be

considered as well.

3. Check whether the value is the result of inexact conversion.

The last point is complicated/costly. It gets even more complicated when

you want to cover non-scalar arguments as well, e. g. sym ([0.1, 0.2]).

So, maybe above goals are too ambitious. We could lower the quality of

step 3 and only check whether the parameter's value is not an integer

and uses more than N mantissa bits on the fractional part of the value

(N = 26 should be reasonable -- half the double precision). Then it is

possible to decide this problem in many common cases and create an

internal function.

__check_inexact_arg__ (x, argn(1, :))

__check_inexact_arg__ (y, argn(2, :))

function __check_inexact_arg__ (val, expression)

if (isa (val, 'double') && warning ("query", "numeric:inexact-argument"))

if (rem (val, pow2 (-26)) != 0)

if (regexp (expression, …))

warning ("numeric:inexact-argument", …)

endif

endif

endif

endfunction

This is quite cheap to check and limits false positives to cases where

the user has entered more than 8 decimal digits and the number happens

to be exact. We don't detect some cases with lengthy numbers, e. g.

1.0000000000000001.

Oliver