改悪される実行環境
2023年8月6日(日)、AtCoderで新ジャッジのテストコンテストが開催された。
新ジャッジテストコンテスト -Algorithm- - AtCoder
新ジャッジテストコンテスト -Heuristic- - AtCoder
これのHeuristicで sqrt
関数を使おうとした所、コンパイルエラーになった。
コードテストで発見したのでこれの提出リンクは無いが、Algorithmでも再現した。
提出 #44342804 - 新ジャッジテストコンテスト -Algorithm-
/usr/bin/ld: /tmp/ccQQlh1z.o: in function `main':
Main.c:(.text.startup+0x68): undefined reference to `sqrt'
/usr/bin/ld: Main.c:(.text.startup+0x88): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
過去の問題では普通に sqrt
関数を使えているので、新仕様での改悪で間違い無さそうだ。
提出 #33735452 - デンソークリエイトプログラミングコンテスト2022(AtCoder Beginner Contest 239)
質問を投げようかとも思ったが、よく見ると
バージョンやライブラリなどに関する要望の受付は終了いたしましたので、お答え出来ません。
とトップの注意事項で明示されている。
残念だなあ。
後の祭り
2023年3月~7月にかけて、言語の要望が募集されていた。
Language Test 202301 - AtCoder
今回の件を受けて確認すると、ここでもコンパイルエラーが再現した。
提出 #44347622 - Language Test 202301
とくに言語を追加してほしいという希望はなかったのであまり気にとめていなかったが、今思えばちゃんと確認しておくべきだった。
対策
標準ライブラリの数学関数 (たとえば sin
、cos
、sqrt
、atan2
などは使いたくなる機会がありそう) は使えなくなってしまうようだが、多くのx86環境ではx87という浮動小数点計算機能がある。
これを使うことで、標準ライブラリに頼らず、かつ自前での実装もせずに数学関数を使うことができる。
たとえば以下のサイトが役立ちそうである。
- x87 instruction setを使う - Qiita
- Mirror of: Into the Void: x86 Instruction Set Reference
- gccのx86インラインアセンブリに関して
基本的には、以下の流れで数学関数を用いることができる。
数学関数の計算は、以下の命令で行うことができる。
実際に組み込んでみた。
double x87_sin(double angle) {
double res;
__asm__ __volatile__(
"fldl %1\n\t"
"fsin\n\t"
"fstpl %0\n\t"
: "=m"(res) : "m"(angle));
return res;
}
double x87_cos(double angle) {
double res;
__asm__ __volatile__(
"fldl %1\n\t"
"fcos\n\t"
"fstpl %0\n\t"
: "=m"(res) : "m"(angle));
return res;
}
void x87_sincos(double* sin_res, double* cos_res, double angle) {
__asm__ __volatile__(
"fldl %2\n\t"
"fsincos\n\t"
"fstpl %1\n\t"
"fstpl %0\n\t"
: "=m"(*sin_res), "=m"(*cos_res) : "m"(angle));
}
double x87_sqrt(double value) {
double res;
__asm__ __volatile__(
"fldl %1\n\t"
"fsqrt\n\t"
"fstpl %0\n\t"
: "=m"(res) : "m"(value));
return res;
}
double x87_atan2(double y, double x) {
double res;
__asm__ __volatile__(
"fldl %1\n\t"
"fldl %2\n\t"
"fpatan\n\t"
"fstpl %0\n\t"
: "=m"(res) : "m"(y), "m"(x));
return res;
}
この x87_sqrt
関数は、新環境でも使えるようである。
提出 #44348412 - 新ジャッジテストコンテスト -Algorithm-
また、旧環境ではあるが、sin
、cos
、sqrt
、atan2
関数を用いている以前の提出
の数学関数を今回用意した関数に置き換えても、正解になった。
免責
最低限の動作確認は行ったが、今回用意した関数が正しく動作する保証はできない。
さらに、AtCoderのルールやLanguage Testのスプレッドシートを確認したが、CPUにx86が使われるという保証は発見できなかった。
x86でないCPUが使われた場合、今回用意した関数は利用できなくなる可能性が高いと思われる。
(エミュレーションなどが行われる可能性もあるため、利用できないと断言はできない)
今回用意した関数を使用した結果、コンテストにおけるペナルティやタイムロスなどの不利益、またはその他の損害が発生しても、筆者は責任を負わない。
使用する場合は自己責任でお願いする。
教訓
次に言語のアップデートがあるときは、ちゃんと確認しよう。
今回、今までgccとclangの2種類あったC言語がgccだけに減らされているし、放置すると次は0種類にされるかもしれない…