Write your own Emacs Lisp macros – a short introduction を読んだ。
- Emacsの拡張言語である Emacs Lisp のマクロ機能の記事である
cl-destructuring-bind
を使った制御は始めて知った- Rustのマクロ記事もあるようなのでそちらも読みたい
Emacs + 暗号 + 数学 + プログラム
Write your own Emacs Lisp macros – a short introduction を読んだ。
cl-destructuring-bind
を使った制御は始めて知ったAnalyzing New Unique Identifier Formats (UUIDv6, UUIDv7, and UUIDv8) を読んだ。この記事は2022年のもので少し内容が古いようだ。
Exploring Typst, a new typesetting system similar to LaTeX – jreyesr’s blog を読んだ。
かなり長い記事なので、もう一回読みたい。のこりは別の日に。 Emacsにもtypst用のパッケージもあったので試してみたい。
ThatGeoGuy – Reflecting on Transducers を読んだ。
半分程度しか読めていない。また時間を取ろう。
You don’t need a terminal emulator · Andrey Listopadov を読んだ。
async-shell-command
が有用であることを再発見したproject-compile
も使えそうプログラミングでは端末とEmacsを交互に使っていたが、Emacsで済むことが増えそうだ。
Avyならなんでもできる | Emacs JP を読んだ。Avy can do anything | Karthinks の翻訳となる。前に一回読もうとした記事だったので和訳は大変ありがたい。
さっそく以下のようによう設定してみたが、アクションが動作しなかった。
(global-set-key (kbd "M-j") 'avy-goto-char-timer)
The magic kernel には画像サイズを変更する際に使用されるアルゴリズムを紹介している記事である。
Gleam is Pragmatic | software is fun を読んだ。
use
を備えているCursed Rust — binarycat を読んだ。Rustの奇妙な箇所を指摘しているらしいが、Rust勉強中の身なのでなにが奇妙なのか分かりかねた。
正則素数を調べていると、ベルヌーイ数により正則素数を判定する記事を幾つか見つけた。
特に 非正則素数チェッカー #日曜数学会 | PPT では論文 (Harvey 2008) による高速なベルヌーイ数の計算方法が紹介されていた。
この論文のアルゴリズムを実際に実装してみたいと考えたため、C言語で実装されたアルゴリズムを論文と比較して理解に努めた。
(Harvey 2008) が提案しているアルゴリムズには以下のような特徴がある。
論文の著者の C++ 実装は以下のベージに存在するが、非常に古くコンパイルもできなかった。
上記のページに SageMath – Open-Source Mathematical Software System に導入されたとあるので、レポジトリを見ると以下の実装を発見した。こちらはコンパイル、実行まで可能であった。
コンパイルは公式のmakefileを参考に以下のようなmakefikeを自作して対応した。
CFLAGS=-O2 -DNDEBUG -DUSE_THREADS -DTHREAD_STACK_SIZE=4096 -std=c++11 bernmm-test: bernmm-test.cpp bern_modp.cpp bern_modp.h bern_rat.cpp bern_rat.h bern_modp_util.cpp bern_modp_util.h g++ $(CFLAGS) -o bernmm-test \ bernmm-test.cpp bern_modp.cpp bern_rat.cpp bern_modp_util.cpp \ -lntl -lgmp -lpthread clean: rm bernmm-test
実際にベルヌーイ数の100番目を計算して、オンライン整数列大辞典 でベルヌーイ数の100番目を確認したが一致していた。
Algorithm1 の対応するコードは以下になるようだ。
/****************************************************************************** Computing the main sum (general case) ******************************************************************************/ /* Returns (1 - g^k) B_k / 2k mod p. PRECONDITIONS: 5 <= p < NTL_SP_BOUND, p prime 2 <= k <= p-3, k even pinv = PrepMulMod(p) g = a multiplicative generator of GF(p), in [0, p) */ long bernsum_powg(long p, mulmod_t pinv, long k, long g) { long half_gm1 = (g + ((g & 1) ? 0 : p) - 1) / 2; // (g-1)/2 mod p long g_to_jm1 = 1; long g_to_km1 = PowerMod(g, k-1, p, pinv); long g_to_km1_to_j = g_to_km1; long sum = 0; muldivrem_t g_pinv = PrepMulDivRem(g, p); mulmod_precon_t g_to_km1_pinv = PrepMulModPrecon(g_to_km1, p, pinv); for (long j = 1; j <= (p-1)/2; j++) { // at this point, // g_to_jm1 holds g^(j-1) mod p // g_to_km1_to_j holds (g^(k-1))^j mod p // update g_to_jm1 and compute q = (g*(g^(j-1) mod p) - (g^j mod p)) / p long q; g_to_jm1 = MulDivRem(q, g_to_jm1, g, p, g_pinv); // compute h = -h_g(g^j) = q - (g-1)/2 long h = SubMod(q, half_gm1, p); // add h_g(g^j) * (g^(k-1))^j to running total sum = SubMod(sum, MulMod(h, g_to_km1_to_j, p, pinv), p); // update g_to_km1_to_j g_to_km1_to_j = MulModPrecon(g_to_km1_to_j, g_to_km1, p, g_to_km1_pinv); } return sum; }