X-window グラフィック
これまで Win32 用のグラフィックルーチンは作ってきましたが、X-Window 用も出来ないものかと前々から考えておりました。Fortran だけで実現しようとすると、沢山のインターフェースを用意する必要が出てきますが、Linux 系では C コンパイラは必ず入っているので、C 言語も使うことにしてハードルを下げることにします。
Bash on Windows で実行して、とりあえず、点を打てれば良しとします。
参考ページ:
linux - X11/Xlib.h not found in Ubuntu - Stack Overflow
- X-Window Graphics の基礎
http://www.cc.kyoto-su.ac.jp/~isida/Pdfs/x.pdf
実行結果
モンテカルロ法で円周率計算
gfortran / intel fortran どちらでも実行できました。
- 必要ならば
sudo apt install libx11-dev
- gfortran 実行例
gfortran plot.c plot.f90 -lX11
gfortran -c -o plot.lib plot.c ifort plot.f90 plot.lib -lX11
ソース・プログラム
C 言語プログラム plot.c
X window の open/close と 点打ちの3つのルーチンを用意します。
#include <X11/Xlib.h> #include <X11/Xutil.h> static Display *d; static Window w; static GC gc; static unsigned long white, black; void X_open(int nx, int ny) { // Open a display. d = XOpenDisplay(0); if ( !d ) return; white = WhitePixel(d, DefaultScreen(d)); black = BlackPixel(d, DefaultScreen(d)); // Create the window w = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, nx, ny, 0, black, white); XMapWindow(d, w); gc = XCreateGC(d, w, 0, 0); } void X_point(int ix, int iy) { XDrawPoint(d, w, gc, ix, iy); XFlush(d); } void X_close(void) { XFreeGC(d, gc); XDestroyWindow(d, w); XFlush(d); XCloseDisplay(d); }
Fortran プログラム plot.f90
C 言語の3つのルーチンに対するインターフェースを用意します。そこから先は Fortran だけで話が済みます。
module m_plot implicit none interface subroutine Xopen(nx, ny) bind(c, name = 'X_open') integer, value :: nx, ny end subroutine Xopen subroutine Xpoint(ix, iy) bind(c, name = 'X_point') integer, value :: ix, iy end subroutine Xpoint subroutine Xclose() bind(c, name = 'X_close') end subroutine Xclose end interface end module m_plot program plot use m_plot implicit none integer, parameter :: n = 10000, nx = 500, ny = nx real :: x(n), y(n) integer :: i, ix, iy call random_seed() call random_number(x) call random_number(y) call Xopen(nx, ny) do ix = 0, nx iy = sqrt(real(ny**2 - ix**2)) call Xpoint(ix, iy) end do do iy = 0, ny ix = sqrt(real(nx**2 - iy**2)) call Xpoint(ix, iy) end do do i = 1, n ix = nx * x(i) iy = ny * y(i) call Xpoint(ix, iy) end do print *, 'Monte-Carlo Pi=', 4 * count(x**2 + y**2 < 1.0) / real(n) print *, 'press enter' read * call Xclose() end program plot
補足[H30.7.10]
環境によっては、窓の立ち上がりが遅くて?待たねばならないようです。XFlush も乱用できません。
#include <X11/Xlib.h> #include <X11/Xutil.h> static Display* d; static Window w; static GC gc; unsigned long white, black; void X_open(int nx, int ny){ // Open a display. d = XOpenDisplay(0); if ( !d ) return; // white = WhitePixel(d, DefaultScreen(d)); black = BlackPixel(d, DefaultScreen(d)); // Create the window w = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, nx, ny, 0, black, white); XMapWindow(d, w); gc = XCreateGC(d, w, 0, 0); XFlush(d); } void X_point(int ix, int iy){ XDrawPoint(d, w, gc, ix, iy); XFlush(d); } void X_flush(){ XFlush(d); } void X_close(void){ XFreeGC(d, gc); XDestroyWindow(d, w); XFlush(d); XCloseDisplay(d); }
module m_plot implicit none interface subroutine Xopen(nx, ny) bind(c, name = 'X_open') integer, value :: nx, ny end subroutine Xopen subroutine Xpoint(ix, iy) bind(c, name = 'X_point') integer, value :: ix, iy end subroutine Xpoint subroutine Xclose() bind(c, name = 'X_close') end subroutine Xclose subroutine Xflush() bind(c, name = 'X_flush') end subroutine Xflush end interface end module m_plot program plot use m_plot implicit none integer, parameter :: n = 10000, nx = 500, ny = nx real :: x(n), y(n) integer :: i, ix, iy call random_seed() call random_number(x) call random_number(y) call Xopen(nx, ny) call sleep(1) ! non-standard do ix = 0, nx iy = sqrt(real(ny**2 - ix**2)) call Xpoint(ix, iy) end do do iy = 0, ny ix = sqrt(real(nx**2 - iy**2)) call Xpoint(ix, iy) end do call Xflush() do i = 1, n ix = nx * x(i) iy = ny * y(i) call Xpoint(ix, iy) end do call Xflush() print *, 'Monte-Carlo Pi=', 4 * count(x**2 + y**2 < 1.0) / real(n) print *, 'press enter' read * call Xclose() end program plot