eo icon indicating copy to clipboard operation
eo copied to clipboard

Check if object is NaN or is Infinity while converting to Phi object

Open maxonfjvipon opened this issue 3 years ago • 12 comments

In some cases we can get NaN or Infinities as a result of object dataization.
For example:

  • 0.0.div 0.0 => nan,
  • 1.0.div 0.0 => positive-infinity,
  • (number nan).ln => nan (natural logarithm, in progress)
  • etc...

NaN are Ifinities are double, so I suggest to do something like this:

private static Phi toPhi(final Object obj) {
    ...
    } else if (obj instanceof Double) {
        if (((Double) obj).isNaN()) {
            phi = new EOnan(Phi.Φ);
        } else {
            phi = new EOfloat(Phi.Φ);
        }
    }
    ....
}

And also add checking infinities here.
In that case we won't get an error when we do for example 0.0.div 0.0, we'll get nan object and will be able to work with it

maxonfjvipon avatar Sep 21 '22 14:09 maxonfjvipon

@maxonfjvipon but we don't have EOnan in here

yegor256 avatar Sep 21 '22 14:09 yegor256

@yegor256 has not it been already created after compiling?

image

maxonfjvipon avatar Sep 21 '22 14:09 maxonfjvipon

@maxonfjvipon it belongs to eo-math package. We can't use objects from this package inside eo-runtime. Well, technically we can, but this would be violation of "layered architecture" principle.

yegor256 avatar Sep 21 '22 14:09 yegor256

@maxonfjvipon @yegor256 I think we are already talk about it here: https://github.com/objectionary/eo/issues/774#issuecomment-1164312509

Graur avatar Sep 21 '22 14:09 Graur

@yegor256 yeah, I remember, but it's more complicated)
Ok, I try to figure it out, but I think eventually it must be done somehow. 0.0.div 0.0 has not to throw an exception. It should return nan object.

maxonfjvipon avatar Sep 21 '22 14:09 maxonfjvipon

@yegor256 I did a little research and here's what I think. Anyway we should move nan and infinities to eo-runtime. I believe it's the place where they belong to. Even in Java NaN belong to Double class. In other cases we won't be able to solve this problem.

After we move them we can solve it in two ways.

  1. Easy. As I described above - add extra conditions to toPhi. There'll be no cross layering anymore because nan,infinities and float are in the same package.
  2. Not easy and maybe not even worth to be discussed. As I suggested here: try to add some new EO syntax.

maxonfjvipon avatar Sep 21 '22 22:09 maxonfjvipon

@maxonfjvipon I have another proposal. How about we make sure div doesn't throw an exception but returns float, which is nan (byte wise)?

yegor256 avatar Sep 22 '22 04:09 yegor256

@yegor256 so the result of 0.0.div 0.0 will be float object, but with bytes of nan.

0.0.div 0.0 > x # EOfloat
QQ.math.nan > n # EOnan

Here we should make sure that x and n have the same amount of inner objects with the same behavior

Won't it be some kind of crutch? Not really float and not really nan (from eo perspective)

maxonfjvipon avatar Sep 22 '22 07:09 maxonfjvipon

@yegor256 It seems some objects like float.lt|lte|gte may not work correctly. Even float.eq

(0.0.div 0.0).eq nan # it'll be TRUE, but has to be FALSE

maxonfjvipon avatar Sep 22 '22 08:09 maxonfjvipon

(0.0.div 0.0).eq nan # it'll be TRUE, but has to be FALSE

@maxonfjvipon As I remember, dividing by 0.0 leads to signed infinity

Graur avatar Sep 22 '22 08:09 Graur

@Graur 0.0 / 0.0 = nan, 1.0 / 0.0 = +inf, -1.0 / 0.0 = -inf

maxonfjvipon avatar Sep 22 '22 08:09 maxonfjvipon

@yegor256 @Graur WDYT?

  1. move nan to eo-runtime (or not)
  2. make 0.0.div 0.0 return float but with nan bytes (Double.NaN)
  3. make nan decorated 0.0.div 0.0
[] > nan
  0.0.div 0.0 > @
  1. extend float.eo: to every inner object that is implemented in EO add check if self as bytes equal to nan.as-bytes (if nan won't be moved - take this nan bytes somewhere else) (btw float object uses eo-collection objects, isn't it a cross-layer violation?) For example:
image

In that case we will get:

0.0.div 0.0 # float that behaves like nan
(0.0.div 0.0).div <any> # should be Double.NaN / <any> = Double.NaN => float that behaves like nan
nan.div <any> # nan - from nan object
4.2.div nan # nan decorates (0.0.div 0.0), so in java it'll be dataized to Double.NaN => 4.2 / Double.NaN = Double.NaN => float that behaves like nan

maxonfjvipon avatar Sep 22 '22 11:09 maxonfjvipon

Resume:

  1. Move nan, positive-infinity and negative-infinity to eo-runtime and place them inside float object
  2. Add decoratees to these objects so they can be dataized to java primitives
  3. Allow division by float zero
  4. Add extra checks to Data.ToPhi.toPhi(), for example:
if (((Double) obj).isNaN()) {
    phi = new EOfloat$EOnan(Phi.Φ);
}

I believe I didn't miss anything. @Graur please assign me. Can you set a 60 minutes budget?

maxonfjvipon avatar Feb 03 '23 11:02 maxonfjvipon

@maxonfjvipon Sure, but it's always better to split this task to several puzzles by 30 min each. Please, use pdd for such cases. I suggest at least 4 pdd puzzles with 30 min budget each.

Graur avatar Feb 03 '23 11:02 Graur

@Graur Ok, sounds great!

maxonfjvipon avatar Feb 03 '23 11:02 maxonfjvipon

@maxonfjvipon 3 puzzles #1800, #1801, #1802 are still not solved.

0pdd avatar Feb 15 '23 10:02 0pdd

@maxonfjvipon all 3 puzzles are solved here: #1800, #1801, #1802.

0pdd avatar Feb 16 '23 11:02 0pdd