→文書への張り込み
(ページの作成:「== Octave入門 == Octave(正確にはGNU Octave)は行列・ベクトルの数値演算を行なうことのできる,コマンドラインインタフェース...」) |
|||
(2人の利用者による、間の8版が非表示) | |||
1行目: | 1行目: | ||
Octave(正確にはGNU Octave)は行列・ベクトルの数値演算を行なうことのできる,コマンドラインインタフェースを備えたフリーの汎用演算ソフトです.本家webサイトは | Octave(正確にはGNU Octave)は行列・ベクトルの数値演算を行なうことのできる,コマンドラインインタフェースを備えたフリーの汎用演算ソフトです.本家webサイトは http://www.octave.org/ です. | ||
Octave自体に組み込まれている関数やコマンドは基本的なものに限られていますが,多くの関数やコマンドを世界中の人が開発し,公開するプロジェクトがあります( | Octave自体に組み込まれている関数やコマンドは基本的なものに限られていますが,多くの関数やコマンドを世界中の人が開発し,公開するプロジェクトがあります( http://octave.sourceforge.net/ ).その成果はOctave-forgeというパッケージとして公開されています.研究室のマシンにインストールされているのもOctave-forgeパッケージです. | ||
== 基本操作 == | |||
=== 起動と終了 === | |||
起動はWindowsPCならスタートメニューのGNU Octave | 起動はWindowsPCならスタートメニューのGNU Octave 3.x を選びます.OS XやlinuxなどPC-unix系のシステムなら,ターミナルを開いてoctaveとタイプすればいいです.起動するとターミナルが開き,コマンドを受け付ける状態になります.終了はexitとタイプします. | ||
=== ヘルプ === | |||
Octave上で関数やコマンドのヘルプを表示するには, | Octave上で関数やコマンドのヘルプを表示するには, | ||
24行目: | 23行目: | ||
とすると,キーワード(関数名など何でも良い)に関連した説明が表示されます. | とすると,キーワード(関数名など何でも良い)に関連した説明が表示されます. | ||
=== カレント・ディレクトリ === | |||
Octaveを起動して開くウィンドウにコマンドを打ち込んでいけば利用はできますが,結果をファイルとして残したり,実験データなとを読み込む場合にはディレクトリを意識する必要があります.今現在自分が作業しているディレクトリをカレント・ディレクトリと呼びます.unix系のOSならすでに各自のホーム・ディレクトリで作業し始めているので,問題は少ないですが,Windowsの場合は注意が必要です. | Octaveを起動して開くウィンドウにコマンドを打ち込んでいけば利用はできますが,結果をファイルとして残したり,実験データなとを読み込む場合にはディレクトリを意識する必要があります.今現在自分が作業しているディレクトリをカレント・ディレクトリと呼びます.unix系のOSならすでに各自のホーム・ディレクトリで作業し始めているので,問題は少ないですが,Windowsの場合は注意が必要です. | ||
39行目: | 38行目: | ||
== 基本数値・算術コマンド == | |||
=== 数値,ベクトル・行列の表現の仕方 === | |||
Octave上でスカラー定数は, | Octave上でスカラー定数は, | ||
57行目: | 56行目: | ||
のように入力します.要素は実数や複素数,後述の変数(数式)でも構いません.また,要素の区切りはスペース以外にカンマ(, )でも大丈夫です.行列はベクトルをセミコロン(; )で改行しながら入力するというイメージです. | のように入力します.要素は実数や複素数,後述の変数(数式)でも構いません.また,要素の区切りはスペース以外にカンマ(, )でも大丈夫です.行列はベクトルをセミコロン(; )で改行しながら入力するというイメージです. | ||
=== 変数 === | |||
Octave上では,実数,複素数,行列,ベクトルの区別なく変数に格納することができます.変数名は英文字で始まる英数字の文字列で,大文字小文字の区別をします. | Octave上では,実数,複素数,行列,ベクトルの区別なく変数に格納することができます.変数名は英文字で始まる英数字の文字列で,大文字小文字の区別をします. | ||
79行目: | 78行目: | ||
のように,特定の変数だけをクリアすることもできます. | のように,特定の変数だけをクリアすることもできます. | ||
=== コマンドライン上での入力と表示 === | |||
基本的に数値やコマンド・関数をタイプしてenterを押せば,入力されて実行されます.標準状態では結果がすぐ表示されますが,表示させないようにすることもできます.一番簡単な方法は行の最後にセミコロン(; )をつけることです. | 基本的に数値やコマンド・関数をタイプしてenterを押せば,入力されて実行されます.標準状態では結果がすぐ表示されますが,表示させないようにすることもできます.一番簡単な方法は行の最後にセミコロン(; )をつけることです. | ||
88行目: | 87行目: | ||
>> a =[1 2 3]; | >> a =[1 2 3]; | ||
=== 四則演算,超越関数 === | |||
四則演算は実数,複素数,行列,ベクトルおよびそれらを内容とする変数に対して実行可能です.ただし,行列,ベクトルの除算は以下のような意味となります. | 四則演算は実数,複素数,行列,ベクトルおよびそれらを内容とする変数に対して実行可能です.ただし,行列,ベクトルの除算は以下のような意味となります. | ||
191行目: | 190行目: | ||
== グラフ == | |||
Octaveではグラフ機能はgnuplotを呼び出して利用しているので,細かなコントロールにはgnuplotのコマンドを理解する必要があります.しかし,octave-forgeのパッケージにはMATLABとの互換性を高めるため,グラフ関連のコマンドが多く追加されていて(例えばgridなど),だいぶ使いやすくなっています. | Octaveではグラフ機能はgnuplotを呼び出して利用しているので,細かなコントロールにはgnuplotのコマンドを理解する必要があります.しかし,octave-forgeのパッケージにはMATLABとの互換性を高めるため,グラフ関連のコマンドが多く追加されていて(例えばgridなど),だいぶ使いやすくなっています. | ||
=== plot関数の基本 === | |||
1次元のベクトルの組を2次元グラフに表現できます.ベクトルXをx軸,Yをy軸としてグラフ化するには,plot(X, Y)とします. | 1次元のベクトルの組を2次元グラフに表現できます.ベクトルXをx軸,Yをy軸としてグラフ化するには,plot(X, Y)とします. | ||
205行目: | 204行目: | ||
線の種類や色を変えたいときは,変数の後に続けてダブルコーテーションかシングルコーテーションでくくったフォーマット文字列を書けばいいです. | 線の種類や色を変えたいときは,変数の後に続けてダブルコーテーションかシングルコーテーションでくくったフォーマット文字列を書けばいいです. | ||
>> plot(X, Y, | >> plot(X, Y, 'b+') | ||
この例は,色をblueとし,線ではなくて+記号でプロットします.その他の色や線類はhelpで調べて下さい. | この例は,色をblueとし,線ではなくて+記号でプロットします.その他の色や線類はhelpで調べて下さい. | ||
211行目: | 210行目: | ||
なお,plot関数の引き数としてx軸, y軸, 線種を繰り返し用いることで複数のグラフを重ね書きすることもできます. | なお,plot関数の引き数としてx軸, y軸, 線種を繰り返し用いることで複数のグラフを重ね書きすることもできます. | ||
>> plot(X1, Y1, | >> plot(X1, Y1, 'r-', X2, Y2, 'g-') | ||
=== その他の装飾 === | |||
plot関数でグラフを書いた後,xlabel, ylabel, titile関数で軸ラベルとタイトルをつけることができます. | plot関数でグラフを書いた後,xlabel, ylabel, titile関数で軸ラベルとタイトルをつけることができます. | ||
>> xlabel( | >> xlabel('time (s)') | ||
>> ylabel( | >> ylabel('sin(x)') | ||
>> title( | >> title('This is a sample graph') | ||
また,グリッド(格子)をつけるには, | また,グリッド(格子)をつけるには, | ||
228行目: | 227行目: | ||
プロットの説明(凡例)が右上に自動的にでますが,これはlegend関数で変更できます.不要な場合は, | プロットの説明(凡例)が右上に自動的にでますが,これはlegend関数で変更できます.不要な場合は, | ||
>> legend( | >> legend('off') | ||
で消えます. | で消えます. | ||
なお,環境によってはlegend関数がうまく機能しない場合があります.その場合は,plot関数でプロットする際に,色や線種を指定するのと同時に説明文をセミコロンで囲むことで指定できます. | なお,環境によってはlegend関数がうまく機能しない場合があります.その場合は,plot関数でプロットする際に,色や線種を指定するのと同時に説明文をセミコロンで囲むことで指定できます. | ||
>> plot(X, Y, | >> plot(X, Y, 'r-;sin;', X, Z, 'g-;cos;') | ||
242行目: | 241行目: | ||
とすることで,x軸y軸それぞれの範囲を指定できます.なお,axis関数はグラフをプロットした後に実行しても効果がないので,後から実行した場合はもう一度プロットし直す必要があります.また,自動調整に戻す場合は, | とすることで,x軸y軸それぞれの範囲を指定できます.なお,axis関数はグラフをプロットした後に実行しても効果がないので,後から実行した場合はもう一度プロットし直す必要があります.また,自動調整に戻す場合は, | ||
>> axis( | >> axis('auto') | ||
とします. | とします. | ||
=== 対数グラフ === | |||
plot関数のかわりにsemilogx関数を使うと片対数(x軸だけ対数)のグラフになります.両対数はloglog関数です.線種の指定などはplot関数と同じです | plot関数のかわりにsemilogx関数を使うと片対数(x軸だけ対数)のグラフになります.両対数はloglog関数です.線種の指定などはplot関数と同じです | ||
=== 文書への張り込み === | |||
グラフをTeX文書などに取り込む場合は,EPSファイルとしていったん保存します.print関数を使うことでファイルに出力できます. | グラフをTeX文書などに取り込む場合は,EPSファイルとしていったん保存します.print関数を使うことでファイルに出力できます. | ||
>> print( | >> print('test.eps','-depsc2') | ||
一つ目の引数はファイル名で,二つ目はファイルの形式を指定するオプションです.- | 一つ目の引数はファイル名で,二つ目はファイルの形式を指定するオプションです.-dに引き続いて,epsc2はEPSのカラーでレベル2と言う意味です. | ||
== スクリプトファイル == | |||
=== スクリプトファイル(mファイル)とは === | |||
これまでのようにコマンドを1行1行打ち込んでいっても作業はできますが,ある程度まとまった処理や繰り返し試行する処理などは,面倒ですし,間違いも見つかりにくいです.そこで,その一連の作業をmファイルというテキストファイルとして保存しておくと,実行や修正が非常に楽になります. | これまでのようにコマンドを1行1行打ち込んでいっても作業はできますが,ある程度まとまった処理や繰り返し試行する処理などは,面倒ですし,間違いも見つかりにくいです.そこで,その一連の作業をmファイルというテキストファイルとして保存しておくと,実行や修正が非常に楽になります. | ||
=== mファイルの作成と実行 === | |||
mファイルはただのテキストファイルですから,メモ帳など使い慣れたエディタで作成・編集できます.保存する場所は自分のホームディレクトリ以下の適当なところとします. | mファイルはただのテキストファイルですから,メモ帳など使い慣れたエディタで作成・編集できます.保存する場所は自分のホームディレクトリ以下の適当なところとします. | ||
ファイル名は変数名と同じく数字で始まらない英数字とし,拡張子は.mとします.実行はファイル名から.mを抜いた部分を入力すればいいです.カレント・ディレクトリにその名前のファイルがあれば実行されます. | ファイル名は変数名と同じく数字で始まらない英数字とし,拡張子は.mとします.実行はファイル名から.mを抜いた部分を入力すればいいです.カレント・ディレクトリにその名前のファイルがあれば実行されます. | ||
=== path === | |||
自作のmファイルをあるディレクトリにまとめておき,カレント・ディレクトリがどこであっても,そのmファイルを実行できるようにすることができます.汎用性の高い関数やツールを作り,将来にわたり使いたい場合に便利です. | 自作のmファイルをあるディレクトリにまとめておき,カレント・ディレクトリがどこであっても,そのmファイルを実行できるようにすることができます.汎用性の高い関数やツールを作り,将来にわたり使いたい場合に便利です. | ||
277行目: | 275行目: | ||
とすることで現在のpath設定が表示されます.(ゼミ開講現在,Windows環境ではなぜか表示されません.)これらに,自身のディレクトリを''追加''するには以下のようにします. | とすることで現在のpath設定が表示されます.(ゼミ開講現在,Windows環境ではなぜか表示されません.)これらに,自身のディレクトリを''追加''するには以下のようにします. | ||
>> path(path, | >> path(path, '/cygdrive/h/Documents/m_files/') | ||
この例では,Documentsディレクトリの下のm_filesディレクトリにmファイルを入れておけば,カレントディレクトリがどこであっても実行できるようになります.なお,間違って | この例では,Documentsディレクトリの下のm_filesディレクトリにmファイルを入れておけば,カレントディレクトリがどこであっても実行できるようになります.なお,間違って | ||
>> path( | >> path('/cygdrive/h/Documents/m_files/') | ||
とすると,pathがm_filesだけになり,自作のコマンド以外は全く実行できなくなりますので,注意です.(一度Octaveを終了して再度起動すれば元に戻ります) | とすると,pathがm_filesだけになり,自作のコマンド以外は全く実行できなくなりますので,注意です.(一度Octaveを終了して再度起動すれば元に戻ります) | ||
== 制御系解析・設計コマンド類 == | |||
=== システムの表現 === | |||
Octave上では,システムは伝達関数表現(分子分母それぞれの係数を降べきの順に並べた2つのベクトルの組),状態空間表現(4つの行列の組),システム行列表現(1つの行列で表現)のいずれかで表現できます.しかし,後述する解析や設計の関数はシステム行列表現を引数としてとるので,その他の表現で与えられた物をシステム行列表現に変換する必要があります.変換を行う関数はtf()です(古いバージョンのoctaveの場合はtf2sys). | Octave上では,システムは伝達関数表現(分子分母それぞれの係数を降べきの順に並べた2つのベクトルの組),状態空間表現(4つの行列の組),システム行列表現(1つの行列で表現)のいずれかで表現できます.しかし,後述する解析や設計の関数はシステム行列表現を引数としてとるので,その他の表現で与えられた物をシステム行列表現に変換する必要があります.変換を行う関数はtf()です(古いバージョンのoctaveの場合はtf2sys). | ||
296行目: | 294行目: | ||
=== 周波数応答の計算 === | |||
代表例としてボード線図を書いてみます.関数はbodeを利用します. | 代表例としてボード線図を書いてみます.関数はbodeを利用します. | ||
316行目: | 314行目: | ||
== データファイルの取り扱い == | |||
=== 全変数の保存と復元 === | |||
一旦Octaveを終了して次回続きをやりたいときなど,変数の内容をとっておきたいことがあります.スクリプトファイルとして作業手順を保存することはできますが,時間のかかる計算が必要な場合その度に計算し直すのも面倒です. | 一旦Octaveを終了して次回続きをやりたいときなど,変数の内容をとっておきたいことがあります.スクリプトファイルとして作業手順を保存することはできますが,時間のかかる計算が必要な場合その度に計算し直すのも面倒です. | ||
330行目: | 328行目: | ||
>> a = [1 2 3]; | >> a = [1 2 3]; | ||
>> B = [1 2 3; 4 5 6; 7 8 9]; | >> B = [1 2 3; 4 5 6; 7 8 9]; | ||
>> save - | >> save -text alldata.dat | ||
とすれば,ファイルalldata.datに,現在のすべての変数の内容がアスキー形式(テキスト形式)で書き出されます.メモ帳など適当なテキストエディタで内容を確認できるはずです.なお,バイナリ形式で保存する場合は-binaryというオプションをつけます.テキスト形式にくらべて精度が高く,ファイルサイズも小さくなります. | とすれば,ファイルalldata.datに,現在のすべての変数の内容がアスキー形式(テキスト形式)で書き出されます.メモ帳など適当なテキストエディタで内容を確認できるはずです.なお,バイナリ形式で保存する場合は-binaryというオプションをつけます.テキスト形式にくらべて精度が高く,ファイルサイズも小さくなります. | ||
345行目: | 343行目: | ||
のように-forceオプションをつけます. | のように-forceオプションをつけます. | ||
=== 指定した変数だけの保存と復元 === | |||
すべての変数を保存する必要がない場合や,一つのファイルに保存してある複数の変数のうちのいくつかだけを復元したい場合もあります.そのような場合,saveやloadコマンドでファイル名の後に変数名を羅列します. | すべての変数を保存する必要がない場合や,一つのファイルに保存してある複数の変数のうちのいくつかだけを復元したい場合もあります.そのような場合,saveやloadコマンドでファイル名の後に変数名を羅列します. | ||
355行目: | 353行目: | ||
できます.なお,先と同様にloadコマンドではファイルの形式は自動的に判別されるので,オプションは通常不要です. | できます.なお,先と同様にloadコマンドではファイルの形式は自動的に判別されるので,オプションは通常不要です. | ||
=== タブまたはスペース区切りのテキストデータの読み込み === | |||
実験結果をOctaveで処理したりグラフ化する場合,実験用のプログラム(通常はC言語などで自作するでしょう)側はOctaveに渡したいデータをテキスト形式のファイルとして保存するのが簡単です. | 実験結果をOctaveで処理したりグラフ化する場合,実験用のプログラム(通常はC言語などで自作するでしょう)側はOctaveに渡したいデータをテキスト形式のファイルとして保存するのが簡単です. | ||
saveコマンドに- | saveコマンドに-textオプションをつけて保存したファイルは,一般に複数の変数について,変数名,タイプ,行サイズ,列サイズ,数列が列挙されています.このフォーマットを再現するようにプログラムを自作すれば,loadコマンドで先と同様に読み込めます.しかし,通常はタブまたはスペース区切りの数列だけのテキストファイルで保存しておき,Octave側で必要に応じて各変数に切り分けることが多いです. | ||
例えば,次のような内容のテキストファイルresult.txtがカレントディレクトリにあるとします. | 例えば,次のような内容のテキストファイルresult.txtがカレントディレクトリにあるとします. | ||
383行目: | 381行目: | ||
>> y = result(:,3); | >> y = result(:,3); | ||
=== 他のアプリケーション向けのテキストデータ書き出し === | |||
Octaveでのシミュレーションや解析の結果を他のアプリケーション(例えばExcelなどのスプレッドシートやIgorやNGraphといったグラフ化ソフトなど)に渡したい時はテキストファイルとして書き出します.ただし,save - | Octaveでのシミュレーションや解析の結果を他のアプリケーション(例えばExcelなどのスプレッドシートやIgorやNGraphといったグラフ化ソフトなど)に渡したい時はテキストファイルとして書き出します.ただし,save -text 変数名 変数名 ...で保存できるOctave固有のフォーマットのファイルをそのまま読み込めるとは限らないので,以下のような工夫が必要です. | ||
まず,書き出したい変数を結合して一つの変数にしておきます.このときサイズ(行数)が揃っていないとエラーになりますので,揃えるか,一緒にすることをあきらめて別のファイルにするか決めます.シミュレーション結果などは,時刻ベクトル,入力ベクトル,出力ベクトルなどが大抵同じ行数でしょうから,まとめて1つの行列にできるでしょう. | まず,書き出したい変数を結合して一つの変数にしておきます.このときサイズ(行数)が揃っていないとエラーになりますので,揃えるか,一緒にすることをあきらめて別のファイルにするか決めます.シミュレーション結果などは,時刻ベクトル,入力ベクトル,出力ベクトルなどが大抵同じ行数でしょうから,まとめて1つの行列にできるでしょう. | ||
392行目: | 390行目: | ||
>> outfile = [t u y]; | >> outfile = [t u y]; | ||
>> save - | >> save -text outfile.txt outfile | ||
保存されたファイルの最初の5行は,日付や変数名,サイズなどの情報で先頭文字が#になっています.受け取る側のアプリケーションでその行を無視するように設定できれば,そのまま使用できますが,そうでない場合はテキストエディタで削除してから読み込ませる必要あります. | 保存されたファイルの最初の5行は,日付や変数名,サイズなどの情報で先頭文字が#になっています.受け取る側のアプリケーションでその行を無視するように設定できれば,そのまま使用できますが,そうでない場合はテキストエディタで削除してから読み込ませる必要あります. | ||
最初から先頭の不要な行をつけないで保存するには,-textではなく,-asciiオプションを使用します. | |||
>> | >> save -ascii outfile.txt outfile | ||
== Octaveスクリプトのいろいろ == | |||
=== キーボード入力,画面への出力 === | |||
スクリプト実行中にキーボードから数値や文字列を入力させるにはinput命令を使います.同時にメッセージとして表示させる文字列を指定することができます. | スクリプト実行中にキーボードから数値や文字列を入力させるにはinput命令を使います.同時にメッセージとして表示させる文字列を指定することができます. | ||
420行目: | 406行目: | ||
画面への出力はC言語と同じくprintf命令を使います. | 画面への出力はC言語と同じくprintf命令を使います. | ||
a = input( | a = input('Please input a: '); | ||
printf( | printf('a = %g\n',a); | ||
=== 条件判定 === | |||
条件判定にはC言語と同じくif命令が利用できます.ただし,C言語のように括弧で条件式は囲みません.また,中括弧({ })は使用せず,endifでif命令の範囲を指定します.さらに,C言語ではelseとifを分けて書きますが,Octaveではelseifと続けて書きます. | 条件判定にはC言語と同じくif命令が利用できます.ただし,C言語のように括弧で条件式は囲みません.また,中括弧({ })は使用せず,endifでif命令の範囲を指定します.さらに,C言語ではelseとifを分けて書きますが,Octaveではelseifと続けて書きます. | ||
a = input( | a = input('Please input a: '); | ||
if a > 0 | if a > 0 | ||
printf( | printf('a > 0\n'); | ||
elseif a > -5 | elseif a > -5 | ||
printf( | printf('-5 < a <= 0\n'); | ||
else | else | ||
printf( | printf('a < = -5\n'); | ||
end | |||
=== 繰り返し === | |||
==== while命令 ==== | |||
while命令は条件が成り立っている間,命令群を繰り返します.やはり中括弧は用いずに,命令群の終わりはendwhileで指定します.なお,中断は\break命令です. | while命令は条件が成り立っている間,命令群を繰り返します.やはり中括弧は用いずに,命令群の終わりはendwhileで指定します.なお,中断は\break命令です. | ||
444行目: | 430行目: | ||
while 条件 | while 条件 | ||
命令群 | 命令群 | ||
end | |||
sum = 0; | sum = 0; | ||
while sum < 100 | while sum < 100 | ||
a = input( | a = input('Please input a: '); | ||
sum = sum + a; | sum = sum + a; | ||
printf( | printf('sum = %g\n', sum); | ||
end | |||
==== for命令 ==== | |||
for命令はC言語のforを限定的にした感じで,インデックスとする変数の初期値,増分,終値を指定して命令群を繰り返します.命令群の終わりはendfor,中断はbreakなのはwhileと同様です.なお,増分を省略すると1ととられます. | for命令はC言語のforを限定的にした感じで,インデックスとする変数の初期値,増分,終値を指定して命令群を繰り返します.命令群の終わりはendfor,中断はbreakなのはwhileと同様です.なお,増分を省略すると1ととられます. | ||
467行目: | 453行目: | ||
if sum >100 | if sum >100 | ||
break | break | ||
end | |||
end | |||
printf( | printf('On i = %d, sum = %g\n', i, sum); | ||
初期値:増分:終値という書き方は,ベクトルの作成にも使えますので覚えておくと便利です. | 初期値:増分:終値という書き方は,ベクトルの作成にも使えますので覚えておくと便利です. | ||
=== ユーザ定義関数 === | |||
スクリプト内でユーザ独自の関数を定義したり,別ファイルで定義したりできます. | スクリプト内でユーザ独自の関数を定義したり,別ファイルで定義したりできます. | ||
483行目: | 469行目: | ||
% 関数の説明 | % 関数の説明 | ||
命令群 | 命令群 | ||
end | |||
関数の終わりを示すためにendfunction命令が必要です.また,function命令直後のコメント文はhelpで表示されるので,簡単な説明を入れておくと良いでしょう. | 関数の終わりを示すためにendfunction命令が必要です.また,function命令直後のコメント文はhelpで表示されるので,簡単な説明を入れておくと良いでしょう. | ||
別ファイルで関数を定義する場合は,ファイル名を関数名に拡張子. | 別ファイルで関数を定義する場合は,ファイル名を関数名に拡張子.mをつけます.関数名は既存の関数とかぶらないように,オリジナルなものになるよう注意が必要です. | ||
なお,C言語の関数と同様に,関数内で変数はローカル変数となるので,変数名がかぶっても内容は別物となることに注意が必要です. | なお,C言語の関数と同様に,関数内で変数はローカル変数となるので,変数名がかぶっても内容は別物となることに注意が必要です. | ||
500行目: | 486行目: | ||
c = a - b; | c = a - b; | ||
err = c' * c; | err = c' * c; | ||
end |