18 行列の操作 編集

行列の要素が,ある条件に合うかどうかを確かめるチェックをしたり,行列の要素を並べ替えるための多くの関数が利用可能です。 たとえば,Octave では,ある行列の全要素が有限値がどうか,あるいは特定の値よりも小さいかどうかを簡単に知ることができます。 Octave では,一部の要素を回転したり,上三角るいは下三角部分を抜き出したり,行列の列をソートしたりもできます。

18.1 要素の検出と条件のチェック 編集

anyとall関数は,行列の要素の「いずれか」あるいは「すべて」がある条件を満たすかどうかを判 定するときに便利です。 find関数も,行列の要素が特定の条件に合っていることを判定するときに便 利です。

any (x, dim) 編集

                                                           [Built-in Function]

ベクトルの引数については,そのベクトルのどれかの要素がゼロでないときに1 を返します。

行列の引数については,各要素が1 と0 を含む行ベクトルを返します。 その要素は,対応する行列 の列の要素のいずれかがゼロでないかどうかを示しています。 以下に例を示す。

any (eye (2, 4)) ) [ 1, 1, 0, 0 ] オプション引数dim を与えると,次元dim にそって動作します。 たとえば,以下のようになります。

any (eye (2, 4), 2) ) [ 1; 1 ]

all (x, dim) 編集

                                                           [Built-in Function]

関数allは,any関数と似た挙動をするが,ベクトルの全ての要素,あるいは行列のdim 次元 方向の全ての要素がゼロでないときにのみ,真を返す点が異なっています。

比較演算子(Section 10.4 [Comparison Ops]を参照)は,1 と0 のみを含む行列を返す ので,その要素がゼロでないかどうかといった簡単なことではなく,多くのことに関して行列をテス トすることは容易です。 たとえば,以下の式は, all (all (rand (5) < 0.9)) ) 0 ランダムな5 行5 列の行列について,その要素の全てが0.9 よりも小さいかどうかを確認するために テストします。

条件文(ifやwhileステートメントのテスト部分)では,Octave は,all (all (condition)) と打ち込んだかのようにテストを扱います。

xor (x, y) 編集

                                                           [Mapping Function]

x とy の全体の「排他的論理和」を返します。 x とy のブール表現では, x またはy が真であり, x かつy が真でないときに限り,真です。

is_duplicate_entry (x) 編集

                                                           [Function File]

もしx の要素が,別の要素と重複しているならば,ゼロでない値を返します。


diff (x, k, dim) 編集

                                                           [Function File]

もしx が長さn のベクトルならば,diff (x)は1 回目の差分(first difference)のベクトル である: x2 ! x1; : : : ; xn ! xn!1. もしx が行列ならば,diff (x)はfirst non-singleton dimension に沿った列の差の行列と なります。

2 番めの引数はオプションです。 もしこれを与えるならば,diff (x,k)となり,ここでk は 非負の整数です。 この関数は,k 回目の差分(k-th differences)を返します。 k が行列の最初の non-singleton dimension よりも大きいことも可能です。 このケースにおいて,diffは次 のnon-singleton dimension に沿って差をとることを継続します。

差をとるべき次元は,オプション変数dim によって明示的に指定することができます。 この場合, k 回目の差分は,この次元に沿って計算されます。 k がsize (x, dim)を越える場合は,空行列 が返されます。

isinf (x) 編集

                                                           [Mapping Function]

x 内の無限大(Inf)要素について1 を,それ以外について0 を返します。 以下に例を示す。

isinf ([13, Inf, NA, NaN]) ) [ 0, 1, 0, 0 ]

isnan (x) 編集

                                                           [Mapping Function]

x の要素がNaN であれば1,それ以外は0 を返します。 以下に例を示す。

isnan ([13, Inf, NA, NaN]) ) [ 0, 0, 0, 1 ]

finite (x) 編集

                                                           [Mapping Function]

有限値であるx の要素について1 を返し,そうでなければ0 を返します。 以下に例を示す。

finite ([13, Inf, NA, NaN]) ) [ 1, 0, 0, 0 ]

find (x) 編集

                                                           [Loadable Function]


ある行列のゼロでない要素のインデックスのベクトルを返します。 行列の各要素について1 個のイ ンデックスを得るために,Octave は,行列の列が(Fortran 配列が格納されているように)1 個の長いベクトルであると偽装します。 たとえば,以下のようになります。

