## a design exercise

APL-related discussions - a stream of APL consciousness.
Not sure where to start a discussion ? Here's the place to be
Forum rules
This forum is for discussing APL-related issues. If you think that the subject is off-topic, then the Chat forum is probably a better place for your thoughts !

### a design exercise

The Problem

Design a representation of complex numbers and a function to do complex multiplication which satisfy the following:

• ⍺ times ⍵ works on corresponding subarrays for “conformable” complex arrays ⍺ and ⍵
• times⌿⍵ or times/⍵ works on a complex “vector” ⍵
The result in each case must be complex numbers using the same representation, of course. Depending on the representation, a complex “vector” could be a higher-dimensional array; for example, if a complex number is a 2-element vector, a complex “vector” would have shape (≢⍵),2. Likewise “conformable” takes the representation into account.

“Structural” (⍴, ↑, etc.), “selection” (⌿, [;], ⌷, etc.), and the ⍳ family (⍳, ∊) functions work best on complex arrays if the complex number representation specifies a scalar representation. Therefore, probably, we want a complex number to be a scalar rather than (say) a 2-element vector.

An Attempt

For example: A complex number is an enclosed pair of numbers, and times is defined as follows:

`      f0← {(-/⍺×⍵),+/⍺×⌽⍵}      f ← f0¨      (⊂3 4) f (⊂5 6)┌─────┐│¯9 38│└─────┘      3j4 × 5j6¯9J38`

So far so good.

To get a complex number from the enclosed pairs representation and vice versa, proceed as follows. The function “j” is described in the APL Chat Forum post j. on 2020-04-09.

`      j←{⍺←0 ⋄ ⍺+0j1×⍵}      jfp← j/¨      pfj← 9 11∘○¨      pfj 3j4 5j6┌───┬───┐│3 4│5 6│└───┴───┘      jfp (3 4) (5 6)3J4 5J6`

Does the function f satisfy the conformability requirement?

`      y←(5 6) (7 8) (¯3 1)      (⊂3 4) f y┌─────┬──────┬──────┐│¯9 38│¯11 52│¯13 ¯9│└─────┴──────┴──────┘      jfp (⊂3 4) f y¯9J38 ¯11J52 ¯13J¯9      3j4 × 5j6 7j8 ¯3j1¯9J38 ¯11J52 ¯13J¯9      xr←¯10+?4 5⍴22 ⋄ xi←¯10+?4 5⍴22 ⋄ x←xr j xi ⋄ x2←xr,¨xi      yr←¯10+?4 5⍴22 ⋄ yi←¯10+?4 5⍴22 ⋄ y←yr j yi ⋄ y2←yr,¨yi      (x×y) ≡ jfp x2 f y21`

OK, the above works. But it fails the second requirement for reduction with complex multiplication:

`      y←(5 6) (7 8) (¯3 1)      f⌿ y┌─────────────┐│┌──────┬────┐│││0 ¯210│0 96│││└──────┴────┘│└─────────────┘      f/y    ⍝ It is not a matter of / versus ⌿┌─────────────┐│┌──────┬────┐│││0 ¯210│0 96│││└──────┴────┘│└─────────────┘      ×/ 5j6 7j8 ¯3j1¯43J¯259`

Discussion

I ran into this problem with the work on Rational Arithmetic reported in the APL Chat Forum. The problem is not a trivial one because complications engendered thereby propagate into all code using rational numbers. I am using complex numbers here to make the point with less distractions. I believe this is a problem with the Dyalog/NARS/APL2 style of arrays, reduction, scan, and inner product; I further believe that this problem precludes an APL programmer being able to define abstract scalars (complex numbers, rational numbers, extended precision integers, polynomials, etc.) in a general way. The problem was first described in Orth’s paper A Comparison of the IPSA and STSC Implementations of Operators and General Arrays, APL Quote Quad, volume 12, number 2, 1981-12.

There are several requirements for an abstract scalar to behave similarly as a simple scalar:

• If f is a “scalar function”, then ⍺ f ⍵ should work on conformable arrays ⍺ and ⍵, producing an array with the same type.
• If f is a “scalar function”, then f/⍵ on a vector ⍵ should produce a scalar with the same type.
• ⍺ ⍵ ↔ ⍺,⍵: The strand of two scalars juxtaposed should form a 2-element vector of the same type.
The “same type” requirement is important because it allows you to carry on, for example in a f b f c, or
a f b g c (where g is another scalar function).

A Solution

The stated problem actually has a solution. Not general and not elegant, but a solution. To wit:

`      times0← {(-/⍺×⍵),+/⍺×⌽⍵}  ⍝ note: same as f0 above      times← {2=≡⍵:⍺ times0¨⍵ ⋄ ⍺ times0 ⍵}       y←(5 6) (7 8) (¯3 1)      (⊂3 4) times y┌─────┬──────┬──────┐│¯9 38│¯11 52│¯13 ¯9│└─────┴──────┴──────┘      3j4 × 5j6 7j8 ¯3j1¯9J38 ¯11J52 ¯13J¯9      times/ y┌────────┐│¯43 ¯259│└────────┘      ×/ 5j6 7j8 ¯3j1¯43J¯259`

The solution is not very satisfying because basically the code is detecting whether it is being evaluated in a reduction, times/⍵, or by itself, ⍺ times ⍵.

`      xr←¯10+?4 5⍴22 ⋄ xi←¯10+?4 5⍴22 ⋄ x←xr j xi ⋄ x2←xr,¨xi      yr←¯10+?4 5⍴22 ⋄ yi←¯10+?4 5⍴22 ⋄ y←yr j yi ⋄ y2←yr,¨yi      (x×y) ≡ jfp x2 times y21      (×\y) ≡ jfp times\ y21      (×⍀y) ≡ jfp times⍀ y21      yr←¯10+?5 6⍴22 ⋄ yi←¯10+?5 6⍴22 ⋄ y←yr j yi ⋄ y2←yr,¨yi      plus←{⍺+⍵}      (x+.×y) ≡ jfp x2 plus.times y21      (x∘.×y) ≡ jfp x2 ∘.times y21`

I feel I am ready to update the Rational Arithmetic code to use these ideas, and then to use that code in some applications. Writing the applications and running into trouble was what made me realize things were amiss with the original design.
Roger|Dyalog

Posts: 215
Joined: Thu Jul 28, 2011 10:53 am