日記」カテゴリーアーカイブ

Aterm MR03LNを買った

半年前から、外出先でインターネットに接続するためにIIJmioのMVNO回線とPocket WiFiの端末(GL02P)を使っていたが、このGL02Pは2年使った後なので電池が死んでいて、しかも元々イーモバイル用の端末だから、NTTドコモの一部の周波数帯に対応していない。

じゃあ新しいモバイルルーターを買おう!となるのだが、GL02P+モバイルバッテリーでも最低限には使えるし、代わりのモバイルルーター(自分の中で)第一候補のAterm MR03LNの価格が2万3千円ほどするので、なかなか買うタイミングが見つからなかった。

しかし、数日前(24日)にAterm MR03LNの価格を調べたらAmazonでタイムセールをやっていて、1万5千円と安くなっていたので、迷わずポチってしまった。しかもクレードル付き。(OCNモバイルONEのSIMとのセットだが、そっちのSIMは無視するものとする)(この記事を書いている現在は価格は元に戻ってしまったようだ)

Aterm MR03LNの製品情報はAtermMR03LN | 製品一覧 | AtermStationで見られる。自分が重視したポイントは、

  • LTE対応。(今じゃ当たり前か)
  • FOMAプラスエリアや、LTEの800MHz帯にも対応。
  • Bluetoothテザリング(PAN)に対応。(Wi-Fiより低速だが消費電力が低い)(ただ、ネットで評判を見るとそこまで期待してはいけない?)
  • IPv6対応。(IIJmioのSIMと組み合わせるとIPv6でインターネットに繋がる)

あたりか。

以下のアプリを使うと、このモバイルルーターの電波状態・バッテリー残量等を確認できる。

それから、休止状態にしたMR03LNをスマートフォンやタブレットのアプリで「リモート起動」できるようだ。しかし、「MR03LNのリモート起動」と「スマートフォン・タブレットからのWi-Fi/Bluetoothでの接続」が連携する訳ではないので、ないよりマシとはいえ、使い勝手はそこまで良くないか。(「リモート起動」した後、スマートフォン・タブレットでMR03LNに接続するまでの間、アプリからは何も操作できない状態になる)

以下、パッケージの写真。

本体、電池パック、裏蓋とクレードルの他に、ACアダプターとUSBケーブルとLANケーブルが付属するが、これらは手持ちのものを使うつもりなので、多分開封しないだろう。

そろそろ、携帯機器に付属するACアダプターとUSBケーブルが、「プリンターに付属するUSBケーブル」のポジションになっている気がするが、付属をやめる動きはないのだろうか。(Nexus 7を買った時のACアダプターとUSBケーブルも封印したままな気がする)

クレードルに装着。クレードルにはLAN端子があって、MR03LNをルーターとして使えるらしい。本体のUSB端子でパソコンにつなぐとパソコンからはネットワークインターフェースに見えるようだが、クレードルのUSB端子ではそういうのはできないようだ。充電用に「ケーブルを差す」よりは「クレードルに置く」方が楽だ。


Pocket Wifi (GL02P)と並べてみた。

MR03LNの方が縦横が大きいが、薄い。重量はそれほど変わらないが、気持ちMR03LNの方が軽い。

GL02Pにはイーモバイル時代を含めて2年半お世話になったが、これでお役御免だ。

東大入試理系数学2015第5問(解いてみた)

暇だったから[要出典]今年の東大の入試問題数学の問題に目を通してみた。問題文はこのへんこのへんで参照できるようだ。

ツイッターでの評判を見る感じ、第5問と第6問が話題になっていて、第5問は整数問題、第6問は(大学の)解析学で出てくる概念に関係あるみたいな感じだった。第5問のが問題文が短い(問題文が長いと読むのが面倒くさい)のでとりあえず第5問を解いてみる。

続きを読む

Macのストレージを空けた

今使っているMacはMacBook Proの256GBフラッシュストレージモデルで、いくらでもファイルを保存できるという感じではない。購入から1年近く経った今、90%以上の領域を使ってしまっている。そこで、使用頻度の低いファイルを外付けHDDに追い出したり、使わなくなった古いバージョンのソフトウエアを積極的に削除していくということが必要になる。

Haskell Platform