find (eye (2)) ) [ 1; 4 ] もし2 つの出力が要求されたならば,findは,行列のゼロでない要素の行と列のインデックス を返します。 以下に例を挙げる。

[i, j] = find (2 * eye (2)) ) i = [ 1; 2 ] ) j = [ 1; 2 ] もし3 つの出力が要求されたならば,findは,ゼロでない値を含むベクトルも返します。

[i, j, v] = find (3 * eye (2)) ) i = [ 1; 2 ] ) j = [ 1; 2 ] ) v = [ 3; 3 ] Chapter 18: 行列の操作143

[err, y1, ...] = common_size (x1, ...) 編集

                                                           [Function File] 全ての入力引数がスカラ,あるいは共通のサイズかどうかを判別します。 もしそうであればerr はゼロであり,yi は,入力引数がスカラならば全要素がxi に等しい共通サイズの行列となり, そうでなければxi です。 もし入力が共通のサイズでなければ,エラーコードは1 であり,yi はxi となります。 以下に例を挙げる。

[errorcode, a, b] = common_size ([1 2; 3 4], 5) ) errorcode = 0 ) a = [ 1, 2; 3, 4 ] ) b = [ 5, 5; 5, 5 ] これは,引数がスカラあるいは共通サイズをとるような関数の実装に役立つ。

18.2 行列の整形 編集

fliplr (x) 編集

                                                           [Function File] 列の順序を逆にしたx のコピーを返します。 以下に例を挙げる。

fliplr ([1, 2; 3, 4]) ) 2 1 4 3 fliplrは2 次元配列についてのみ動作します。 N 次元の配列を反転するには,このかわりに flipdimを使用してください。

flipud (x) 編集

                                                           [Function File] 行の順序を逆にしたx のコピーを返します。 以下に例を挙げる。

==== flipud ([1, 2; 3, 4]) ) 3 4 1 2 行列を反転するための軸を定義することが困難なため,flipudは2 次元配列に限って動作す る。 N 次元の配列を反転するには,このかわりにflipdimを使用してください。

flipdim (x, dim) 編集

                                                           [Function File]

Return a copy of x flipped about the dimension dim. For example flipdim ([1, 2; 3, 4], 2) ) 2 1 4 3

rot90 (x, n) 編集

                                                           [Function File]

x の要素を反時計回りに90 度回転させた行列を返します。 2 番めの引数は,オプションであり,90 度回転を何回行うかを指定する(初期値は1 である)。 n に負の値を指定すると,行列を時計回 りに回転させる。 たとえば, rot90 ([1, 2; 3, 4], -1) ) 3 1 4 2 この式は,与えられた行列を時計回りに90 度回転させる。 以下の式は,すべて等価なステート メントです。


rot90 ([1, 2; 3, 4], -1) ´ rot90 ([1, 2; 3, 4], 3) ´ rot90 ([1, 2; 3, 4], 7) 行列を回転するための軸を定義することが困難なため,rot90は2 次元配列に限って動作します。

N 次元の配列を反転するには,このかわりにrotdimを使用してください。

rotdim (x, n, plane) 編集

                                                           [Function File] x の要素を反時計回りに90 度回転させた行列を返します。 2 番めの引数は,オプションであり,90 度回転を何回行うかを指定する(初期値は1 である)。 3 番めの引数もオプションであり,回転 の次元を定義します。 plane は,その行列の2 つの異なる妥当な次元を含む,2 要素のベクトル です。 もしplane が与えられなければ,最初の2 つのnon-singleton dimensions が使用さ れる。

n に負の値を指定すると,行列を時計回りに回転させる。 たとえば, rotdim ([1, 2; 3, 4], -1, [1, 2]) ) 3 1 4 2 この式は,与えられた行列を時計回りに90 度回転させる。 以下の式は,すべて等価なステート メントです。

rot90 ([1, 2; 3, 4], -1, [1, 2]) ´ rot90 ([1, 2; 3, 4], 3, [1, 2]) ´ rot90 ([1, 2; 3, 4], 7, [1, 2])

cat (dim, array1, array2, . . . , arrayN) 編集

                                                           [Built-in Function]

N 個の配列オブジェクト,array1,array2,. . . ,arrayN を次元dim に沿って連結したもの を返します。

