def take(Fn, A, B): """ implement dyadic ↑ """ assertNotArray(A) if B.isScalar() or B.isEmptyVector(): if A.isEmptyVector(): return B if B.isVectorLike(): assertScalarLike(A) Apy = confirmInteger(A.scalarToPy()) if Apy == 0: return makeEmptyVector(B.prototype()) Rpy = Fn(Apy, B.vectorToPy(), B.padFill()) return makeVector(Rpy, abs(Apy), B.prototype()) Apy = [confirmInteger(I) for I in A.vectorToPy()] assertTrue(B.dimension() == (2, 2), "WIP - MATRIX ERROR") assertTrue(len(Apy) == B.rank(), "LENGTH ERROR") Rpy = [] for Bit in Fn(Apy[0], B.arrayByLastAxis(), B.padFill()): Rpy += Fn(Apy[1], Bit.vectorToPy(), Bit.padFill()) return makeArray(Rpy, [abs(I) for I in Apy], B.prototype())
def pick(_, A, B): """ implement dyadic ⊃ """ assertNotArray(A) assertNotArray(B) if A.isEmptyVector(): return B assertNotScalar(B) if B.isVector(): IO = indexOrigin() try: for X in A.vectorToPy(): X = confirmInteger(X) assertTrue(X >= IO, "INDEX ERROR") if isinstance(B, aplQuantity): B = B.vectorToPy()[X - IO] else: assertError("RANK ERROR") except IndexError: assertError("INDEX ERROR") if isinstance(B, aplQuantity): return B return makeScalar((B, ), None)
def grade(descending, B): """ implement monadic ⍒ and ⍋ """ def _sortKey(Y): """ sort key depends on type as well value """ if isinstance(Y, aplQuantity): return 2 * Y.tally(), Y if isinstance(Y, str): return 0, ord(Y) return 1, Y assertNotScalar(B, "DOMAIN ERROR") if B.isArray(): assertTrue(B.dimension() == (2, 2), "WIP - MATRIX ERROR") Bpy = [Bit.vectorToPy() for Bit in B.arrayByLastAxis()] Key = lambda X: [_sortKey(Y) for Y in Bpy[X]] if B.isVector(): B.resolve() Bpy = B.vectorToPy() Key = lambda X: _sortKey(Bpy[X]) Len = B.tally() S = list(range(Len)) S.sort(key=Key, reverse=descending) return makeVector(iterator.grade(S), Len)
def encode(Fn, A, B): """ implement dyadic ⊤ """ if B.isEmptyVector(): # Simplistic return makeEmptyVector() if A.isEmptyVector(): # Simplistic return makeEmptyVector() if B.isArray(): if A.isScalarLike(): Rpy = [] Apy = A.vectorToPy() for Bpy in B.arrayToPy(): Rpy.append(Fn(Apy, Bpy).__next__()) return makeArray(Rpy, B.dimension()) assertError("WIP - RANK ERROR") if B.isVector(): assertTrue(B.tally() == 2, "WIP - LENGTH ERROR") if A.isArray(): assertError("WIP - RANK ERROR") if A.isVector(): assertTrue(A.tally() == 2, "WIP - LENGTH ERROR") Rpy, Apy = [], A.vectorToPy() for Bpy in B.vectorToPy(): Rpy += Fn(Apy, Bpy) Rpy = monadicTranspose(Rpy, (A.tally(), B.tally())) return makeArray(Rpy, (A.tally(), B.tally())) Rpy, Apy = [], A.vectorToPy() for Bpy in B.vectorToPy(): Rpy += Fn(Apy, Bpy) if A.isArray(): Rpy, Bpy = [], B.scalarToPy() for Ait in A.arrayByFirstAxis(): Rpy += Fn(Ait.vectorToPy(), Bpy) return makeArray(Rpy, A.dimension(), B.prototype()) if A.isVector(): Rpy = Fn(A.vectorToPy(), B.scalarToPy()) return makeVector(Rpy, A.tally()) Rpy = Fn(A.vectorToPy(), B.scalarToPy()) return makeScalar(Rpy)
def maths(Fn, A, B): """ the basic recursive map for dyadic mathematical functions """ if B.isArray(): if A.isArray(): # Check ranks are equal Rpy = iterator.maths(maths, Fn, A, B) elif A.isVector(): # Check length is compatible Rpy = iterator.maths(maths, Fn, A.vectorIterator(), B) else: Rpy = iterator.maths(maths, Fn, A.scalarIterator(), B) return makeArray(Rpy, B.dimension(), B.prototype()) if A.isArray(): if B.isVector(): # Check length is compatible Rpy = iterator.maths(maths, Fn, A, B.vectorIterator()) else: Rpy = iterator.maths(maths, Fn, A, B.scalarIterator()) return makeArray(Rpy, A.dimension(), A.prototype()) if B.isVector(): if A.isVector(): if B.isEmptyVector(): assertTrue(A.isEmptyVector(), "LENGTH ERROR") Rpy = iterator.maths(maths, Fn, A, B) elif B.isEmptyVector(): return B else: Rpy = iterator.maths(maths, Fn, A.scalarIterator(), B) return makeVector(Rpy, B.dimension(), B.prototype()) if A.isVector(): if A.isEmptyVector(): return A else: Rpy = iterator.maths(maths, Fn, A, B.scalarIterator()) return makeVector(Rpy, A.dimension(), A.prototype()) return makeScalar(iterator.maths(maths, Fn, A, B))
def transpose(_, B): """ implement monadic ⍉ """ if B.isArray(): assertTrue(B.dimension() == (2, 2), "WIP - MATRIX ERROR") Rpy = monadicTranspose(B.arrayToPy(), B.dimension()) return makeArray(Rpy, B.dimension(), None) return B
def iota(Fn, B): """ implement monadic ⍳ the operand is scalar: there is no map as such """ if B.isScalar(): Bpy = confirmInteger(B.scalarToPy()) assertTrue(Bpy >= 0, "DOMAIN ERROR") return makeVector(Fn(Bpy), Bpy) assertNotVector(B, "WIP - LENGTH ERROR") assertNotArray(B)
def drop(Fn, A, B): """ implement dyadic ↓ """ assertNotArray(A) if B.isScalar(): if A.isEmptyVector(): return B assertScalarLike(A) Apy = confirmInteger(A.scalarToPy()) if Apy == 0: return makeVector(B.vectorToPy(), 1, B.prototype()) return makeEmptyVector(B.prototype()) if B.isVector(): if A.isEmptyVector(): Apy = 1 else: assertScalarLike(A) Apy = confirmInteger(A.scalarToPy()) if Apy == 0: return B Rpy = Fn(Apy, B.vectorToPy()) return makeVector(Rpy, -1, B.prototype()) Apy = [confirmInteger(I) for I in A.vectorToPy()] assertTrue(B.dimension() == (2, 2), "WIP - MATRIX ERROR") assertTrue(len(Apy) == B.rank(), "LENGTH ERROR") Rpy = [] for Bit in Fn(Apy[0], B.arrayByLastAxis()): Rpy += Fn(Apy[1], Bit.vectorToPy()) Dpy = [max(0, I[1] - abs(I[0])) for I in zip(Apy, B.dimension())] return makeArray(Rpy, Dpy, B.prototype())
def reverselast(Fn, B): """ implement monadic ⌽ """ if B.isArray(): assertTrue(B.dimension() == (2, 2), "WIP - MATRIX ERROR") Rpy = [] for Bit in B.arrayByLastAxis(): Rpy += Fn(Bit.vectorToPy()) return makeArray(Rpy, B.dimension(), None) if B.isVector() and not B.isEmptyVector(): return makeVector(Fn(B.vectorToPy()), B.dimension(), None) return B
def compressFirst(Fn, A, B): """ implement dyadic ⌿ """ assertNotArray(A) if B.isScalar() and A.isEmptyVector(): return makeEmptyVector(B.prototype()) if B.isVectorLike(): Rpy = Fn(A.promoteScalarToVectorPy(), B.vectorToPy(), B.padFill()) return makeVector(Rpy, -1, B.prototype()) if B.isArray(): assertTrue(B.dimension() == (2, 2), "WIP - MATRIX ERROR") Apy = [confirmInteger(I) for I in A.vectorToPy()] if A.isScalarLike(): Lpy = abs(Apy[0]) * B.dimension()[0] else: Lpy = sum(abs(I) for I in Apy) Dpy = list(B.dimension()) Dpy[0] = Lpy Dpy[0], Dpy[-1] = Dpy[-1], Dpy[0] if Lpy == 0: return makeArray(B.padFill(), Dpy, B.prototype()) assertTrue(tuple(Dpy) == (2, 2), "WIP - MATRIX ERROR") Rpy = [] for Bit in B.arrayByFirstAxis(): Rpy += Fn(A.promoteScalarToVectorPy(), Bit.vectorToPy(), B.padFill()[-1]) Rpy = monadicTranspose(Rpy, B.dimension()) return makeArray(Rpy, Dpy, B.prototype())
def transpose(_, A, B): """ implement dyadic ⍉ """ assertNotArray(A) if B.isArray(): assertTrue(A.tally() == B.rank(), "LENGTH ERROR") IO = indexOrigin() Apy = [confirmInteger(I) - IO for I in A.vectorToPy()] high = B.rank() + 1 assertTrue(all(x >= 0 and x <= high for x in Apy), "DOMAIN ERROR") assertTrue(sum(Apy) <= sum(range(B.rank())), "DOMAIN ERROR") Rpy = dyadicTranspose(B.arrayToPy(), Apy, B.dimension()) def newDimensions(A, B): """ determine dimensions of the transposed result """ R = list(range(len(A))) for I in R: H = [B[X] for X in R if A[X] == I] if H: yield min(H) Dpy = tuple(newDimensions(Apy, B.dimension())) if len(Dpy) == 1: return makeVector(Rpy, Dpy[0], None) return makeArray(Rpy, Dpy, None) if B.isVector(): assertScalarLike(A) Apy = confirmInteger(A.scalarToPy()) assertTrue(Apy == 1, "DOMAIN ERROR") return B assertEmptyVector(A) return B
def _nextPair(self): """ fetch the next pair of values from the iterators """ OK = 0 try: self._X = confirmInteger(self._A.__next__()) if self._X > 0: self._T += 1 if self._T == 0: return elif self._X == 0: self._X -= 1 OK += 1 except StopIteration: pass if self._X < 0 and self._T < 0: return try: self._Y = self._B.__next__() self._T -= 1 OK += 1 except StopIteration: pass if self._X < 0 and self._T == 0: return if OK != 2: if isinstance(self._A, aplIterator): assertTrue(self._T == 1, "LENGTH ERROR") else: assertTrue(self._T == 0, "LENGTH ERROR") raise StopIteration
def reshape(Fn, A, B): """ implement dyadic ⍴ """ assertNotArray(A) if A.isScalarLike(): Apy = confirmInteger(A.scalarToPy()) assertTrue(Apy >= 0, "DOMAIN ERROR") if Apy == 0: return makeEmptyVector(B.prototype()) Bpy = B.castToVectorPy() return makeVector(Fn(Apy, Bpy), Apy, B.prototype()) if A.isEmptyVector(): Bpy = B.castToVectorPy() return makeVector(Fn(1, Bpy), 1, B.prototype()) Apy = tuple([confirmInteger(I) for I in A.vectorToPy()]) assertTrue(Apy == (2, 2), "WIP - MATRIX ERROR") for I in Apy: assertTrue(I >= 0, "DOMAIN ERROR") Bpy = B.castToVectorPy() return makeArray(Fn(Apy, Bpy), Apy, 2 * B.prototype())
def rotateFirst(Fn, A, B): """ implement dyadic ⌽ """ assertNotArray(A) if B.isArray(): if not A.isScalarLike(): assertTrue(A.tally() == B.rank(), "LENGTH ERROR") assertTrue(B.tally() != 0, "WIP - LENGTH ERROR") Apy = [ operator.mod(confirmInteger(I), B.tally()) for I in A.vectorToPy() ] if A.isScalarLike(): Apy = Apy * B.rank() Rpy = [] for Apy, Bit in zip(Apy, B.arrayByFirstAxis()): Rpy += Fn(Apy, Bit.vectorToPy()) Rpy = monadicTranspose(Rpy, B.dimension()) return makeArray(Rpy, B.dimension(), None) assertScalarLike(A, "RANK ERROR") Apy = confirmInteger(A.scalarToPy()) if B.isEmptyVector(): return B Apy = operator.mod(Apy, B.tally()) if Apy == 0: return B return makeVector(Fn(Apy, B.vectorToPy()), B.dimension(), None)
def partition(Fn, A, B): """ implement dyadic ⊂ """ assertNotArray(A) assertNotTrue(B.isScalar(), "RANK ERROR") if A.isEmptyVector() and B.isEmptyVector(): return B if A.isScalar(): Apy = confirmInteger(A.scalarToPy()) if Apy == 0: return makeEmptyVector() return makeScalar((B, ), B.prototype()) if B.isArray(): assertTrue(B.dimension() == (2, 2), "WIP - MATRIX ERROR") Apy = A.vectorToPy() assertTrue(len(Apy) == B.rank(), "LENGTH ERROR") Rpy = [] for Bit in B.arrayByLastAxis(): Rpy += makeScalar((Fn( A.vectorToPy(), Bit.vectorToPy(), ), B.prototype())) Dpy = list(B.dimension()) Dpy[-1] = 1 return makeArray(Rpy, Dpy, None) return makeVector(Fn(A.vectorToPy(), B.vectorToPy()), -1, B.prototype())
def expandFirst(Fn, A, B): """ implement dyadic ⍀ """ assertNotArray(A) if B.isScalar() and A.isEmptyVector(): return makeEmptyVector(B.prototype()) if B.isVectorLike(): if A.isScalar(): Apy = confirmInteger(A.scalarToPy()) assertTrue(Apy >= 0, "LENGTH ERROR") if Apy == 0: return makeVector(B.prototype(), 1, B.prototype()) Rpy = Fn(A.promoteScalarToVectorPy(), B.vectorToPy(), B.padFill()) return makeVector(Rpy, -1, B.prototype()) if B.isArray(): assertTrue(B.dimension() == (2, 2), "WIP - MATRIX ERROR") Apy = [confirmInteger(I) for I in A.vectorToPy()] if A.isScalarLike(): if Apy[0] < B.dimension()[0]: assertError("LENGTH ERROR") else: assertError("DOMAIN ERROR") else: Lpy = sum(abs(I) if I != 0 else 1 for I in Apy) Dpy = list(B.dimension()) Dpy[-1] = Lpy assertTrue(tuple(Dpy) == (2, 2), "WIP - MATRIX ERROR") Rpy = [] for Bit in B.arrayByFirstAxis(): Rpy += Fn(A.promoteScalarToVectorPy(), Bit.vectorToPy(), B.padFill()[-1]) Rpy = monadicTranspose(Rpy, Dpy) Dpy[0], Dpy[-1] = Dpy[-1], Dpy[0] return makeArray(Rpy, Dpy, B.prototype())
def decode(Fn, A, B): """ implement dyadic ⊥ """ if B.isArray(): if A.isScalarLike(): Rpy = [] for Bit in B.arrayByFirstAxis(): Rpy.append(Fn(A.promoteScalarToVectorPy(), Bit)) return makeVector(Rpy, B.dimension()[0], B.prototype()) if A.isVector(): assertNotTrue(A.isEmptyVector(), "DOMAIN ERROR") assertTrue(A.tally() == B.dimension()[0], "LENGTH ERROR") Rpy = [] for Bit in B.arrayByFirstAxis(): Rpy.append(Fn(A.vectorToPy(), Bit)) return makeVector(Rpy, A.dimension(), B.prototype()) assertTrue(A.rank() == B.rank(), "WIP - RANK ERROR") assertTrue(A.dimension()[-1] == B.dimension()[0], "LENGTH ERROR") Rpy = [] for Ait in A.arrayByLastAxis(): for Bit in B.arrayByFirstAxis(): Rpy.append(Fn(Ait, Bit)) return makeArray(Rpy, A.dimension(), B.prototype()) if B.isVector(): if A.isEmptyVector() or B.isEmptyVector(): return makeScalar(0) return makeScalar(Fn(A.promoteScalarToVectorPy(), B.vectorToPy())) if A.isScalar(): assertNumeric(A) assertNumeric(B) return B return makeScalar(Fn(A.vectorToPy(), B.scalarIterator()))
def grade(descending, A, B): """ implement dyadic ⍒ and ⍋ """ def _sortKey(Y): """ return collation sequence index or 1 greater """ try: return Apy.index(Y) except ValueError: return Csl assertNotScalar(A, "RANK ERROR") A.resolve() assertTrue(A.isString(), "DOMAIN ERROR") B.resolve() assertTrue(B.isString(), "DOMAIN ERROR") assertNotArray(A, "RANK ERROR") Csl = A.dimension() Apy = ''.join(A.vectorToPy()) if B.isArray(): assertTrue(B.dimension() == (2, 2), "WIP - MATRIX ERROR") Bpy = [Bit.vectorToPy() for Bit in B.arrayByLastAxis()] Key = lambda X: [_sortKey(Y) for Y in Bpy[X]] if B.isVectorLike(): Bpy = B.vectorToPy() Key = lambda X: _sortKey(Bpy[X]) Len = B.tally() S = list(range(Len)) S.sort(key=Key, reverse=descending) return makeVector(iterator.grade(S), Len)