~/Library/Haskell 以下にいろいろ入っている。
$ du -h -d 2 Library/Haskell で調べた感じ、古いGHC 7.6.3が1.3GBほど占めているようだった。なので古いGHCを消す。
手順はMac OS X – HaskellWikiをみた限りでは uninstall-hs コマンドを使えばいいらしい。

$ du -h -d 2 Library/Haskell
144K	Library/Haskell/bin
 26M	Library/Haskell/doc
1.3G	Library/Haskell/ghc-7.6.3/lib
1.3G	Library/Haskell/ghc-7.6.3
3.2G	Library/Haskell/ghc-7.8.3/lib
3.2G	Library/Haskell/ghc-7.8.3
188K	Library/Haskell/logs
203M	Library/Haskell/repo-cache/hackage.haskell.org
156M	Library/Haskell/repo-cache/hdiff.luite.com
359M	Library/Haskell/repo-cache
4.9G	Library/Haskell
$ uninstall-hs -v
-- Versions found on this system

7.6.3
    /Library/Frameworks/GHC.framework/Versions/7.6.3-x86_64
    /Library/Haskell/ghc-7.6.3
    /Users/*/.ghc/x86_64-darwin-7.6.3
    /Users/*/Library/Haskell/ghc-7.6.3

7.8.3
    /Library/Frameworks/GHC.framework/Versions/7.8.3-x86_64
    /Library/Haskell/ghc-7.8.3
    /Library/Haskell/ghc-7.8.3-x86_64
    /Users/*/.ghc/x86_64-darwin-7.8.3
    /Users/*/Library/Haskell/ghc-7.8.3

-- To remove a version and all earlier: uninstall-hs thru VERSION
-- To remove only a single version:     uninstall-hs only VERSION