A = ones (2, 2); B = zeros (2, 2); cat (2, A, B) ) ans = 1 1 0 0 1 1 0 0 これとは別に,以下のように2 番めの次元に沿ってA とB を連結することができます。

[A, B] dim はN 個の配列オブジェクトの次元より大きくても良く,その結果は,以下の例が示すよう に,dim 次元となります。

Chapter 18: 行列の操作145 cat (4, ones(2, 2), zeros (2, 2)) ) ans = ans(:,:,1,1) = 1 1 1 1 ans(:,:,1,2) = 0 0 0 0

horzcat (array1, array2, . . . , arrayN) 編集

                                                           [Built-in Function]

N 個の配列オブジェクト,array1,array2,. . . ,arrayN を次元2 に沿って水平方向へ連結 したものを返します。

vertcat (array1, array2, . . . , arrayN) 編集

                                                           [Built-in Function]

N 個の配列オブジェクト,array1,array2,. . . ,arrayN を次元1 に沿って垂直方向へ連結 したものを返します。

permute (a, perm) 編集

                                                           [Built-in Function]

N 次元の配列オブジェクトa に対するgeneralized transpose を返します。 置換ベクトルperm は, 1:ndims(a)の要素を含んでいなければならない(どのような順でも良いが,各要素は1 度だ け現れなければならない)。

ipermute (a, iperm) 編集

                                                           [Built-in Function]

permuteの逆関数です。 以下の式, ipermute (permute (a, perm), perm) は,元の配列a を返します。

reshape (a, m, n, . . . ) 編集

                                                           [Function File]

reshape (a, siz) 編集

                                                           [Function File] 行列a の各要素を組み替え,与えられた次元となる行列を返します。 その行列の要素は,行要素が 連続であるもの(column-major;Fortran の配列が格納されているような順序)としてアク セスされます。

以下に例を挙げる。

reshape ([1, 2, 3, 4], 2, 2) ) 1 3 2 4 もとの行列における全要素数は,新しい行列の総要素数と一致していなければならない。

返される行列が1 つの次元しか持たないことは起こり得ず,引数が空であるという警告がなさ れる。


y = circshift (x, n) 編集

                                                           [Function File]

配列x を循環シフトします。 n は,x の次元数よりも大きくない整数のベクトルでなければなら ない。 n の値は,正にも負にもなります。 これは,ある値またはx がシフトされる方向を決定します。

もしn の要素がゼロならば,対応するx の次元はシフトされません。 たとえば,以下のように なります。

x = [1, 2, 3; 4, 5, 6, 7, 8, 9]; circshift (x, 1) ) 7, 8, 9 1, 2, 3 4, 5, 6 circshift (x, -2) ) 7, 8, 9 1, 2, 3 4, 5, 6 circshift (x, [0,1]) ) 3, 1, 2 6, 4, 5 9, 7, 8

y = shiftdim (x, n) 編集

                                                           [Function File]

[y, ns] = shiftdim (x) 編集

                                                           [Function File] x の次元を,n だけずらす(シフトする)。 ここでn は整数のスカラでなければなりません。 n が 正のとき,x の次元は左にシフトされ,前方の次元は末尾側に循環します。 もしn が負ならば,, x の次元は右にシフトされ,n 個の先立つsingleton dimensions を加えます。

たとえば,以下のようになります。

x = ones (1, 2, 3); size (shiftdim (x, -1)) ) [2, 3, 1] size (shiftdim (x, 1)) ) [1, 1, 2, 3] [b, ns] = shiftdim (x); ) b = [1, 1, 1; 1, 1, 1] ) ns = 1

shift (x, b) 編集

                                                           [Function File]

shift (x, b, dim) 編集

                                                           [Function File] もしx がベクトルならば,x 要素の長さb だけ循環シフトします。

もしx が行列ならば,x の各列に対して同じことをします。 もしオプション引数dim を与えると, この次元に沿って処理を行う。

[s, i] = sort (x) 編集

                                                           [Loadable Function]

[s, i] = sort (x, dim) 編集

                                                           [Loadable Function]

[s, i] = sort (x, mode) 編集

                                                           [Loadable Function]

[s, i] = sort (x, dim, mode) 編集

                                                           [Loadable Function]

