フラクタル記述言語 Fractal#


はじめに

ある図形の変形を繰り返した結果できる図形があります。 たとえば、 図1(図1) のような線分を 図2(図2) のような数個の線分に 変形する操作を繰り返すことによって、 図3(図3) のような図形を描くことができます。 ここで紹介するものは、このような図形を描画するための言語です。

この言語 Fractal# では、 図形の情報の集合の間の変換を合成することができます。 図形の情報は、図の各(有向)線分の情報です。 図形が描画される平面を複素平面と考え、 始点が a、終点が a + b である線分を (a, b) と表します。 (0, 1) を単位線分と呼びます。 ある線分 (a, b) は単位線分 (0, 1) をその線分に写す変換と考えることができます。 線分 (a, b) に対応する変換を t(a, b) とすると、 変換 t(a, b) は線分 (c, d) を (a + bc, bd) に写す変換となります。 このような変換全体の集合を T とします。 集合 T の二つの元 t, s に対して、変換 t の結果に対して変換 s を適用した 結果を作る変換(変換の合成)を Fractal# では t & s と書きます。 集合 T の元 t に対して、「t の固定化」!t を考えます。 集合 T の元と「固定化された元」全体の集合を T' とします。すなわち

    T' = { t, !t | t∈T }
と定義します。 固定化された元は演算 & によって変化しないとして、 集合 T' の二つの元 t', s' に対して、t' & s' を定義します。
    t & !s = !(t & s),
    !t & s = !t,
    !t & !s = !t
とします。 集合 T' の二つの部分集合 x、y に対して、 x の元であるすべての変換 t と y の元であるすべての変換 s とからできる t & s 全体の集合を x & y とします。すなわち
    x & y = { t & s | t∈x, s∈y }
と定義します。 また、x と y の和集合を x | y と書きます。

たとえば、 図4(図4) のような線分を、 図5(図5) のような数個の線分に変形する変換は、 線分 L から線分 A、B、C、D への変換をそれぞれ a、b、c、d とすると、 Fractalでは図4から図5への変換は、a | b | c | d と表すことができます。 また、a | b | c | d を e とすると、図4から 図5(図6) への変換は、 e & e & e & e と表すことができます。

言語の説明

全体の記述は以下のようになります。
    定義; 定義; ... 定義; 式
最後の式は、この式を繰り返すことを表します。 これを「繰り返し式」と呼びます(後述)。 「定義」は変数の定義
    var 変数名 = 式
または関数の定義
    var 関数名 = (変数名, 変数名, ... , 変数名) => 式
です。 //から行の終わりまではコメントです。

式は次のものです。 二項演算子と関数適用は左結合です。 演算子の優先順位は C# と同様とします。 不要な括弧は省いてもかまいません。 (結合の順序を変えるために括弧を使うことができます。)
  (式 二項演算子 式)
  (単項演算子 式)
  (式 ? 式 : 式)
  関数名(式, 式, … , 式)
  関数名(式..式)
  (式 ^ 式)(式)
  (式)

二項演算子

数値は複素数とします。これは複素平面上の点を表します。 数値全体の集合を N で表します。 真理値(真または偽)全体の集合を B で表します。 T' を上で定義した固定化されていないかまたは固定化された変換(線分)全体の集合とし、 L を T' の部分集合全体の集合とします。

演算子 意味
+ N×N→N 加算
L×N→N 加算(線分の移動)、(a, b) + c = (a + c, b)
- N×N→N 減算
L×N→N 減算(線分の移動)、(a, b) - c = (a - c, b)
* N×N→N 乗算
L×N→N 乗算(線分の長さと向きの変更)、(a, b) * c = (a, bc)
/ N×N→N 除算
L×N→N 除算(線分の長さと向きの変更)、(a, b) / c = (a, b/c)
^ N×N→N 累乗
L×N→L 変換の繰り返し、t ^ n = t & t & … & t (n個)
(L→L)×N→(L→L) 変換の繰り返し
== N×N→B 等しい
!= N×N→B 等しくない
< N×N→B 小さい
<= N×N→B 小さいか等しい
> N×N→B 大きい
>= N×N→B 大きいか等しい