$ uninstall-hs only 7.6.3
-- Would remove just version 7.6.3
/Library/Frameworks/GHC.framework/Versions/7.6.3-x86_64
/Library/Haskell/ghc-7.6.3
/Users/*/.ghc/x86_64-darwin-7.6.3
/Users/*/Library/Haskell/ghc-7.6.3
/Users/*/Library/Haskell/bin/cpphs@ -> ../ghc-7.6.3/lib/cpphs-1.18.4/bin/cpphs
/usr/bin/ghc-7.6.3@ -> /Library/Frameworks/GHC.framework/Versions/7.6.3-x86_64/usr/bin/ghc-7.6.3
/usr/bin/ghc-pkg-7.6.3@ -> /Library/Frameworks/GHC.framework/Versions/7.6.3-x86_64/usr/bin/ghc-pkg-7.6.3
/usr/bin/ghci-7.6.3@ -> /Library/Frameworks/GHC.framework/Versions/7.6.3-x86_64/usr/bin/ghci-7.6.3
/usr/bin/haddock-ghc-7.6.3@ -> /Library/Frameworks/GHC.framework/Versions/7.6.3-x86_64/usr/bin/haddock-ghc-7.6.3
/usr/bin/runghc-7.6.3@ -> /Library/Frameworks/GHC.framework/Versions/7.6.3-x86_64/usr/bin/runghc-7.6.3
-- To actually remove these files, sudo run the command again with --remove
-- To generate a script to remove these files, run the command again with --script

$ sudo uninstall-hs only --remove 7.6.3
Password:
-- Removing just version 7.6.3

そもそも今インストールされているGHC 7.8.3も最新版じゃないという気がするが。

TeX Live (MacTeX)

古いTeX Live 2013が入っていたので消す。確かMacTeXで入れたような気がするので、このへんを読んでおく。普通に /usr/local/texlive/2013 を消せばいいみたい。

$ du -d 1 -h /usr/local/texlive
4.4G	/usr/local/texlive/2013
4.5G	/usr/local/texlive/2014
4.0K	/usr/local/texlive/texmf-local
8.9G	/usr/local/texlive
$ sudo rm -rf /usr/local/texlive/2013

その他

Homebrewで入っている古いソフトウエアを消したりMacPortsで入っている古いソフトウエアを消したり、Dropboxで同期しているでかくて使用頻度の低いファイルを同期しないようにしたりいろいろ

TeXを勉強したい

LaTeXではない方の)plain TeXを勉強すべしという電波を受信したので、勉強しようと思った。

じゃあ何を読んで勉強しようかという話だが、TeX Wiki内のTeX入門/マクロの作成 – TeX Wikiというページが入門として良さそうだった。

もうちょっとまじめに勉強しようとなると、TeXの本 – TeX Wikiの下の方にある

あたりを読むと良さそう。

学園祭で来場者に複素関数を教えた話

11月22日から24日にかけて行われた東京大学駒場キャンパスでの第65回駒場祭で、数学科有志による「ますらぼ」企画(@UTmathlabo)に参加していました。「ますらぼ」では、数学科生・院生による発表、我々で作った冊子の配布、それから数学に関する展示が行われていました。

私は、かねてから作っていた複素関数を視覚化するWebアプリケーション “Conformality” に関する記事を書いたり、展示をしたりしていました。

冊子には、いくつかの複素関数の例・解説と、Webアプリの舞台裏に関する記事を書きました。一方、展示では、いくつかの複素関数の例・解説をポスター(というほどの紙の大きさでもない)で貼ったのと、パソコンとタブレットを用意して実際にWebアプリを動かしながら解説するのをやりました。

来場者に解説するとき、聞き手のレベルに合わせて話して、分かってもらうのは楽しかったです。実際どのぐらい理解してもらえたかは不明ですが…。あと、ふだんあまり喋らないので声が枯れました。

具体的に、レベルに応じてどんな内容を話したかというと、

小学生(!)

  • そもそも0や負の数はまだ習っていないので、まずはそこから。
  • 複素数の足し算が平行移動になることを説明できれば十分すぎるだろう。

中学生

  • 実数はOK。「数直線の数」みたいな感じ。
  • 複素数を紹介。いずれ高校で習うよ、ということで。
  • 複素数のかけ算ぐらいまでは解説しただろうか?
  • 「関数」としては \(y=ax^2\) ぐらいがいいとこだったかな?と思ったが、中学校では「関数」として「一次関数」というのが出てくるのを失念していた。

高校生

  • 現行の学習指導要領では数学IIIで複素数平面を扱う。複素数自体は、もっと前の2次方程式関連のところで出てくるはず。(高校では「複素数平面」というようだが、数学が専門の人は普通は「複素平面」と言う。私のような面倒くさがりな人には1文字少ないのはでかい)
  • 学年としては、3年生は複素数平面知っているはず。2年生の11月では複素数平面をやっている学校があるかないか、という感じ。聞いてみたところ「明日(火曜日)から複素数平面の単元に入る」という人もいた。
  • 事前に書店などに出向いて数学IIIの参考書を立ち読みしたところ、高校で扱うのは(今回関係ありそうなのは)複素数のかけ算の図形的な意味やド・モアブルの定理がせいぜいだということが分かった。
  • 今は高校で行列を教えないので、一次分数変換と行列の関係を教えにくかった。
  • 高校では実数の指数関数や三角関数を習う。

大学生

  • 複素数や複素平面はまあ知っている(1、2年生や、文系の3、4年生も含めて)。
  • 理系の3、4年生には一次分数変換の円円対応や正則関数の等角性まで知っている人もいて話が早かった。

という感じでした。

教える関数としては、当初は一次分数変換が一番単純かなあと思いましたが、高校生を視野に入れるなら複素数のかけ算(拡大縮小と回転)からやった方が学習の役にも立つだろうと思って、冊子やポスターでは最初に複素数のかけ算の例を載せました。しかし、実際に人に教えるときはもっと初歩的な、複素数の足し算の幾何学的意味(平行移動)から始めたので、他人への解説の仕方というのは自分だけで考えてもわからないものだということを認識しました。

解説内容はそのうちこのブログかどこかに載せたいと思います(時間があれば)。

余談として、「ますらぼ」の教室では学内無線LANが使えないので、Webアプリケーションを動かすには工夫が必要でした。持ち込んだ機器は

  • MacBook
    • 解説の際の主力。
    • ペアレンタルコントロールを設定したアカウントでWebブラウザを動かした。
    • セキュリティースロットにワイヤーをつけて盗まれないようにした。6年半前にこのMacBookを買ってから初めてセキュリティースロットが活躍した。
  • Nexus 7
  • AirMac Express
    • Nexus 7とMacBookを同一ネットワークにつなげた。

で、MacでWebサーバーを動かしてWebアプリケーションを動かす感じにしました。URLは本来の “https://miz-ar.info/webapp/conformality/” で動いているように見せたかったので、MacBookとNexus 7で d-poppo.nazo.cc がMacBookのIPアドレスに解決されるようにしました。

ドメイン名に対して好き勝手なIPアドレスを割り当てるためには /etc/hosts をいじるのが手軽な方法だと思います。しかし、Androidの場合は /etc/hosts をいじるにはroot権限を取る必要があり、調べてみたところ思いの外危なそう&面倒くさそうだなあと思ったので、代わりに手元でDNSサーバーを動かすことにしました。MacBookにはDNSサーバーのソフトウエア(BIND9)が搭載されていた(最新のOSXにはないらしい)のですが、駒場祭直前にBIND9の使い方なんて覚えられない…。と思っていたらWebminとかいう便利なツールがあることを知ったので軟弱者の私はそれでBIND9を設定しました。めでたしめでたし。

自作PCにWindows 8.1を導入した (2)

前回: 自作PCにWindows 8.1を導入した

Arch LinuxとWindowsのデュアルブート

自分がArch Linuxを入れる時に使ったブートマネージャーはrEFIndだった。そのコンピューターに追加でWindowsを入れると、Windows Boot Managerがハードディスクのどこかにインストールされてそれが使われるようになる。が、それだと起動時にOSを選択できないので、ブートマネージャーの選択をrEFIndに戻す。ブートマネージャーを選ぶには、ファームウエア(UEFI?)の側でブートデバイスを選ぶ要領でやればよい。自分が使っているGIGABYTEのマザーボードだと、電源投入直後にF12を押すとブートデバイスを選択する画面が出るので、そこでrEFIndを選択した。

rEFIndの画面には、起動できるOS(今は2種類。OSのインストールDVDを入れるとそれも選択肢に現れる)の一覧が表示されるので、それで選べばよい。

ハードウエアクロック

Arch Linuxをインストールした時、ハードウエアクロックはUTCで設定したが、Windowsではデフォルトで地方時(local time)を使う(?)ので、日本だと9時間ずれた時間がWindows上に表示される。

この問題については、Arch Wikiの記事に書いてある(日本語記事)。記事に従ってレジストリをいじればよい。Windowsによる時刻同期は、よくわからないが切った方がいいらしい。

ソフトウエアのインストール

コマンドラインで使えるWindows向けのパッケージマネージャーであるところのChocolateyを入れてみた。そうすると、管理者権限のあるコマンドプロンプトとかPowerShell上で

choco install virtualbox
choco install GoogleChrome
choco install gimp

という具合でソフトウエアを導入できる。便利。

デュアルブートじゃなくて仮想化で同時に使いたい

先に書いたように、起動時にWindowsかArch Linuxかを選択すれば、どちらか一方のOSを起動できる(デュアルブート)。が、時代は仮想化だ(?)。Windowsを立ち上げつつLinuxも使う、あるいはその逆をやりたい。それも、新しく仮想マシンにLinuxをインストールするのではなく、既に物理ハードディスクにインストールしてあるLinuxを使いたい。

普通、仮想化ソフトウエアでOSを動かすときは、ゲストOS用のハードディスクの実体はホストOSのファイルシステム上に作られる数十GBのファイルになっているが、その代わりに物理ハードディスクを直接ゲストOSに割り当てたい。

VirtualBoxの場合はこの辺の手順でそれができるらしい。が、なぜかうまくいかなかった。どういうエラーが出たかは覚えていない。

そういえば今回インストールしたのは8.1 Pro (x64)なので、Hyper-Vというやつが使えるはずだ。試してみようということで、
コントロールパネル > プログラム > プログラムと機能 > Windows の機能の有効化または無効化
でHyper-Vにチェックを入れ、再起動。この辺の記事を参考に設定しようとしたが、物理ディスクをオフラインにする手順のところで詰まった。具体的には、
コンピューターの管理 > 記憶域 > ディスクの管理
で、Arch Linuxが入っているディスク0をオフラインにしようとしたら、「現在のシステムディスクまたは BIOS ディスク 0 上のディスク属性は変更できません。 」というエラーが出た。EFIが入っているディスクだからダメなのか。よくわからん。

続きはまた今度。

IIJmioの格安SIMを1ヶ月間使ってみた感想

IIJmioの格安SIMを買ってから1ヶ月が経ったので、実際に使って生活した感想を書く。

端末

結局Pocket WifiのGL02Pで使い続けている。前の記事でも書いたように、この端末はSIMフリーで、APNを設定すればドコモのMVNOでも使える。SIMの大きさは標準SIMだが、microSIMでもアダプタなしで騙し騙し使える。自分の生活圏では、ほとんど3Gしか掴まない。LTEの表示が出る場所(つまり、ドコモのLTEの1.7GHz帯の電波が飛んでいる)も一部にはあるようだ。

OLYMPUS DIGITAL CAMERAOLYMPUS DIGITAL CAMERAOLYMPUS DIGITAL CAMERAスクリーンショット 2014-11-06 0.17.43

利用状況

家にいる時は家の固定回線があり、大学にいる時は(建物によっては)学内無線LANが使えるので、モバイル回線にお世話になるのは、このどちらでもない場所となる。駅や電車内とか。ただし、電車通学ではないので通学中は使わない。

というわけなので、普段の生活の中で、家と大学だけで過ごす日はまったくモバイル回線を使わない。そういうわけで、日によってばらつきが大きく、(b-mobileやOCNにあるような)高速通信の容量が1日あたりで決まっているプランよりも、今回選んだ、高速通信の容量が1ヶ月あたりで決まっているプランの方が向いている。

利用量は多い日で100MBを超える程度。まったく使わない日も多いので、先月は一ヶ月の利用量が2GBに届かず、700MBくらい余った。なので、常に高速通信ONで問題なさそうである。まあ、これは外出先で容量を食うサービス等を利用していないからだろう。動画の視聴や、リモートデスクトップ、VNCはやっていない。外出先でのアプリのアップデートは避けたいと思っている。

今後

これからどうするか。先の記事にも書いたように、今持っている端末がアレなので、新しい端末を入手したい。iPhoneを買うか、Android端末か、モバイルルーターか。

自分の中ではNexus 5が有力候補だったが、調べたところFOMAプラスエリアに完全対応していないようで、そこが不安要素になっている。

あと、メインのドコモ回線をどうするかも悩む。今はFOMA契約で、ガラケーで使っているが、今後どうするか。

日記終わり。

自作PCにWindows 8.1を導入した

1年半前にパソコンを自作したのだが、今まではLinux (Arch Linux)だけを入れて使ってきた。だが、何となくWindows環境の必要性を感じたので、Windows 8.1 Pro (DSP版)を買ってきてインストールすることにした。無印じゃなくてProにしたのは、リモートデスクトップを使いたいというのが主な理由だ。

そのパソコンに入っているHDDは手持ちの物の再利用(前はMacBookに入っていたが、容量が狭くなり換装したので余った)で、潤沢に容量があるというわけではなかったので、HDDも新しいのを買った。

インストールだが、特に何の問題もなかった。DVDから起動して、(新しく導入した)HDDを選択して、おわり。Microsoftアカウントの名前はローマ字にしていたので、ホームディレクトリの名前はローマ字になった。

とりあえず導入したソフトウエアは

  • Firefox
  • Dropbox
  • iCloud for Windows
    • ついでにBonjourが入るので他の端末から ホスト名.local で参照できるようになる

で、明日以降もっとほかのソフトウエアとかも入れて環境を整えたい。

…と思ったが、Arch Linuxを起動できるか確認していない。Arch Linuxの時はrEFIndを使っていたが、WindowsのUEFI事情はよく分からない。明日以降なんとかしたい。Arch Wikiのこのへんが参考になるだろうか。

IIJmioの格安SIMを買った

いままでイーモバイル(最近Y! mobileになったけど)のLTE回線でPocket WiFiを使ってきたけど、その2年契約が切れるのを機に、最近流行の格安SIMを使ってみることにした。

ドコモのMVNOでいわゆる「格安SIM」を提供しているのはb-mobileをはじめとして数社あるが、今回選んだのはIIJmioのデータ専用プラン。これまで使ってきたイーモバイルのデータ専用回線から移行するので、音声通話やSMSは必要ないと判断した。IIJmioを選んだ理由は、

  • 最近増量されて一番安いプランの高速データ通信容量が2GBになった。他社と比べてお得?(そこまで徹底的に調べたわけではないけど)
  • 対応した端末を使えばIPv6が使える!(21世紀になって十数年も経ったんだからいい加減IPv6を使ってもいいよね?)

あたり。まあ2年縛りとかはない(IIJmioの場合は高々2ヶ月程度の最低利用期間があるけど)ので、他社のが良いと思ったら気軽に乗り換えられる。

購入方法は、家電量販店で「IIJmioウェルカムパック」を買ってウェブで登録することにした。物理的な店舗で買えば、SIMカードが送られてくるのを待つ必要がない。買って帰って登録すればすぐに使えるようになる。また、月額料金とは別に初期費用的な感じでSIMカードが3000円ちょいするが、量販店だと定価より安く買える可能性がある。ビックカメラで買えば無料でWi2の公衆無線LANが使えるらしいが、まあ別にいいかなと思って普段使っている量販店で買った。

端末は、とりあえず手持ちの端末で使うことにした。手持ちの端末は

  • ドコモの古いAndroidスマートフォン
    • 古いやつなのでLTE非対応。
    • MVNOのSIMだとテザリングができない。
    • SIMカードのサイズはmicroSIM。
  • Pocket WiFi GL02P
    • 今までよく知らなかったが、イーモバイルの端末(最近の物を除く)は基本的にSIMフリーらしい。なのでドコモのSIMカードを挿しても通信できる。
    • ただし、ドコモの一部周波数帯に非対応。山間部で強い味方となるFOMAプラスエリアも使えないらしい。
    • 他のモバイルルーターに対してこれといった優位点はない。自分の手持ちっていうだけ。
    • まるまる2年使っているわけなのでバッテリーがへたっている。モバイルブースターなしでは使えない状態。
      • SIMカードのサイズは標準SIMなので、microSIMとかnanoSIMで使う場合はアダプターが必要。

あたり。まあそのうち良さげなモバイルルーターとか買うと思う。タブレットを買う時にLTEモデルを買っておけば良かったかなあと思ったり。

IPv6を使うには、端末として

  • Nexus 5/7みたいな一部のスマートフォン・タブレット
    • SIMロックされたものを含む多くのスマートフォンが、IPv4とIPv6を選べないらしい。
  • モバイルルーターだと、NECのAterm MR03LN (および旧機種?のMR02LN)
    • Aterm MR03LNは現時点のSIMフリーなモバイルルーターとしてはトップクラスに評判がいいっぽい。
    • Aterm MR03LNはBluetooth PANによるテザリングができる。Bluetooth DUNと違って、iPad/iPod touchでも使える。(iPhoneはネットワークアクセスを提供する側の機能しか実装されていないので使えないらしい。参考
  • ドコモの一部の通信端末でも使えるらしい?参考(2年前の記事だけど)

が必要らしい。IIJmioによる接続確認端末の一覧がここにある。

下調べはこれぐらいにして、実際に使ってみた感想だが、特筆すべきところはなかった。普通に期待通りというか。GL02Pで電波の掴みが悪いのは周波数帯のせいなのか自分の家の電波環境が悪いのか。ドコモのスマートフォンでテザリングができないので、主にモバイルルーターで使うことになるだろうか。日記終わり。

ECMAScriptでのいくつかの数学関数の実装

C言語をはじめとする多くのプログラミング言語には、exp, log, sqrt などの指数、対数、平方根の関数や、 cos, sin, tan などの三角関数、cosh, sinh, tanh などの双曲線関数が備わっている。これらの数学関数はECMAScript (JavaScript)からは、Mathオブジェクト経由で Math.expMath.cos などのようにアクセスできる(が、現状ECMAScriptには双曲線関数はない)。

さて、C99でこれらに加えて、acosh, asinh, atanh などの逆双曲線関数や、expm1log1p などの「精度を意識した」関数などが追加された(expm1は\(\exp x-1\), log1p は \(\log(1+x)\) を計算する関数である)。これらの関数をECMAScriptで使うにはどうすればいいか?

ECMAScriptの次期標準であるECMAScript 6では、双曲線関数 Math.(cosh|sinh|tanh) や、C99で追加された関数に対応する Math.(acosh|asinh|atanh)Math.expm1, Math.log1p が入るらしい(Firefoxなどでは既に実装されている)。しかし、ECMAScript 6に非対応の環境では、これらの関数は自前で実装するしかない。

幸い、双曲線関数は指数関数で書ける。よって、例えば Math.sinh はECMAScriptに既に存在する Math.exp 関数を使って次のように書ける:

[sourcecode lang=”js”]
Math.sinh = Math.sinh || function(x) {
return (Math.exp(x)-Math.exp(-x))/2;
};
[/sourcecode]

Mozillaのサイトにも代替コード(Polyfill)として同じようなコードが載っている。めでたしめでたし。

といいたいところだが、精度を気にする場合はそうはいかない。例えば、\(x\) にとても小さい数、例えば \(x=10^{-20}\) を代入してみるとどうなるだろうか。\(\sinh\) のテーラー展開\[
\sinh x=x+\frac{x^3}{3!}+\cdots
\]を考えると(\(x^3\) は微小なので無視して)値はおおよそ \(x=10^{-20}\) と一致するはずである。この場合、ECMAScriptの「数」はIEEE754の64bit浮動小数点数で、精度は53bitしかないため、\(x\) が十分に小さければ \(x+\frac{x^3}{3!}+\dots\) は完全に \(x\) と一致する。

一方、指数関数のテーラー展開は\[
\exp x=1+x+\frac{x^2}{2!}+\cdots
\]で、今書いたのと同じ理由で Math.exp(x)Math.exp(-x) は完全に 1 と等しくなる。従って、さっき実装したオレオレ Math.sinh は0を返す。情報落ちだか桁落ちだか忘れたが、なんかそういう現象が起こっている。これは理想的とはいえない。ちなみに、C言語の sinh はこの場合「正しい」 \(10^{-20}\) を返す。

同様に、Math.expm1 を次のように愚直に実装しても、同じ問題が発生する。

[sourcecode lang=”js”]
Math.expm1 = Math.expm1 || function(x) {
return Math.exp(x)-1;
};
[/sourcecode]

では、どうすれば \(x\) が小さい時でも「正しい」答えを出す expm1 関数を作れるか?(双曲線関数よりも指数関数の方が単純なので、以後こちらを議論する)

まあ単純な答えとしては、 \(x\) が小さいときに関数のテイラー展開を使って多項式として計算してやれば良い。さっきのように \(x=10^{-20}\) とかだと1次近似で \(x\) そのものを返してやればよかったが、この近似は \(x\) がどのぐらい小さければ問題ないのか?あるいは、近似の次数をどのぐらい増やしてやれば誤差はどれぐらい小さくなるか?

仮に、\(\exp x\) を \(n\) 次の多項式で近似するとしよう。すると、真の値(無限級数で表される)との差は\[
\left\lvert(\text{差})\right\rvert=\left\lvert\exp x-1-\sum_{k=1}^{n}\frac{x^k}{k!}\right\rvert=\left\lvert\sum_{k=n+1}^{\infty}\frac{x^k}{k!}\right\rvert
\]となる。これを適当に評価してやれば良い。実際にやってみると、例えば次のようになる。\begin{align*}
\left\lvert(\text{差})\right\rvert=\left\lvert\sum_{k=n+1}^{\infty}\frac{x^k}{k!}\right\rvert
&\le\sum_{k=n+1}^{\infty}\frac{\lvert x\rvert^k}{k!} \\
&=\frac{\lvert x\rvert^{n+1}}{(n+1)!}\sum_{k=0}^{\infty}\frac{\lvert x\rvert^k}{(n+2)\cdot\dots\cdot(n+k+1)} \\
&\le\frac{\lvert x\rvert^{n+1}}{(n+1)!}\sum_{k=0}^{\infty}\frac{1}{(n+2)^k} \quad (\left\lvert x\right\rvert <1\text{を仮定}) \\
&\le\frac{\left\lvert x\right\rvert^{n+1}}{(n+1)!}\frac{1}{1-\frac{1}{n+2}} \\
&\le\frac{\left\lvert x\right\rvert^{n+1}}{(n+1)!}\frac{n+2}{n+1}=\frac{(n+2)\left\lvert x\right\rvert^{n+1}}{(n+1)(n+1)!}
\end{align*}
では、どういうときに \(n\) 次の多項式近似の値を使ってよいかというと、近似値 \(\sum_{k=1}^{n}\frac{x^k}{k!}\) の大きさに対してこの \(\left\lvert(\text{差})\right\rvert\) の大きさが(精度が53bitの浮動小数点数の場合は) \(2^{-53}\) よりも小さければ確実に問題ない(十分条件)。つまり\begin{align*}
\left\lvert\frac{(\text{差})}{\sum_{k=1}^{n}\frac{x^k}{k!}}\right\rvert<2^{-53}
\end{align*}だ。この左辺をもうちょっと分かりやすい形で評価すると
\begin{align*}
\left\lvert\frac{(\text{差})}{\sum_{k=1}^{n}\frac{x^k}{k!}}\right\rvert&\le\left\lvert\frac{(\text{差})}{x}\right\rvert \\
&=\left\lvert\frac{1}{x}\frac{(n+2)\left\lvert x\right\rvert^{n+1}}{(n+1)(n+1)!}\right\rvert \\
&=\frac{(n+2)\left\lvert x\right\rvert^n}{(n+1)(n+1)!}
\end{align*}
となる(書いた後に気付いたが、最初の行の評価が \(x<0\) のときにマズい気がする)。つまり、\(n\) 次近似を使っても良い十分条件として\[
\frac{(n+2)\left\lvert x\right\rvert^n}{(n+1)(n+1)!}<2^{-53},
\]すなわち\[
\left\lvert x\right\rvert<\sqrt[n]{\frac{(n+1)(n+1)!}{n+2}2^{-53}}
\]が得られる。

例えば、\(n=3\) として右辺を計算すると \(1.286976\ldots\times 10^{-5}\) が得られるので、さっきのオレオレ Math.expm1 の実装は

[sourcecode lang=”js”]
Math.expm1 = Math.expm1 || function(x) {
if (Math.abs(x) <= 1.28e-5) {
return x*(1+x/2*(1+x/3));
} else {
return Math.exp(x)-1;
}
};
[/sourcecode]

のように改良できる。

まあ、改良したと言っても所詮お遊びで、実際のC言語のライブラリの実装はこんな適当なコードよりもちゃんとやっているので、真面目にやりたい人はC言語のライブラリの実装を移植しよう。

Math.expm1 の他に、Math.log1p, Math.sinh, Math.tanh, Math.asinh, Math.atanh あたりの関数を実装する時にも同じような(小手先の)テクニックが使える。

ところで、MDNに載っている Math.tanh のPolyfillに問題があるのを見つけた。MDNのPolyfillでは xInfinity かどうかを関数の最初でチェックしているが、xInfinity でなくても Math.exp(x)Infinity になる場合を考慮していない。その結果、Math.tanh(x) に 1 を返してほしいのに実際には NaN が返ってくる場合がある。

最後に全く関係ない話だが、プログラミング言語Luaは標準ライブラリに math.sinh などの双曲線関数を計算する関数(中ではC言語のライブラリ関数を呼び出す)を持っている。しかし、どうやら将来的にはこれらの双曲線関数を標準ライブラリから外すようだ(次期バージョン5.3でdeprecated扱い)。理由として作者は「あまり使われていない」「必要なら mathx などの外部ライブラリを使えば良い」としている(この記事に書いた理由により、「math.exp で実装できる」は理由にならない)。ECMAScript と Lua はよく似ていると言われる事が多いが、一方がWebの世界のアセンブラとなるべく数学関数・浮動小数点数関係の関数を追加しようとしているのに対し、もう一方はそれを削減しようとしているのは対照的だと思った。(まあ筆者自身はLuaを活発に触っていたのは5.1時代の事で、5.2が出て以降はあまり触っていないので、ぶっちゃけどうでもいいのだが)