x の要素を昇順で並べ替えたコピーを返します。 行列に対しては,sortは各列について要素を並びかえす。 以下に例を挙げる。

sort ([1, 2; 2, 3; 3, 1]) ) 1 1 2 2 3 3

sort関数は,ソートされた行列における要素,元の行インデックスを含む行列を作るためにも 使用できるだろう。 たとえば,以下のようです。

[s, i] = sort ([1, 2; 2, 3; 3, 1]) ) s = 1 1 2 2 3 3 ) i = 1 3 2 1 3 2 オプション引数dim を与えると,その行列はdim によって定義された次元に沿ってソートされる。 オプション引数modeは,値がソートされる並び順を定義します。 modeがとりうる値は,‘ascend’ あるいは‘descend’ です。 等しい要素について,このインデックスは,等しい要素が元のリストに現れる順序となります。 sort関数は,文字列や文字列のセル配列をソートするために使用することもできます。 その場合は,文字列の辞書順となります。 sortにおいて使用されているアルゴリズムは,部分的に並べ替えられたリストをソートすることに最適化されています。 sort関数は,指定すべきソートキーを受け入れないので,1 回の呼び出しでは,さまざまな列に ある要素の値によって,ある行列の行を並べ替えることはできません。 1 しかし,2番めの出力を使用することにより,与えられた列における値に基づいて全行をソートすることが可能です。 以下に,2列めにある値に基づいて,行列の行をソートする例を示します。

a = [1, 2; 2, 3; 3, 1]; [s, i] = sort (a (:, 2)); a (i, :) ) 3 1 1 2 2 3

tril (a, k) 編集

                                                           [Function File]

triu (a, k) 編集

                                                           [Function File] 行列a の下三角(tril)あるいは上三角(triu)部分を抜き出し,その他の全ての要素に0 をセットすることで作られる新たな行列を返します。 2 番めの引数はオプションであり,主対角の どのくらい上の対角または下の対角にもゼロするかを指定します。

k の初期値はゼロであり,結果としてtriuとtrilは,通常は,返される行列の一部に主対角 を含みます。

もしk が負であれば,主対角の上側(tril)または下側(triu)の要素も選択します。

k の絶対値は,下側対角または上側対角の数よりも大きくなければならない。

1 たとえば,最初に1 列めの値に基づいてソートし,次に,この並び順を保ったまま,2 列めにある値に基づい てソートすることなどです。


たとえば, tril (ones (3), -1) ) 0 0 0 1 0 0 1 1 0 および tril (ones (3), 1) ) 1 1 0 1 1 1 1 1 1 となります。

vec (x) 編集

                                                           [Function File] 行列x の列を,1 列に積み上げたベクトルにして返します。

統計学ならびに経済学における行列の微分についての応用は,Magnus and Neudecker (1988) を参照してください。

vech (x) 編集

                                                           [Function File] 正方行列x の右上三角の要素を削除し,残りの要素を1 列に積み上げたベクトルにして返します。

統計学ならびに経済学における行列の微分についての応用は,Magnus and Neudecker (1988) を参照してください。

prepad (x, l, c) 編集

                                                           [Function File]

postpad (x, l, c) 編集

                                                           [Function File]

postpad (x, l, c, dim) 編集

                                                           [Function File] スカラc をベクトルx の長さがl になるまで,その先頭(末尾)に追加します。 もし3 番めの引 数が与えられなければ,0 という値が使用されます。

もしlength (x) > lならば,x の始まり(終わり)からの要素は,長さl のベクトルが得ら れるまで削除されます。

もしx が行列ならば,要素は各行に追加されたり取り除かれたりします。

もしオプション引数dim が与えられるならば,この次元に沿って操作を行う。

18.3 特殊なユーティリティ行列 編集

eye (x) 編集

                                                           [Built-in Function]

eye (n, m) 編集

                                                           [Built-in Function]

eye (. . . , class) 編集

                                                           [Built-in Function]

単位行列を返します。 1個のスカラ引数を付けて呼び出すと,eye関数は指定した次元の正方行列を返します。 もし2個のスカラを与えると,それらを行数と列数として受け入れる。 2個の要素を持つベクトルを与えると,その要素の値をそれぞれ行数および列数として受け入れる。 たとえば,以下のようになります。

eye (3) ) 1 0 0 0 1 0 0 0 1

