スキップしてメイン コンテンツに移動

投稿

多項式 in Rust

環 R 上の多項式 R[x] とは, 有限個の R の元の組の全体 R[x] に以下の代数構造を入れたもの. 多項式 p(x) in R[x] と元 r in R の和 p(x) + r 多項式 p(x), q(x) in R[x] の和 p(x) q(x) 多項式 p(x) in R[x] と元 r in R の積 r p(x) 多項式 p(x), q(x) in R[x] の和 p(x) + q(x) 多項式 p(x) in R[x] に元 r in R を代入する: p(r) 多項式 p(x) in R[x] に多項式 q in R[x] を代入する: f(q(x)) R[x] はこの和と積に関して環をなす. より詳細な多項式環の性質については wikipedia 参照. これを Rust で実装する. ジェネリクスとトレイト境界のよい練習になった. 特に多項式への代入として環 R の元と多項式 R[x] のどちらをも許す部分で手間取った. 若干 clone を使い過ぎた気もするけど, 他にどうしようもなさそう. /// 多項式を表す構造体. #[derive(Clone, Debug, PartialEq, Eq)] pub struct Polynomial<T> {     coef: Vec<T>, } extern crate num_traits; use num_traits::Zero; use std::ops::{Add, Sub, Neg, Mul}; impl<T> Polynomial<T> where T: Clone + Zero + PartialEq {     /// 係数の配列から新しく多項式を生成する. 係数はタプルでもベクトルでもよい.     /// 係数 [ a_0, a_1, ... ] の $n$ 番目の要素が $n$ 次項の係数となる.     ///     /// 引数の配列が要素を持たない可能性を考慮し, `Polynomial::new` 関数の戻り値     /// は `Option<Polynomial>` である. 使用する前に `.unwrap()` する.     ///     ///
最近の投稿

Rust でテキストファイルのインデントを整形

