我有兴趣使用elisp来练习实现一些线性代数算法(速度不是这里的一个目标) - 但是elisp并不支持像常见的lisp这样的多维数组
我需要最终做一些事情,比如在索引处获取值,获取子矩阵,获取此列,获取此行等,以编写算法,分解等等
我如何在elisp中重新创建类似的东西? 即。我如何从简单的数据结构,如列表和构建到矩阵?
我试着看看Emacs calc
但它有点过头了,我不知道如何定义实际矩阵
(虽然我对数学很满意,但对于lisps我只有一点方案经验..所以也许这不是一个好的入门项目?哈哈)
答案 0 :(得分:0)
在只有一维数组(或向量)的语言中,显而易见的方法是创建向量的向量。
这是一个简单的实现这个技巧(非常不适合生产使用!)在elisp中:
(defun make-simple-array (dims &optional init)
;; make n-dimensional array, represented as a vector of vectors (of
;; vectors ...).
(if (null (cdr dims))
(make-vector (car dims) init)
(let* ((d1 (car dims))
(dt (cdr dims))
(v (make-vector d1 nil))
(i 0))
(while (< i d1)
(aset v i (make-simple-array dt init))
(setq i (1+ i)))
v)))
(defun simple-array-ref (a indices)
(if (null (cdr indices))
(aref a (car indices))
(simple-array-ref (aref a (car indices)) (cdr indices))))
(defun simple-array-set (a indices newval)
(if (null (cdr indices))
(aset a (car indices) newval)
(simple-array-set (aref a (car indices)) (cdr indices) newval)))
这种方法很简单,但会导致可怕的局部性:数组的元素可能遍布整个地方。更好的方法是分配一个大向量,然后计算其中元素的位置。这就是任何严肃的阵列实现都会起作用的。
对于hack值,这里是一个原始的部分实现,它将数组保持为一个大向量并计算位置。在此实现中,数组存储为(v . factors)
的缺点,其中factors
是计算索引到v
所需的预先计算的索引因子。这个实现至少有两个问题:
(0 2)
索引的元素,这实际上是由(1 0)
索引的元素。无论如何,这是一个实现。
(defun compute-flat-array-total-size (dimensions)
;; this is in fact (reduce #'* dimensions), but elisp
(let ((s 1))
(mapc (lambda (d) (setq s (* s d))) dimensions)
s))
(defun compute-flat-array-index-factors (dimensions)
(cond ((null dimensions)
'(0))
((null (cdr dimensions))
'(1))
(t (let ((ftail (compute-flat-array-index-factors (cdr dimensions))))
(cons (* (car dimensions) (car ftail))
ftail)))))
(defun compute-flat-array-index (indices factors)
;; Again, elisp sucks: you can't even use mapc here
(let ((index 0)
(itail indices)
(ftail factors))
(while (not (null itail))
(when (null ftail)
(error "too many indices"))
(setq index (+ index (* (car itail) (car ftail)))
itail (cdr itail)
ftail (cdr ftail)))
(unless (null ftail)
(error "two few indices"))
index))
(defun make-flat-array (dimensions &optional init)
;; a flat array is a cons of a vector of its contents and a list of
;; index factors.
(cons (make-vector (compute-flat-array-total-size dimensions) init)
(compute-flat-array-index-factors dimensions)))
(defun flat-array-ref (fa indices)
(aref (car fa) (compute-flat-array-index indices (cdr fa))))
(defun flat-array-set (fa indices newval)
(aset (car fa) (compute-flat-array-index indices (cdr fa)) newval))