以下の式は,全て同じ結果になります。

eye (2) ≡ eye (2, 2) ≡ eye (size ([1, 2; 3, 4])

オプション引数class は,指定したタイプの配列を返すようにします。

val = zeros (n,m, "uint8")

Matlab との互換性について,引数をつけずにeyeを呼び出すことは,1 という引数を付けて呼び出すことに等しい。

ones (x) 編集

                                                           [Built-in Function]

ones (n, m) 編集

                                                           [Built-in Function]

ones (n, m, k, . . . ) 編集

                                                           [Built-in Function]

ones (. . . , class) 編集

                                                           [Built-in Function]

その要素が全て1 であるような行列またはN 次元の配列を返します。 その引数は,eyeの引数と同じように扱われます。 全要素が全て同じ値をもつ行列を作るには,以下のような式を使うのがよい。

val_matrix = val * ones (n, m) オプション引数class は,指定したタイプの配列を返すようにします。

val = ones (n,m, "uint8")

zeros (x) 編集

                                                           [Built-in Function]

zeros (n, m) 編集

                                                           [Built-in Function]

zeros (n, m, k, . . . ) 編集

                                                           [Built-in Function]

zeros (. . . , class) 編集

                                                           [Built-in Function]

その要素が全て0 であるような行列またはN 次元の配列を返します。 その引数は,eyeの引数と同じように扱われます。 オプション引数class は,指定したタイプの配列を返すようにします。

val = zeros (n,m, "uint8")

repmat (A, m, n) 編集

                                                           [Function File]

repmat (A, [m n]) 編集

                                                           [Function File]

行列A を,行方向にm 個,列方向にn 個に並べたブロック行列を作る。 もしn が指定されなければ,m × m のブロック行列を作る。

rand (x) 編集

                                                           [Loadable Function]

rand (n, m) 編集

                                                           [Loadable Function]

rand ("seed", x) 編集

                                                           [Loadable Function]

範囲(0, 1) に一様分布する乱数を要素に持つ行列を返します。 その引数は,eyeに対する引数と同じように処理されます。 さらに,以下の式を使用することにより,乱数生成器に関するシードをセットすることができます。

rand ("seed", x)

ここでx はスカラの値です。もし,

rand ("seed")

のように呼び出すと,randは現在のシード値を返します。

randn (x) 編集

                                                           [Loadable Function]

randn (n, m) 編集

                                                           [Loadable Function]

randn ("seed", x) 編集

                                                           [Loadable Function]

正規分布する乱数を要素に持つ行列を返します。その引数は,eyeに対する引数と同じように処理されます。 さらに,以下の式を使用することにより,乱数生成器に関するシードをセットすることができます。

randn ("seed", x)

ここでx はスカラの値です。 もし,

randn ("seed")

のように呼び出すと,randは現在のシード値を返します。 randおよびrandn関数は,別の生成器を使用しています。 これは,以下のように確かめることが できます。

rand ("seed", 13); randn ("seed", 13); u = rand (100, 1); n = randn (100, 1);

および

rand ("seed", 13); randn ("seed", 13); u = zeros (100, 1); n = zeros (100, 1); for i = 1:100 u(i) = rand (); n(i) = randn (); end

は,同じ結果を返します。 通常,randおよびrandnは,その初期シードをシステムクロックから得ています。 その結果,乱数列はOctave を実行するたびに同じではありません。 もし正確に乱数列を再生成する必要が本当にあるならば,シードに特定の値をセットすればよいのです。 引数なしで呼び出すと,randとrandnは1個の乱数を返します。 randとrandn関数は,Ranlib からのFortran コードを使用します。 これは, Department of Biomathematics at The University of Texas, M.D. Anderson Cancer Center, Houston, TX 77030. のBarry W. Brown とJames Lovato

によってまとめられた,乱数値生成のためのFortranルーチンのライブラリです。

randperm (n) 編集

                                                           [Function File] 1 からn までの整数をランダムに並べた行ベクトルを返します。

diag (v, k) 編集

                                                           [Built-in Function]

ベクトルv を対角k に配置した対角行列を返します。 2 番めの引数はオプションです。 もしその引数が正であれば,そのベクトルはk 番めの上対角(super-diagonal)に配置します。 もしこれが負の値ならば,k 番めの下対角(sub-diagonal)に配置します。 k の標準設定は0 であり,そのベクトルは対角に配置されます。 たとえば,以下のようになります。

diag ([1, 2, 3], 1) ) 0 1 0 0 0 0 2 0 0 0 0 3 0 0 0 0

