Ejemplo n.º 1
0
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())
Ejemplo n.º 2
0
def enlist(Fn, B):
    """
    implement monadic ∊
    """
    if B.isEmptyVector():
        return B

    if B.isVectorLike():
        return makeVector(Fn(B.vectorToPy()), -1, B.prototype())

    return makeVector(Fn(B.arrayToPy()), -1, B.prototype())
Ejemplo n.º 3
0
def unravel(_, B):
    """
    implement monadic ,
    """
    if B.isArray():
        return makeVector(B.arrayToPy(), B.elementCount(), B.prototype())

    if B.isVector():
        return B

    return makeVector(B.vectorToPy(), 1, B.prototype())
Ejemplo n.º 4
0
def rho(_, B):
    """
    implement monadic ⍴
    """
    if B.isArray():
        return makeVector(B.dimension(), B.rank())

    if B.isVector():
        return makeVector((B.tally(), ), 1)

    return makeEmptyVector()
Ejemplo n.º 5
0
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))
Ejemplo n.º 6
0
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())
Ejemplo n.º 7
0
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())
Ejemplo n.º 8
0
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())
Ejemplo n.º 9
0
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)
Ejemplo n.º 10
0
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)
Ejemplo n.º 11
0
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)
Ejemplo n.º 12
0
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()))
Ejemplo n.º 13
0
def deal(Fn, A, B):
    """
    implement deal (dyadic ?)
    """
    assertScalarLike(A, "RANK ERROR")
    assertScalarLike(B, "RANK ERROR")

    Apy = confirmInteger(A.scalarToPy())

    return makeVector(Fn(Apy, B.scalarToPy()), Apy)
Ejemplo n.º 14
0
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())
Ejemplo n.º 15
0
def evaluate(expression, cio):
    """
    evaluate an APL expression

    called from parse and routines parse calls so beware indirect recursion
    """
    try:
        expr = expression.lstrip()

        if not expr:
            assertError("SYNTAX ERROR")

        lhs, expr = parse(expr, cio)

        if lhs == []:
            lhs = None
        elif len(lhs) > 1:
            lhs = makeVector(tuple(lhs), -1, None)
        elif isinstance(lhs[0], aplQuantity):
            lhs = lhs[0]
        else:
            lhs = makeScalar(lhs[0], None)

        if not expr:
            return lhs

        if cio.newStmt:
            if lhs is None and expr[0] == '⊣':
                cio.hushImplicit = True
            cio.newStmt = False

        operator = operatorFunction(expr[1:].lstrip()) if lhs is None else None

        if operator is None and lhs is None:
            function = monadicFunction(expr)
        else:
            identity, function = dyadicFunction(expr)

        if not operator is None:
            expr = expr[1:].lstrip()

        rhs = evaluate(expr[1:], cio)
        rhs.expressionToGo = expr

        if operator is None:
            result = function(rhs) if lhs is None else function(lhs, rhs)
        else:
            result = operator(function, identity, rhs)

        return result.resolve() if eagerEvaluation() else result

    except aplException as error:
        if not error.expr:
            error.expr = expr
        raise error
Ejemplo n.º 16
0
def maths(Fn, B):
    """
    the basic recursive map for monadic mathematical functions
    """
    if B.isArray():
        return makeArray(iterator.maths(maths, Fn, B), B.dimension())

    if B.isVector():
        return makeVector(iterator.maths(maths, Fn, B), B.dimension(),
                          B.prototype())

    return makeScalar(iterator.maths(maths, Fn, B))
Ejemplo n.º 17
0
    def _aplVector(self, Y):
        """
        create, for return, a non-empty APL vector quantity else raise StopIteration)
        """
        V = self._V

        if V == []:
            raise StopIteration

        self._V = [] if Y is None else [Y]

        return makeVector(tuple(V), len(V), (makePrototype(V[0]), ))
Ejemplo n.º 18
0
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())
Ejemplo n.º 19
0
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())
Ejemplo n.º 20
0
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())
Ejemplo n.º 21
0
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
Ejemplo n.º 22
0
    def __next__(self):
        V = []  # the vector (row) to return
        L = self._L

        try:
            while L:
                V.append(self._B.__next__())
                L -= 1
        except StopIteration:
            if L != self._L:
                assertError("lastAxisIterator: oops")
            raise StopIteration

        return makeQuantity.makeVector(V, self._L)
Ejemplo n.º 23
0
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)
Ejemplo n.º 24
0
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
Ejemplo n.º 25
0
def evaluateBoxTickIO(expr, cio):
    """
    evaluate, print (possibly) and return an intermediary result
    """
    texpr = expr[1:].lstrip()

    if texpr and texpr[0] == '←':
        # output operator

        newStmt = cio.newStmt
        cio.newStmt = False

        rhs = evaluate(texpr[1:], cio) if newStmt else evaluate(
            texpr[1:], cio).resolve()

        if rhs.padFill() == ' ':
            cio.userPromptLength = rhs.dimension()
            cio.printExplicit(rhs, '')
        elif rhs.isVector():
            cio.printExplicit(makeVector((rhs, ), 1), '')
        else:
            cio.printExplicit(rhs, '')

        if newStmt:
            cio.hushImplicit = True
            rhs = None

        return rhs, len(expr)

    else:
        # input operator

        lcio = shallowcopy(cio)
        lcio.startNewLine()
        lcio.prompt = ""

        try:
            expr = lcio.read(lcio.inFile)
        except EOFError:
            assertError("EOF ERROR")

        value = makeString(cio.userPromptLength * ' ' + expr, False)

        cio.endOfLine = '\n'

        return value, 1
Ejemplo n.º 26
0
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)
Ejemplo n.º 27
0
def find(Fn, A, B):
    """
    implement dyadic ∊
    """
    A.resolve()

    Apy = A.arrayToPy() if A.isArray() else A.vectorToPy()
    Bpy = B.arrayToPy() if B.isArray() else B.vectorToPy()

    Rpy = Fn(Apy, Bpy)

    if B.isArray():
        return makeArray(Rpy, B.dimension(), B.prototype())

    if B.isVector():
        return makeVector(Rpy, B.dimension(), B.prototype())

    return makeScalar(Rpy, B.prototype())
Ejemplo n.º 28
0
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")
Ejemplo n.º 29
0
def membership(Fn, A, B):
    """
    implement dyadic ∊
    """
    if A.isEmptyVector():
        return A

    Apy = A.arrayToPy() if A.isArray() else A.vectorToPy()
    Bpy = B.arrayToPy() if B.isArray() else B.vectorToPy()

    Rpy = Fn(Apy, Bpy)

    if A.isArray():
        return makeArray(Rpy, A.dimension(), A.prototype())

    if A.isVector():
        return makeVector(Rpy, A.dimension(), A.prototype())

    return makeScalar(Rpy, A.prototype())
Ejemplo n.º 30
0
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())