MENU

AtCoder新ジャッジにC言語で数学関数(libm)を使うためのおまじない

AtCoder新ジャッジにおいて C言語コンパイルオプション -lm がついておらず、数学関数(libm) を使う事が出来ません。(引数が定数の場合最適化によって使えてしまう事もあります)そこでこれらのコードを実行するために x87アセンブリから使う方法やlibmを動的ロードする方法が有志によって見つけられました。

qiita.com

そこで、これのうち libm の動的リロードをマクロにし、三行のスニペットにしました! LOAD_LIBM マクロを追加すれば同様に追加することができます。 また、これらの引数/戻り値が double 以外の関数を扱いたい場合やエラー処理をきちんとしたい人はよしなに書き換えてもらえるとありがたいです。 良さげな改良がある場合は twitter などで教えてくれると喜びます(この記事からリンクを貼ったりしたいです)。

#include <dlfcn.h>
#define LOAD_LIBM(FUNC) double (*FUNC)(double);__attribute__((constructor))static void loadlibm_##FUNC(){FUNC=dlsym(dlopen("libm.so.6",RTLD_LAZY),#FUNC);}
LOAD_LIBM(sqrt); LOAD_LIBM(sin); LOAD_LIBM(cos);LOAD_LIBM(tan); LOAD_LIBM(atan2);

#include <dlfcn.h>
#define LOAD_LIBM(FUNC) double (*FUNC)(double);__attribute__((constructor))static void loadlibm_##FUNC(){FUNC=dlsym(dlopen("libm.so.6",RTLD_LAZY),#FUNC);}
LOAD_LIBM(sqrt); LOAD_LIBM(sin); LOAD_LIBM(cos);LOAD_LIBM(tan); LOAD_LIBM(atan2);

#include<stdio.h>

int main(){
  double a;
  scanf("%lf",&a);
  printf("sqrt(%lf) = %lf\n", a, sqrt(a));
  printf("sin(%lf) = %lf\n", a, sin(a));
  printf("cos(%lf) = %lf\n", a, cos(a));
  printf("atan2(%lf) = %lf\n", a, atan2(a));
}
sqrt(2.000000) = 1.414214
sin(2.000000) = 0.909297
cos(2.000000) = -0.416147
atan2(2.000000) = 1.365650