32ビット?64ビット?(自分用メモ)

■gccが32ビットか64ビットか:
gcc -v の出力の Target: のところを見る.

32ビットの場合 Target: mingw32
64ビットの場合 Target: x86_64-pc-msys

などのようになる.システムの細かな差異によって文字列は少しずつ違うが,64ビットの場合 x86_64 が部分文字列としてしばしば含まれる.

■ghcが32ビットか64ビットか:
次のようなファイルを作る:

main = print ()

そして

$ ghc --make foo.hs
[1 of 1] Compiling Main             ( foo.hs, foo.o )
Linking foo.exe ...

$ file foo.exe

32ビットの場合には
PE32 executable (console) Intel 80386, for MS Windows

64ビットの場合には 
PE32+ executable (console) x86-64, for MS Windows

のようになる.

■おまけ:
自分がどの gcc を使ってるのかわからなくなった場合などは
which -a gcc
すればよい.使い分けをしたい場合は適宜 .bashrc に alias を張ればよさそう.

広告

HaskellからFFIでCの配列を扱う(マーシャリング)

HaskellのFFIについてはこのブログでも例えばこんな記事で扱っている.

今回はその記事では触れなかったマーシャリングについて扱う.まずは次のようなCの関数があったとしよう:

#include <stdlib.h>
#include <stdio.h>
#include "c_header.h"

/*
int sum(int* p);

int fib(int** pp, int n);
*/

int sum(int* p, size_t n)
{
  if(n == 0){ return 0; }
  size_t i;
  int retval = 0;
  for(i = 0; i < n; ++i)
  {
    retval += p[i];
  }
  return retval;
}

int fib(int** pp, int n)
{
  if(n<=0){ return 1;}
  *pp = malloc(n * sizeof(int));
  if(n>=1){ (*pp)[0] = 1;}
  if(n>=2){ (*pp)[1] = 1;}
  if(n>=3){
    int i;
    for(i=2; i < n; ++i)
    {
      (*pp)[i] = (*pp)[i-1] + (*pp)[i-2];
    }
  }
  return 0;
}

これらのコードは次のように使われる:

#include <stdio.h>
#include <stdlib.h>
#include "src/c_header.h"

#define N 10
int main(void)
{
  int array[] = {1,2,3,4,5,6,7,8,9,10};

  int s = sum(array, sizeof(array)/sizeof(array[0]));
  printf("sum=%d\n",s);

  int* p = 0;
  int r = fib(&p,N);
  if(r==1){ printf("failed"); }
  else{
    int i;
    for(i=0; i < N; ++i)
    {
      printf("fib(%d)=%d\n",i,p[i]);
    }
  }
  free(p);
  return 0;
}

sumやfibは次のようにHaskellから扱える:

module Lib
    where

import Foreign.C.Types
import Foreign.Ptr
import Foreign.Marshal.Array
import Foreign

-- int sum(int* p, size_t n);
foreign import ccall "c_header.h sum" cSum
  :: Ptr CInt -> CSize -> IO CInt

hSum :: [Int] -> IO Int
hSum xs =
  let
    xs' = fromIntegral <$> xs :: [CInt]
    len   = fromIntegral $ length xs :: CSize
  in
  do
    arr <- newArray xs' :: IO (Ptr CInt)
    l <- return len  :: IO CSize
    ret <- cSum arr l :: IO CInt
    return $ fromIntegral ret

-- int fib(int** pp, int n);
foreign import ccall "c_header.h fib" c_fib
  :: Ptr (Ptr CInt) -> CInt -> IO CInt

hFib :: Int -> IO [Int]
hFib n =
    do
      ptrOut <- malloc  :: IO (Ptr (Ptr CInt))
      n' <- return $ fromIntegral n :: IO CInt
      ret <- c_fib  ptrOut  n' :: IO CInt
      out <- peekArray n =<< peek ptrOut :: IO [CInt]
      free =<< peek ptrOut
      free ptrOut
      return (fromIntegral <$> out) :: IO [Int]

cSum と hSum, c_fibとhFibのシグネチャは結構ずれている.
関数cSumは sum と同様にポインタとサイズを受け取る.hSum ではサイズを配列から計算しているので長さを引数にする必要がない.
また,c_fib では二重ポインタと長さを引数にしているが,hFibでは長さだけが引数となっている.c_fib の引数となっている二重ポインタは出力用の変数だからである.

