Hi all!
These two F# programs describe what initiates the special handling. It
might be different in J, but the functionality should be the same, at
least from what my tests show. Except from the error case. JWithATwist
hides no error cases.
let rec RankMonadic uVerb functionRank xNoun : JNoun =
let xShape=xNoun.JShape
//Rank in the call to the J verb is the min of functionRank and
x rank
let xRank = xShape.Length
let rank = min xRank functionRank
//If outershape contains zero, there is nothing to operate on.
//This is no problem if innershape contains zero. Then the
corresponding empty array is used in the call.
//If outershape contains zero and innershape does not, we need
something to operate on to
//determine type and shape of the empty result. We then
generate a default object of the correct
//shape and type to operate on.
let xShape = xNoun.JShape
let innerShape = Array.sub xShape (xRank-rank) rank
let outerShape = Array.sub xShape 0 (xRank-rank)
match innerShape, outerShape with
|innerShape, outerShape when (0=Array.fold (*) 1 outerShape)
&& (( 0<>Array.fold (*) 1 innerShape) || innerShape=[||]) ->
RankMonadicEmptyArraySpecialHandling uVerb rank xNoun
outerShape innerShape
|_ ->
let boxesOfNoun = RankMonadicBox uVerb rank xNoun
RankMonadicOpen boxesOfNoun
let rec RankDyadic uVerb functionRank xNoun yNoun: JNoun =
let xShape,yShape=xNoun.JShape,yNoun.JShape
//Rank in the call to the J verb is the min of functionRank and
x rank
let xyRank = [|xShape.Length;yShape.Length|]
let rank = min xyRank functionRank
// TODO: Duplicated code in RankDydic and RankDyadicBox because
of planned restructuring.
let xShape,yShape=xNoun.JShape,yNoun.JShape
let xRank,yRank = xShape.Length,yShape.Length
let xOperationRank,yOperationRank =
match rank with
|[|xOperationRank;yOperationRank|] ->
xOperationRank,yOperationRank
|_ ->
raise JExceptionLengthError
//x
let xInnerShape = Array.sub xShape (xRank-xOperationRank)
xOperationRank
//let xFrameSize = Array.fold (*) 1 xInnerShape
let xOuterShape = Array.sub xShape 0 (xRank-xOperationRank)
let xNValues = max 1 (Array.fold (*) 1 xOuterShape)
//y
let yInnerShape = Array.sub yShape (yRank-yOperationRank)
yOperationRank
//let yFrameSize = Array.fold (*) 1 yInnerShape
let yOuterShape = Array.sub yShape 0 (yRank-yOperationRank)
let yNValues = max 1 (Array.fold (*) 1 yOuterShape)
//
let nValues,outerShape =
match xOuterShape,yOuterShape with
|x,y when x.Length < y.Length ->
yNValues,yOuterShape
|x,y when x.Length >= y.Length ->
xNValues,xOuterShape
|_ ->
raise JExceptionSystemError
match xNValues,yNValues with
|xNValues,yNValues when xNValues=yNValues || xNValues = 1 ||
yNValues = 1 ->
//If outershape contains zero, there is nothing to operate on.
//This is no problem if innershape contains zero. Then the
corresponding empty array is used in the call.
//If outershape contains zero and innershape does not, we
need something to operate on to
//determine type and shape of the empty result. We then
generate a default object of the correct
//shape and type to operate on.
let xSpecialHandling = ( 0<>Array.fold (*) 1 xInnerShape)
|| xInnerShape=[||]
let ySpecialHandling = ( 0<>Array.fold (*) 1 yInnerShape)
|| yInnerShape=[||]
match xInnerShape,yInnerShape,outerShape with
|xInnerShape,yInnerShape,outerShape when (0=Array.fold (*)
1 outerShape) && ( xSpecialHandling || ySpecialHandling) ->
RankDyadicEmptyArraySpecialHandling xSpecialHandling
ySpecialHandling uVerb rank xNoun yNoun outerShape xInnerShape yInnerShape
|_ ->
let boxesOfNoun = RankDyadicBox uVerb rank xNoun yNoun
RankMonadicOpen boxesOfNoun
|_->
raise JExceptionLengthError
The rest of the code is available in the Base.fs file in JWithATwist.
For copyright reasons I don't look in the J code base, so I can not
point to the problem in the J code.
Cheers,
Erling Hellenäs
Den 2017-12-20 kl. 15:00, skrev Erling Hellenäs:
We have a problem in the Rank operator, which I described. I am trying
to create a discussion about solutions to this problem. /Erling
Den 2017-12-20 kl. 13:31, skrev Raul Miller:
Actually, J does support arrays of nothing. That's what i.0 is, after
all. And, if you want a scalar containing an array of nothing, then a:
matches that specification.
And we have an algebra here - though if (as in your previous message)
you do multiplication and call it addition, this becomes very
difficult to talk about.
That said, remember that we can add an arbitrary number of leading 1
dimensions to any array without changing the number of elements in
that array.
Thanks,
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm