adds support for Python 3.5 infix matrix multiplication
Python 3.5 will have a new commercial-at infix operator with the magic methods __matmul__, __rmatmul__, and __imatmul__, unused as yet in the standard library, but intended to represent matrix multiplication in numerical code; see PEP 465 (https://www.python.org/dev/peps/pep-0465/) for details. This commit (developed against Python 3.5 alpha 3) brings support for this operator to Hy when running under Python 3.5 (or, hypothetically as yet, greater). For Hy under Python <= 3.4, attempting to use `@` in function-call position currently results in a NameError; this commit does not change that behavior. This is intended to resolve #668.
This commit is contained in:
parent
4938163ec4
commit
0dbf2126cf
@ -42,6 +42,7 @@ PY27 = sys.version_info >= (2, 7)
|
||||
PY3 = sys.version_info[0] >= 3
|
||||
PY33 = sys.version_info >= (3, 3)
|
||||
PY34 = sys.version_info >= (3, 4)
|
||||
PY35 = sys.version_info >= (3, 5)
|
||||
|
||||
if PY3:
|
||||
str_type = str
|
||||
|
@ -38,7 +38,8 @@ from hy.models.cons import HyCons
|
||||
from hy.errors import HyCompileError, HyTypeError
|
||||
|
||||
import hy.macros
|
||||
from hy._compat import str_type, long_type, PY27, PY33, PY3, PY34, raise_empty
|
||||
from hy._compat import (
|
||||
str_type, long_type, PY27, PY33, PY3, PY34, PY35, raise_empty)
|
||||
from hy.macros import require, macroexpand, reader_macroexpand
|
||||
import hy.importer
|
||||
|
||||
@ -121,6 +122,13 @@ def builds(_type):
|
||||
return _dec
|
||||
|
||||
|
||||
def builds_if(_type, condition):
|
||||
if condition:
|
||||
return builds(_type)
|
||||
else:
|
||||
return lambda fn: fn
|
||||
|
||||
|
||||
class Result(object):
|
||||
"""
|
||||
Smart representation of the result of a hy->AST compilation
|
||||
@ -1638,6 +1646,7 @@ class HyASTCompiler(object):
|
||||
@builds("|")
|
||||
@builds("^")
|
||||
@builds("&")
|
||||
@builds_if("@", PY35)
|
||||
@checkargs(min=2)
|
||||
def compile_maths_expression(self, expression):
|
||||
ops = {"+": ast.Add,
|
||||
@ -1652,6 +1661,8 @@ class HyASTCompiler(object):
|
||||
"|": ast.BitOr,
|
||||
"^": ast.BitXor,
|
||||
"&": ast.BitAnd}
|
||||
if PY35:
|
||||
ops.update({"@": ast.MatMult})
|
||||
|
||||
inv = expression.pop(0)
|
||||
op = ops[inv]
|
||||
@ -1711,6 +1722,7 @@ class HyASTCompiler(object):
|
||||
@builds("|=")
|
||||
@builds("^=")
|
||||
@builds("&=")
|
||||
@builds_if("@=", PY35)
|
||||
@checkargs(2)
|
||||
def compile_augassign_expression(self, expression):
|
||||
ops = {"+=": ast.Add,
|
||||
@ -1725,6 +1737,8 @@ class HyASTCompiler(object):
|
||||
"|=": ast.BitOr,
|
||||
"^=": ast.BitXor,
|
||||
"&=": ast.BitAnd}
|
||||
if PY35:
|
||||
ops.update({"@=": ast.MatMult})
|
||||
|
||||
op = ops[expression[0]]
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
(import [hy._compat [PY35]])
|
||||
|
||||
(setv square (fn [x]
|
||||
(* x x)))
|
||||
|
||||
@ -140,3 +142,52 @@
|
||||
(defn overflow-int-to-long []
|
||||
"NATIVE: test if int does not raise an overflow exception"
|
||||
(assert (integer? (+ 1 1000000000000000000000000))))
|
||||
|
||||
|
||||
(defclass HyTestMatrix [list]
|
||||
[[--matmul--
|
||||
(fn [self other]
|
||||
(let [[n (len self)]
|
||||
[m (len (. other [0]))]
|
||||
[result []]]
|
||||
(for [i (range m)]
|
||||
(let [[result-row []]]
|
||||
(for [j (range n)]
|
||||
(let [[dot-product 0]]
|
||||
(for [k (range (len (. self [0])))]
|
||||
(+= dot-product (* (. self [i] [k])
|
||||
(. other [k] [j]))))
|
||||
(.append result-row dot-product)))
|
||||
(.append result result-row)))
|
||||
result))]])
|
||||
|
||||
(def first-test-matrix (HyTestMatrix [[1 2 3]
|
||||
[4 5 6]
|
||||
[7 8 9]]))
|
||||
|
||||
(def second-test-matrix (HyTestMatrix [[2 0 0]
|
||||
[0 2 0]
|
||||
[0 0 2]]))
|
||||
|
||||
(def product-of-test-matrices (HyTestMatrix [[ 2 4 6]
|
||||
[ 8 10 12]
|
||||
[14 16 18]]))
|
||||
|
||||
(defn test-matmul []
|
||||
"NATIVE: test matrix multiplication"
|
||||
(if PY35
|
||||
(assert (= (@ first-test-matrix second-test-matrix)
|
||||
product-of-test-matrices))
|
||||
;; Python <= 3.4
|
||||
(let [[matmul-attempt (try (@ first-test-matrix second-test-matrix)
|
||||
(catch [e [Exception]] e))]]
|
||||
(assert (isinstance matmul-attempt NameError)))))
|
||||
|
||||
(defn test-augassign-matmul []
|
||||
"NATIVE: test augmented-assignment matrix multiplication"
|
||||
(let [[matrix first-test-matrix]
|
||||
[matmul-attempt (try (@= matrix second-test-matrix)
|
||||
(catch [e [Exception]] e))]]
|
||||
(if PY35
|
||||
(assert (= product-of-test-matrices matrix))
|
||||
(assert (isinstance matmul-attempt NameError)))))
|
||||
|
Loading…
Reference in New Issue
Block a user