gaucheで行列

gaucheで行列はgauche.arrayを使う。

(use gauche.array)
(print (array-ref #,(<array> (0 2 0 2) 1 2 3 4) 0 0))
(print (array-ref #,(<array> (0 2 0 2) 1 2 3 4) 0 1))
(print (array-ref #,(<array> (0 2 0 2) 1 2 3 4) 1 0))
(print (array-ref #,(<array> (0 2 0 2) 1 2 3 4) 1 1))
;1
;2
;3
;4

おお、まるきり配列!

Reader syntax: #,(<array> shape obj …)

配列はこの形式で書き出されます。 (配列が例えば<u8array>であるなら、<array>の部分は<u8array> となります。) shapeは偶数個の整数のリストで、 2n番目の整数がn次元目のインデックスの下限を、2n+1番目の 整数がn次元目のインデックスの上限(+1)を表します。 その後に、配列の要素がrow-majorの順で書き出されます。

この構文が読み込まれると、もとの配列とequal?である配列が作成されます。

あれ?2n->2n-1,2n+1->2nのミスかな?

(use gauche.array)
(print (array-ref #,(<array> (1 3 0 2) 1 2 3 4) 2 1))
;4

たぶんそうだな。

行列の積もできる。

(use gauche.array)
(print (array-mul
	#,(<array> (0 2 0 2)
		   1 2
		   3 4)
	#,(<array> (0 2 0 2)
		   2 0
		   0 2)))
;>>#,(<array> (0 2 0 2) 2 4 6 8)

1行2列なのが気持ち悪いが行列×ベクトルもOK

(print (array-mul #,(<array> (0 2 0 2) 2 0 0 1) #,(<array> (0 2 0 1) 2 3)))
;#,(<array> (0 2 0 1) 4 3)

2行1列ではエラーとなる

(print (array-mul #,(<array> (0 2 0 2) 2 0 0 1) #,(<array> (0 1 0 2) 2 3)))
;>>*** ERROR: dimension mismatch: can't mul shapes #,(<array> (0 2 0 2) 0 2 0 2) and #,(<array> (0 2 0 2) 0 1 0 2)

ということでコッホ曲線をsvgで出力してみる。
いまいち可読性が悪い。どうしてくれよう。(要検討)

(use gauche.array)
(use math.const)
(define (koch a b n)
  (let* 
      ((c (array
	   (shape 0 3 0 1)
	   (/ (+ (* 2 (array-ref a 0 0)) (array-ref b 0 0)) 3)
	   (/ (+ (* 2 (array-ref a 1 0)) (array-ref b 1 0)) 3)
	   1))
       (d (array
	   (shape 0 3 0 1)
	   (/ (+ (array-ref a 0 0) (* 2 (array-ref b 0 0))) 3)
	   (/ (+ (array-ref a 1 0) (* 2 (array-ref b 1 0))) 3)
	   1))
       (e (array-mul
	   (array (shape 0 3 0 3)
		  1 0 (array-ref c 0 0)
		  0 1 (array-ref c 1 0)
		  0 0 1)
	   (array-mul
	    (array (shape 0 3 0 3)
		   (cos (/ pi 3)) (- (sin (/ pi 3))) 0
		   (sin (/ pi 3)) (cos (/ pi 3)) 0
		   0 0 1)
	    (array-mul
	     (array (shape 0 3 0 3)
		    1 0 (- (array-ref c 0 0))
		    0 1 (- (array-ref c 1 0))
		    0 0 1)
	     d)))))
;    (print a "\n" b "\n" c "\n" d "\n" e)
    (if (> n 0)
	(let ((m (- n 1)))
	  (koch a c m)
	  (koch c e m)
	  (koch e d m)
	  (koch d b m))
	(let 
	    ((line
	      (lambda (a b)
		(print "<line x1=\"" (x->integer (array-ref a 0 0))
		       "\" y1=\"" (x->integer (array-ref a 1 0))
		       "\" x2=\"" (x->integer (array-ref b 0 0))
		       "\" y2=\"" (x->integer (array-ref b 1 0))
		       "\" stroke=\"blue\" stroke-width=\"1\" />"))))
	  (line a c)
	  (line c e)
	  (line e d)
	  (line d b)))))

(print "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"1000\" height=\"1000\">")
(koch #,(<array> (0 3 0 1) 100 100 1) #,(<array> (0 3 0 1) 900 100 1) 4)
(print "</svg>")