単項演算子

演算子 意味
- N→N 符号を変える
~ N→N 角度(度)を複素数に変換
! L→L 固定化

式1 ? 式2 : 式3

式1は真理値で、式1を評価した結果が真のとき式2を評価してその値がこの式の値となり、 偽のとき式3を評価してその値がこの式の値となります。

関数名(式, 式, … , 式)

関数を評価します。「(式, 式, ... , 式)」の部分は関数の引数です。関数名は「定義」の部分で定義された「ユーザー定義関数」か、定義しなくても使える「システム標準関数」です。

関数名(式1..式2)

上記の関数で、引数の個数が1個で、N から L への関数であるとき、この形式を使うことができます。 関数を f、式1の値を m、式2の値を n とすると、f(式1..式2) の値は f(m) | f(m+1) | … | f(n-1) となります。

(式1 ^ 式2)(式3)

上記の関数で、引数の個数が1個で、式1の値が L から L への関数、式2の値が数値であるとき、この形式を使うことができます。 式1の値を f、式2の値を n とすると、(式1 ^ 式2)(式3)の値は f を n 回繰り返した f(f(…(f(式3の値))…)) となります。

システム標準関数名

次のものがあります。 実数の関数もあります(実数を R で表します)。 基本的には C# で標準的に使えるものの中から JavaScript で簡単に実装できるものとしています。

名前 意味
sin N→N 正弦関数
cos N→N 余弦関数
tan N→N 正接関数
sinh N→N 双曲線正弦関数
cosh N→N 双曲線余弦関数
tanh N→N 双曲線正接関数
acos N→N 逆余弦関数
asin N→N 逆正弦関数
atan N→N 逆正接関数
asinh R→R 逆双曲線正弦関数
acosh R→R 逆双曲線余弦関数
atanh R→R 逆双曲線正接関数
exp N→N 指数関数
log N→N 対数関数
log10 N→N 底 10 の対数関数
log2 N→N 底 2 の対数関数
sqrt N→N 平方根
cbrt N→N 立方根
abs N→N 絶対値
sign R→R 符号を示す数値(正のとき1、0のとき0、負のとき-1)
ceiling R→R 指定した数以上の数のうち、最小の整数値
floor R→R 指定した数以下の数のうち、最大の整数値
round R→R 最も近い整数
truncate R→R 整数部(0 に向かって最も近い整数)
phase N→N 極座標の偏角
rot R×R→N 実数部と虚数部から絶対値1の複素数を作る
atan2 R×R→N 座標で指定された点の偏角
print N→N ステータス領域に数値を出力する(結果は入力された値)

システム標準定数名

定義しなくても使える「システム標準定数」は次のものがあります。

名前 意味
u L 単位線分だけからなる集合
i N 虚数単位
e R 自然対数の底
pi R 円周率

繰り返し式と式の結果

「フラクタル7」では繰り返しの回数を指定することができます。

「繰り返し式」の値の型は L または N→L です。 型が L のとき値を t とすると、指定した繰り返しの回数 n に対して、 線分の集合 t ^ n が結果となります。 型が N→L のとき値を関数 f とすると、指定した繰り返しの回数 n に対して、 線分の集合 f(n) が結果となります。

演算子の優先順位

優先順位の高い順で以下のような順となります。
演算子 意味
-、!、~ 単項演算子
*、/ 乗法、除法
+、– 加法、減法
<、>、<=、>= 関係演算子
==、!= 等価比較
& 変換の合成
^ 累乗、変換の繰り返し
| 変換の和集合
&& 論理積
|| 論理和
c ? t : f 条件演算子
.. 範囲(C#の優先順位とは異なります)
=、=> 変数、関数の定義

2022年8月17日 Ver.1.00