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 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 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 index(Fn, A, B): """ implement dyadic ⍳ """ assertNotArray(A) if B.isEmptyVector(): return makeEmptyVector(B.prototype()) if A.isEmptyVector(): Rpy = scalarIterator(indexOrigin(), B.elementCount(), B.expressionToGo) elif B.isArray(): Rpy = Fn(A.vectorToPy(), B.arrayToPy()) else: Rpy = Fn(A.vectorToPy(), B.vectorToPy()) if B.isArray(): return makeArray(Rpy, B.dimension()) if B.isVector(): return makeVector(Rpy, B.dimension()) return makeScalar(Rpy)
def unique(Fn, B): """ implement monadic ∪ """ assertNotArray(B, "RANK ERROR") if B.isScalarLike() or B.isEmptyVector(): return B return makeVector(Fn(B.vectorToPy()), -1, B.prototype())
def set2set(Fn, A, B): """ implement dyadic ∪ and ∩ """ assertNotArray(A) assertNotArray(B) if A.isEmptyVector() and B.isEmptyVector(): return B Rpy = Fn(A.vectorToPy(), B.vectorToPy()) return makeVector(Rpy, -1, A.prototype())
def tail(Fn, B): """ implement monadic ↓ """ assertNotArray(B, "RANK ERROR") if B.isScalarLike(): return makeEmptyVector(B.prototype()) if B.isEmptyVector(): return B return makeVector(Fn(B.vectorToPy()), B.dimension() - 1, B.prototype())
def without(Fn, A, B): """ implement dyadic ~ """ assertNotArray(A) if B.isArray(): Rpy = Fn(A.vectorToPy(), B.arrayToPy()) else: Rpy = Fn(A.vectorToPy(), B.vectorToPy()) return makeVector(Rpy, -1, A.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 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 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 makePrototype(self): """ the quantity's array prototype used for padding/filling """ if self.isVectorLike(): if isinstance(self._value, tuple): prototype = [] for element in self._value: prototype.append(makeQuantity.makePrototype(element)) else: prototype = self._value.makePrototype() return tuple(prototype) assertNotArray(self, "WIP - makePrototype PROTOTYPE RANK ERROR")
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 concatenate(Fn, A, B): """ implement dyadic , """ assertNotArray(A, "WIP - RANK ERROR") assertNotArray(B, "WIP - RANK ERROR") prototype = B.prototype() if A.isEmptyVector() else A.prototype() Apy = 1 if A.isScalar() else A.dimension() Bpy = 1 if B.isScalar() else B.dimension() dimension = -1 if (Apy < 0 or Bpy < 0) else (Apy + Bpy) Rpy = Fn(A.vectorToPy(), B.vectorToPy()) return makeVector(Rpy, dimension, prototype)
def scanLast(Fn, _, B): """ the map for the \ (scan along last axis) operator """ if B.isScalar(): return B if B.isVector(): if B.isEmptyVector(): return B if B.isScalarLike(): return makeScalar(B.scalarToPy()) Rpy = iterator.scanVector(Fn, B) return makeVector(Rpy, B.dimension(), B.prototype()) assertNotArray(B, "WIP - RANK ERROR")
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 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)
def reduceFirst(Fn, A, B): """ the map for the ⌿ (reduce along first axis) operator """ if B.isScalar(): return B if B.isVector(): if B.isEmptyVector(): assertNotTrue(A is None, "DOMAIN ERROR") return makeScalar(A) Rpy = iterator.reduceVector(Fn, B) if Rpy.isScalar(): return Rpy return makeScalar((Rpy, ), makePrototype(Rpy)) assertNotArray(B, "WIP - RANK ERROR")
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())