次のコードはhSum,hFibの使用例である.

module Main where

import Lib

main :: IO ()
main =
  do
    a <- hSum [1,2,3,4]
    print a
    xs <- hFib 15
    print xs

stack でこのコードをビルドする場合,stack.yaml に次のような行を加えねばならない:

c-sources:  src/c_impl.c

optparse-generic

自分用メモ.

必要なことはすべて https://github.com/Gabriel439/Haskell-Optparse-Generic-Library から辿れるhttp://hackage.haskell.org/package/optparse-generic/docs/Options-Generic.htmlに載っている.

■optparse-genericとは何ですか?:コマンドライン引数を処理するライブラリの一つです.

■インストール:stack install optparse-generic

■サンプル:

{-# LANGUAGE DataKinds          #-}
{-# LANGUAGE DeriveGeneric      #-}
{-# LANGUAGE FlexibleInstances  #-}  -- One more extension.
{-# LANGUAGE OverloadedStrings  #-}
{-# LANGUAGE StandaloneDeriving #-}  -- To derive Show
{-# LANGUAGE TypeOperators      #-}

import Options.Generic --stack install optparse-generic

data OptionInput  w = OptionInput
  { foo :: w ::: Int           <?> "Documentation for the foo flag"
  , bar :: w ::: Double        <?> "Documentation for the bar flag"
  , baz :: w ::: String        <?> "Documentation for the baz flag"
  , qux :: w ::: Maybe String  <?> "Documentation for the qux flag"
  , quux :: w ::: Bool         <?> "Documentation for the quux flag"
  } deriving (Generic)

instance ParseRecord (OptionInput Wrapped)
deriving instance Show (OptionInput Unwrapped)

main = do
    x <- unwrapRecord "program short description"
    let i = foo x :: Int
    let d = bar x :: Double
    let s = baz x :: String
    let s' = qux x :: Maybe String
    let b = quux x :: Bool
    print (x :: OptionInput Unwrapped)

■サンプルのビルド:stack ghc optiontest.hs
必要に応じて,package.yaml で
dependencies:
– optparse-generic

■サンプルを動かす:optiontest.exe --foo 2 --bar 3.478 --baz "hoge" --qux "fuga"

github メモ

自分用メモです.

■開発作業
git checkout -b hoge #作業用ブランチを作成
★自由にコード等を編集する.
git commit -m "fix bug" #変更内容をコミット
git push origin hoge #自分のレポジトリにプッシュ
★github ページに言ってPull Request を作る.
★権威ある人に merge してもらう.

■自分のレポジトリを最新の状態に更新する
(git remote add upstream git@github.com:foo/bar.git)← upstream の登録は一度やればいい
git checkout master #作業ブランチを master に
git pull upstream master
git push origin master #自分のレポジトリにpush

■開発ブランチにmasterの内容を適用する
git checkout master
git pull origin master
git checkout hoge
git rebase master

★叱られたらファイルを修正して
git rebase –continue

■何がうまくいかない場合とりあえず現状を把握する
git status

■ローカルでの変更が邪魔して pull できない場合
git stash save "some-name"

■作業ブランチの確認
git branch

■ブランチ一覧
git branch -a

■リモートブランチの一覧
git branch --remote

■リモートブランチ foo の削除
git push origin :foo

■作業ブランチをhogeに変更
git checkout hoge

■作業ブランチの名称を fuga に変更
git branch -m fuga

■手元のブランチ piyo をリモートに登録する
git push -u origin piyo

■git管理下にあるファイル一覧
git ls-files

■git管理下にあるファイルをすべてadd
git add .

■git管理下にあるファイルのリネーム
git mv aaa.txt bbb.txt

■出したプルリクを取り下げる
remoteにpush済みのブランチを削除することで紐づくpull requestを削除出来ます
git push --delete origin hoge

■url の確認
git remote -v

■git管理下にあるファイルを削除
git rm hogehoge
(ディレクトリごと:git rm -r hogedir )

■ファイルをローカルに残したままgit管理下からファイルを除く
(1) git rm --cached hogehoge
(2) .gitignore に追記する

■originの変更
git remote set-url origin git@github.com:foo/bar.git

■upstreamの変更
git remote set-url upstream git@github.com:foo/bar.git

■自分がコミットしたところだけログを見る
git log --author=differential.engine@gmail.com

こうやって
commit 23985b88d43328a72bacafb784d7e30f78357f83
Author: dif_engine
Date: Fri Jul 6 23:00:00 2018 +0900

だったとき
git diff 23985b88d43328a72bacafb784d7e30f78357f83 > hoge.txt
とするとコミット 23985b88d43328a72bacafb784d7e30f78357f83 から HEAD までの差分が手に入る.一般には
git diff COMMIT-ID1:COMMIT-ID2 > out.txt

uniq 的な関数(Haskell)

Haskell のリストから重複要素を除去する関数はnubである.「同じかどうか」を判定する関数を引数に取る nubBy を使いたい場合もある.これらの関数はリスト全体を舐めて重複要素を除去する.

扱っている配列がソート済みである場合も多い.その場合,隣接要素だけ見ていけば重複要素を除去できるはずである.そうすれば少しだけ効率が良いかも知れない.そう考えてこんな関数を書いてみた:

uniq :: (Eq a) => [a] -> [a]
uniq = foldr  uniqAux []
  where uniqAux :: (Eq a) => a -> [a] -> [a]
        uniqAux t [] = [t]
        uniqAux t (u:us) = (if t == u then [u] else [t,u]) ++ us

uniqBy を作るのも簡単である.

※効率がどうこうと言ったが,性能比較はまだしていない.

知られざるZakon

■Elias Zakonの事について調べたので書いてみる.とはいえこの人物にはwikipediaページも作られていないので,そんなに世間から関心を持たれてもなさそうである.私がこれを書く理由は個人的な関心からである.

■そもそもなぜ彼に興味を持ったのか.ここ数年,私は超準解析(Nonstandard Analysis, NSA)の勉強している.この超準解析というものがどのようなものであるかについてはこの記事では扱わない.(私のブログでは過去にこのような記事で少し触れたことがある).超準解析はAbraham Robinson(1918-1974)によって創始された.しかしながら,Robinsonが創始した当初の議論は高階型理論に基づいていることもあって他の数学者には理解が難しかった(というようなことが色々な著者によって述べられている).

しかしながら,W.A.J.Luxemburg編集の1969年の論文集“Applications of Model Theory to Algebra, Analysis, and Probability” に収録された Abraham Robinson and Elias Zakon の論文“A Set-Theoretical Characterization of Enlargements” において,超準解析が数学の「ふつうの言語」である集合論の枠組みで捉えられるようになり,超準解析の普及を後押しした.

もちろん現実はもう少し複雑であり,上の論文集でも超準解析を実現するための方法が幾つか提案されている.とはいえ,いわゆる上部構造によって集合論の中で超準モデルを構成して見せたのは“A Set-Theoretical Characterization of Enlargements”が最初である.上部構造による構成には具体性があるため,あまりモデル理論などの知識がなくても議論を追いやすいのはひとつの魅力ではないかと思われる.実際,M.デービス,斉藤正彦,中村徹の三氏がそれぞれ書いた超準解析入門書でも上部構造の議論が用いられていることに注意すると,Robinson & Zakon は今でもある程度の影響を与えていると考えられる.

ところで,LuxemburgやLoebのように超準解析の「業界」で長く影響を持ってきた人たちと違い,Zakonの名前は目立たない.前述したようにWikipediaページもない.そこで,超準解析の世界にそれなりの足跡を残しつつ無名のZakonという人物についてなんとなく興味を持っていた.

■ふと思いたって検索してみたら彼が “Mathematical Analysis I” という本を書いているらしいことに気づいた:http://www.trillia.com/zakon-analysisI.html 
以下に,この本の「About the Author」というところに書かれていることのうち必要と思われる箇所だけ訳しておく:

■エリアス・ザーコンは1908年に帝政ロシアで生まれ,20世紀ヨーロッパ動乱の余波を受けた.

ザーコンはドイツとポーランドで数学と法学を学び,後に父親の法律事務所に加わった.ドイツ軍の接近から逃れるようにして1941年に彼は家族をシベリアのバルナウルへ家族を連れてゆき,そこで民衆とともに苦難の5年間を過ごした.バルナウルにはレニングラード包囲から逃れてレニングラード工科大学も避難してきており,彼はそこで数学者I.P. Nathansonに会ったのだった.Nathansonの励ましにより,ザーコンは数学の勉強と研究を再開した.

ザーコンと彼の家族はオーストリアのザルツブルクの難民キャンプで1946年から1949年まで過ごし,そこでヘブライ語を独習した.これは彼が流暢に使えるようになった6つあるいは7つの言語の1つであった.1949年に,彼は新しく建国されたイスラエルへ家族を連れてゆき,ハイファのイスラエル工科大学で1956年まで教えた.イスラエル共和国ではロジックと解析学の彼の最初の研究論文を発表した.

彼の人生を通して,ザーコンは音楽,芸術,政治,歴史,法律,そして特にチェスへの関心を絶やさなかった.彼がチェスのマスター称号を獲得したのはイスラエルにおいてである.

1956年,ザーコンはカナダに移住した.トロント大学では,研究員としてアブラハム・ロビンソンと共に働いた.1957年に,彼は(カナダの)ウィンザー大学の数学科に入り,新しく創設された数学の優等学位プログラムを1960年に得た.ウィンザーでは,彼はロジックと解析学の研究の成果の発表も続けた.このポストマッカーシー時代には,多産にして奇矯な数学者ポール・エルデシュをゲストとして迎えることが度々あった.エルデシュはその政治的見解からほどなくして米国から追放されている.エルデシュがミシガン大学や他のアメリカの大学から数学の議論をするために人々が集まるウィンザー大学で話すこともあった.

ウィンザーにおいて,ザーコンは三巻からなる解析学の本を著した.これは製本され生徒に配布された.ザーコンの目標はなるべく早く厳密な内容を紹介することにあった.こうすることによって後の講義ではこの内容に依拠することが出来るからである.

■余談1. Elias という名前はイスラエルの預言者エリヤに由来する.

■余談2. I. P. Nathanson という数学者のことはWebで調べてもよくわからない.

■余談3. Zakon がすでに故人であることはわかっているが没年はわからなかった.

翻訳に poedit を使う(メモ)

poEdit は本来ソースコードに含まれたメッセージなどをローカライズするためのものらしいが,通常の文書を翻訳するのにも使える.一年ぶりに使おうとしたら使い方を思い出せなくて困ったのでメモしておく.

英文和訳を例にする.

■1.poedit をインストールしておく.Windows版がある.https://poedit.net/download

■2.gettext を使えるようにしておく.
自分はVMWareに入れたUbuntuに入れた.apt-get install gettext みたいな感じで行けたはず.(gettext for Windows というのもあるらしいがしばらくメンテナンスされていない雰囲気).

■3.VMWareのUbuntuとの共有フォルダに翻訳したい英文ファイル(例えばhoge.txtとかhoge.rtfなど)を入れる.以下では hoge.txt として説明する.一文ずつ訳す(おすすめ)ためには,一文ごとに空行を入れておく.

■4.Ubuntuのコマンドラインから 
txt2po hoge.txt hoge.po
として po ファイルを作る.

■5. poedit で翻訳する

■6. Ubuntu のコマンドラインから
po2txt hoge.po hoge.translated
としてやると,翻訳文だけを集めたファイル hoge.translated が得られる.

集合論宇宙についてのメモ

■「集合全体の集まり」を「宇宙(universe)」と呼びしばしば{\mathbf{V}}などと書く.ただし,「宇宙」という言葉はもう少し小さな「集合」を指すために使われることもある.以下ではZFCにおける「集合全体の集まり」の意味で{\mathbf{V}}という文字を使う.ところで,なぜ”V”なのかというと,ドイツ語のVollraumから来ているらしい.voll(いっぱいの)/raum(空間) と分解すれば意味は取れる.

{\mathbf{V}}が集合ではないことは,少なくとも二つの方法で示せる.最初に基礎の公理を使う方法を示し,次に分出公理図式を使うものを示す.

■基礎の公理を用いた証明.
基礎の公理は次のようなものであった:
{\forall x \enskip \left(x \not= \varnothing  \Rightarrow \exists y \in x \enskip \forall t \in x \enskip (t \not\in y)\right).}

さて,{\mathbf{V}}が集合であったと仮定すると{X:= \left\lbrace  \mathbf{V}\right\rbrace}も集合である.この{X}に基礎の公理を適用すると{\mathbf{V}\not\in \mathbf{V}}が得られるが,{\mathbf{V}}はすべての集合を含んでいるのだからこれはおかしい.よって,{\mathbf{V}}が集合として存在するという仮定から矛盾が導かれたことになる.よって{\mathbf{V}}は集合ではない.

■分出公理図式を用いた証明.
分出公理図式は無限個の公理の総称であり,ある集合から部分集合を作ることを可能にする.(分出公理図式は置換公理図式から導くことも可能であり,ZFCの公理群に含めない場合もあるが,何れにせよZFCでは分出「公理」図式は使用可能である).

{\mathrm{V}}が集合だと仮定すると,分出公理図式から{W:=\left\lbrace x \in \mathbf{V} \mid x \not\in x \right\rbrace}も集合となり,特に{W\in \mathbf{V}}である.すると,{W \in W}であると同時に{W \not\in W}であることが導かれてしまう(床屋のパラドックス).よって{\mathbf{V}}は集合ではあり得ない.

■余談
しばしば,{\mathbf{V}}が集合ではないことの直感的な説明として,「{\mathbf{V}}は集合に収まるには巨大過ぎる」と説明されることがある.

ブルバキの位相についてのメモ

大学二年生の夏休みはずっとブルバキの位相の本を読んでいたような記憶がある.Springer から出てた “General Toplogy Chapters 1-4” がそれ.いま思えば別にこれが位相空間を学ぶベストの本ではないと思うが,20歳の頃に悩みながら読んだ記憶が美化されてしまうせいもあってか不思議と嫌いになれず,いまだに手元にこの本が置いてある.

上で《嫌いになれない》と書いた.この本は多くの位相空間の教科書とはなんとなく書き方が違う.なにせ,肝心の位相空間の定義の仕方からして少し変わっている.ややクセがあるのは確かであり,人前で《この本が好き》というのは少し気恥ずかしい.どう書けば《変わってる》感じが伝わるかわからないが,ここでは二点

1.開集合系の定義の仕方
2.フィルターへの偏愛

に絞って説明する.

■1.開集合系の定義の仕方
ブルバキでは集合{X}上の位相構造{T}が次のよう性質を満たすものとして定義されている:
(O1) {T}の集合の合併は{T}に属する.
(O2) {T}の集合の有限交差は{T}に属する.

多くの教科書では{X,\varnothing \in T}も公理になっている.しかし,実はこれは(O1)(O2)から次のように導ける:

・空集合が{T}に属すること:{T}の空部分集合を考える.(O1)により{\bigcup \varnothing \in T}となることから成立.

{X}{T}に属すること:{T}の空部分集合を考える.(O2)により{\bigcap \varnothing \in T}となることから成立.

上の議論には納得が行くだろうか.空集合が{T}に属することの議論には問題がないが,{X}{T}に属することの議論はどうだろうか.そもそも{\bigcap \varnothing}の指示内容は何だろうか——それが存在するとして,それは果たして集合だろうか?

(念のために付言すれば,通常の集合論では{\bigcap \varnothing}を考えない.たとえばキューネン『キューネン数学基礎論講義』p.32とそこにおける議論を見よ).

■2.フィルターへの偏愛
位相空間はフィルターを用いて定義することもできる.この《フィルター》というのはブール代数などでも研究されるフィルターと大体同じ概念である.(Xの冪集合をブール代数とみなしたときの「ブール代数のフィルター」はこの本での「フィルター」になっている).フィルターを通して眺めると連続性の議論がやや代数的な雰囲気になる.とはいえ,この本で扱われている範囲ではあまりフィルターを持ち出して議論する旨味はそんなに感じられない.読んで理解するのが結構大変なわりにはどこへもたどり着けないようなもやもやした気持ちが残る.

■3.おまけ:公理(O3)
先述したように,ブルバキの位相空間の公理は(O1)(O2)で尽くされているのだが,しばらく読み進めるとChap 1 sec8.4 Regular Space Prop.11 に(O3)が登場している.なぜこの公理が(O3)と呼ばれるのにふさわしいのか,などは全く説明されていない.やはりこの本はクセが強い.

(latex)新しいパッケージを入れただけでコンパイルできなくなる問題

■概要:新しいパッケージを入れただけでコンパイルできなくなったら一度関連ファイルを削除してみよう.

■編集しているPDFにハイパーリンクを追加しようと思い,プリアンブルに \usepackage{hyperref} を追加してコンパイルしたところ:
Paragraph ended before \Hy@setref@link was complete.

というメッセージが出て止まってしまった.関連するファイル,つまり hoge.aux, hoge.idx, hoge.out, hoge.log を一度全部削除してからコンパイルしたら通った.これらの関連ファイルはTeXworksの「ファイル」メニューから削除できる.