インデントが不揃いなテキストファイルを整形したくなったので Rust コードを書いたお話。 いつかまた使えそうだけど保管するのが面倒なので、ここに放流しておく。 use std::fs::File; use std::io::{BufReader, BufRead, BufWriter, Write}; fn main() { // ファイル読み込み let file = File::open("input.md").unwrap(); let mut reader = BufReader::new(file); // 出力ファイルの確保 let file = File::create("output.md").unwrap(); let mut writer = BufWriter::new(file); // メインループ (各行ごとに処理) loop { // 一行ずつ読み出す let mut buf = String::new(); let num_bytes = reader.read_line(&mut buf).unwrap(); if num_bytes == 0 { // EOF に到達したらループを抜ける break; } else { // そうでないとき, 整形してファイルに書き出す. let output = format_text( buf ); writer.write(output.as_bytes()).unwrap(); } } } // 先頭が " " のとき 4 文字インデントに整形して返し, // そうでなければ入力を返す関数. fn format_text( buf: String ) -> String { if buf.chars().next() == Some(' ') { format!(&

Python 3.7.2 のソースビルド

Debian 9.7 2019-02-04 依存パッケージの導入 build-essential は当然として sudo apt install libreadline-dev libncursesw5-dev libssl-dev libsqlite3-dev libgdbm-dev libbz2-dev liblzma-dev zlib1g-dev uuid-dev libffi-dev libdb-dev tk-dev コンパイル ユーザー環境に pip つきでインストールする例. ./configure --prefix=/home/name/.local --with-ensurepip --enable-optimizations make -j4 make altinstall ただし手元の WSL 環境ではなぜかいくつかのテスト (signal 等) が終了しない (ファイアウォールのせいかと思うけれども切っても失敗した) ので, その場合フル最適化は諦めて --with-lto でリンク時の最適化だけ行う.

Emacs 26.1のソースビルド

環境: Debian 9.5 stretch x86_64 インストール先をホームディレクトリ内にすればビルド自体には管理者権限は不要. ただし必要なライブラリをインストールするためにsudoを使った. ソースのダウンロード: http://ftp.jaist.ac.jp/pub/GNU/emacs/ 依存ライブラリの導入 他に足りないライブラリがある場合は次節でconfigureしたときに教えてくれるから適宜インストールする. 手元の環境ではlibncurses5-devとlibgnutls28-devが足りないと怒られたので sudo apt install libgnutls28-dev libncurses5-dev を実行. 最近はもっぱらCUI版しか使ってないからGUIは放棄したけど, GUI版をインストールする場合は下記参照. インストール 別段難しいことはなく ./configure --prefix=/home/name/.local/ --without-x make make install でオッケー. 10分もかからなかった. これでインストール時に指定したディレクトリ (上の例だと/home/name/.local/bin) に実行ファイルが生成されるから, 普通に実行すればいい. GUI版のインストール フル機能のGUI版には追加で libgtk-3-dev , libtiff5-dev , libgif-dev , libgd-dev が必要. 適宜インストールしてconfigure時に without-x オプションを外せばよい. ただしGTK+3にディスク容量190MBくらい必要. emacsの実行ファイル自体は49MB->54MBでGUIつけてもそんなに大きくなる訳ではない.

Emacs on WSLのクリップボード

問題 手元の環境 (Debian 9.5 on Win10 1803) だけかもしれないけれども、cmdのコピペ機能(つまり右クリック)を使って Emacs on WSL にペーストしようとすると、非常に重い、とてつもなく思い。短文ならともかく500行とかコピペしようとすると数分固まる。20行くらいでも時間がかかる。そのうえ、インデントが妙なことになる。最悪。 解決策 PowerShellの Get-Clipboard コマンドを使えば、Win10のクリップボードの中身を取り出せる。そこで、PowerShellコマンドを呼び出して出力をバッファに書き込むようにすればいい。 reddit に書いてあったスクリプトを修正したものがこちら。 (defun wsl-paste () (interactive) (insert (shell-command-to-string "powershell.exe -command 'Get-Clipboard'"))) (global-set-key (kbd "C-c C-v") 'wsl-paste) これで C-c C-v でWin10のクリップボードからペーストする。 いまいち検証しきれてないけれども、 (setq x-select-enable-clipboard t) 設定と相性が悪い模様。このところGUIはほぼ使わなくなってたので、こちらを消すことで対処した。 コメント これで爆速でペーストできるようになって一件落着。VS Codeに移行するかと本気で考えたけど、やっぱりEmacsのが使いやすい。

Rustで科学技術計算 (4) Vec型の操作まとめ

https://doc.rust-lang.org/std/vec/struct.Vec.html 新しいベクタの作り方 let mut vec: Vec<f64> = Vec::new(); let mut vec: Vec<f64> = Vec::with_capacity(1024); let mut vec: Vec<f64> = vec![ 0., 1., 2., 3. ]; let mut vec: Vec<f64> = vec![ 0.; 16 ]; let mut vec = (0..16).map(|x| x as f64).collect::<Vec<f64>>(); // 連続する数字を要素とするベクタをイテレータを経由して生成 // mapの部分をいじるか, イテレータアダプタを使えばもっといろいろなことができる // https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/book/iterators.html 要素の挿入 vec.push( 3.14 ); // ベクタの最後に要素3.14を追加する vec.insert( 2, 3.14 ); // vec[2] = 3.14となるように要素を挿入し, その後ろの要素を一個ずつずらす // メソッドinsert( index, element ) はindex > vec.len()のときパニックを引き起こす vec.append( vec2 ); // ふたつのベクタを連結する (Pythonでいうリストのextend) 要素の除去 vec.remove(4); // 4番目の要素vec[3]を除去し, 後ろの要素を一個ずつ詰める vec.swap_remove(4); //4番目の要素vec[3]を除去し, 最後の要素vec[vec.len()-1]をvec[3]に入れる // メソッドswap_removeはO(1)で動作するのに対して, removeの方が時間がかかる let x: f64 = vec.pop(); // 最後の要素を取り出し, それを返す (従ってこの処理によりvec.len()

制限三体問題シミュレータ by Rust

// 制限三体問題シミュレータ // // 座標系は連星系の重心を原点とし, 平均運動nで回転する系. // 従ってe=0のとき連星は静止するが, e \neq 0も計算できる. // 連星の長半径aと平均運動nが1となる単位系を用いる. // // 必要なパラメータは // 連星の質量比 q = M_2 / M_1 // 連星の離心率 e // 計算終了時刻 t_end // と初期条件 x: [f64;3], v: [f64;3] の計九つ. 上ふたつを // コマンドライン引数としてセットすることもできる. // // use std::env; // コマンドライン引数を使用する場合はコメントアウトを外す use std::f64::consts::PI; fn main() { // パラメータの設定 // let args: Vec = env::args().collect(); // let q: f64 = args[1].parse:: ().unwrap(); // let e: f64 = args[1].parse:: ().unwrap(); let q: f64 = 0.01; let e: f64 = 0.; let t_end: f64 = 128.*PI; // 初期条件 let mut t: f64 = 0.; let mut x: [f64;3] = [ 0.5-q/(1.+q), 3f64.sqrt()/2., 0. ]; let mut v: [f64;3] = [ 0., 0., 0. ]; println!("{} {} {} {}", t, x[0], x[1], x[2] ); // アウトプット間隔 let t_output: f64 = 0.0625; let mut t_record: f64 = t_output; // 数値積分 while t < t_end { rk4( &mut t, &mut x, &mut v, [q,e] ); if t >= t_record { println!("{} {} {} {}", t, x[0], x[