関数linspaceとlogspaceは,等間隔あるいは対数的に区切られた要素をもつベクトルを生成することを容易にします。 Section 4.2 [Ranges]を参照してください。

linspace (base, limit, n) 編集

                                                           [Built-in Function]

base とlimit の間を,等間隔でn 個に区切った要素をもつ行ベクトルを返します。 要素数n は,1 より大きくなければならない。 base とlimit は,その範囲に常に含まれる。 もしbase がlimit よりも大きければ,その要素は降順に格納されます。 もし点の数が指定されなければ,100 とい う値を使用します。

linspace関数は,常に行ベクトルを返します。

logspace (base, limit, n) 編集

                                                           [Function File]

linspaceと同様であるが,その値が10base から10limit まで対数的に区切られているところ が異なっています。

もしlimit が? に等しいならば,その点は10base and 10? ではなく,10base and ? の範囲になります。 これはMatlab 関数に対応した互換性を保つためのものです。

warn_neg_dim_as_zero 編集

                                                           [Built-in Variable] もしwarn_neg_dim_as_zeroの値がゼロでないならば,以下のような式に対して警告を表示 する: eye (-1) 初期値は0 です。

warn_imag_to_real 編集

                                                           [Built-in Variable] もしwarn_imag_to_realがゼロでないならば,複素数を実数に暗黙的に変換するときに警告 を表示します。 初期値は0 です。

18.4 有名な行列 編集

The following functions return famous matrix forms.

hankel (c, r) 編集

                                                           [Function File] Return the Hankel matrix constructed given the first column c, and (optionally) the last row r. If the last element of c is not the same as the first element of r, the last element of c is used. If the second argument is omitted, it is assumed to be a vector of zeros with the same size as c. A Hankel matrix formed from an m-vector c, and an n-vector r, has the elements H(i; j) = ? ci+j!1; i + j ! 1 ・ m; ri+j!m; otherwise.

hilb (n) 編集

                                                           [Function File]

オーダーnのヒルベルト行列を与えます。 ヒルベルト行列の(i,j)要素は、以下のように定義されます。

 
 

invhilb (n) 編集

                                                           [Function File]

オーダーnのヒルベルト逆行列を与えます。 これは、以下の式を持いて正確に計算できます。

Aij = !1i+j(i + j ! 1)
μ
n + i ! 1
n ! j
¶μ
n + j ! 1
n ! i
¶μ
i + j ! 2
i ! 2
¶2
= p(i)p(j)
(i + j ! 1)
where
p(k) = !1k
μ
k + n ! 1
k ! 1
¶μ
n
k

The validity of this formula can easily be checked by expanding the binomial coefficients in both formulas as factorials. It can be derived more directly via the theory of Cauchy matrices: see J. W. Demmel, Applied Numerical Linear Algebra, page 92. Compare this with the numerical calculation of inverse (hilb (n)), which suffers from the ill-conditioning of the Hilbert matrix, and the finite precision of your computer’s floating point arithmetic.

sylvester_matrix (k) 編集

                                                           [Function File] Return the Sylvester matrix of order n = 2k.

toeplitz (c, r) 編集

                                                           [Function File]

Return the Toeplitz matrix constructed given the first column c, and (optionally) the first row r. If the first element of c is not the same as the first element of r, the first element of c is used. If the second argument is omitted, the first row is taken to be the same as the first column. A square Toeplitz matrix has the form: 2 666664 c0 r1 r2 ¢ ¢ ¢ rn c1 c0 r1 ¢ ¢ ¢ rn!1 c2 c1 c0 ¢ ¢ ¢ rn!2 ... ... ... . . . ... cn cn!1 cn!2 : : : c0 3 777775

vander (c) 編集

                                                           [Function File] Return the Vandermonde matrix whose next to last column is c. A Vandermonde matrix has the form: 2 6664 cn!1 1 ¢ ¢ ¢ c21 c1 1 cn!1 2 ¢ ¢ ¢ c22 c2 1 ... . . . ... ... ... cn!1 n ¢ ¢ ¢ c2 n cn 1 3 7775