I think you have plenty of cause for confusion here. As far as I'm
aware, there is no source which clearly and correctly documents the
behaviour of J's tolerant complex floor. It's also a poor design in my
opinion: in particular it fails to satisfy the desirable property that
if c=z for a complex integer c, using tolerant comparison, then c=<.z .

Here's the implementation of complex floor in J's source:

ZF1(jtzfloor){D p,q;
 ZF1DECL;
 zr=jfloor(a); p=a-zr;
 zi=jfloor(b); q=b-zi;
 if(1<=p+q+(1.0-jt->cct))if(p>=q)++zr; else ++zi;   // could improve this test
 ZEPILOG;
}

And a J translation which behaves almost identically (it looks like
<!.0/d has some numerical issues):

jfl =: 3 : 0"0
  c =. +. y
  f =. <.!.0 c
  d =. c - f
  j./ f + (<!.0/d) |. 2 {. 1 <: +/d
)

There are three comparisons here which could each be tolerant, or not.
Two of them are intolerant (!.0). However, The J dictionary
(https://www.jsoftware.com/help/dictionary/d011.htm) and NuVoc
(https://code.jsoftware.com/wiki/Vocabulary/ltdot) both incorrectly
indicate that they should be tolerant.

J's implementation seems to be an attempt to follow the XAPL standard
(ISO/IEC 13751:2001), which is not freely available. The standard is
ambiguous, since it uses the undefined terms "fractional-parts" and
"nearer". It's unclear whether these should be subject to comparison
tolerance, and it looks like the documentation and implementation have
interpreted it two different ways.

I think that the fully tolerant interpretation used in documentation is
slightly better, but I consider XAPL's definition to be borderline
nonsensical in either case. As a Dyalog APL implementer I have done some
work on designing a better specification which I'd be happy to share.

The page http://www.jsoftware.com/papers/eem/complexfloor1.htm, which
describes intolerant complex floor, is giving me a 403 error. Does
anyone else see it?

Marshall

On Fri, Oct 11, 2019 at 07:51:17PM +0900, ethiejiesa via Programming wrote:
> 
> I assume this is well known by the cognoscenti, but I just ran into a newbie 
> surprise:
> 
>        <. _1e_14j0
>     _1
>        <. _1e_14 j. 0
>     0
> 
> This came about as I was learning about and playing with the complex floor. 
> Apparently, the differing behaviour traces back to how tolerance is handled 
> differently for different numeric types:
> 
>         (3!:0) 0j0
>     1
>         (3!:0) 0 j. 0
>     16
> 
> Tricky. So in the former case, it seems that the number literal parser 
> understands equivalence classes of types and is lifting numbers to their most 
> specific type. In the latter case, from the dictionary, 0 j. 0 <--> 0 + 0j1 * 
> 0:
> 
>         (3!:0) 0 + 0j1 * 0
>     16
> 
> So, in a sense 0 j. 0 is a complex because the return values of + and * are 
> the _coarser_ of their arguments, which seems to lie in tension with the 
> cleverness of the number parser.
> 
> Perhaps this is all documented clearly somewhere and I just missed it, but I 
> had fun figuring this one out and wanted to share.
> 
> I assume that complex vs. real tolerance is a well-worn discussion topic; 
> however, is there much on the idea of making field operations "type lifting" 
> in a way similar to number literal parsing? Not even sure if this a 
> reasonable thing to do.
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to