ことはじめ

にほんごのれんしゅうにっき

天気の子を観た

酔っ払った勢いに任せて書いた。ネタバレ注意。




我々は成長したので今となっては理不尽を押し付けられたところでうるせえよみたいな感じで突っぱねるという術を身に付けたけれど、あの頃の僕らは社会の厳しさといったものに飼いならされて自分自身さえ自分に厳しくなっていて、それで下らない(ほんとうは下らなくはないのだけれど)葛藤とともに何も得られずに曖昧になってしまっていたんだ。
結局の所、そのような「厳しさ」が物語のリアリティであって、それがハッピーエンドを阻害していた。
天気の子は、そういう厳しさというか物語的なリアリティをいい感じの理由(セカイはもともと狂ってる)でもって全部うるせえよといいつつ殴り飛ばしてくれた。
それが本当に最高に爽快で救われたんだ。
リアリティという名のしがらみを、自分に対する厳しさや非認容を、全部全部過去に。
僕らはやっと前に歩きだすことができると確信できたんだよ。
ウオー

std::accumulate de overflow

何も考えずに使ってると嵌るよーというお話.

こんなコードを書いたのですが結果がどうもおかしい.

using ull = unsigned long long;
 
std::vector<ull> v = {/* いっぱい */};
ull sum = std::accumulate(v.begin(), v.end(), 0);


うーんうーん唸ってたわけですがライブラリのコードを見れば一発だったわけで...

template <class InputIterator, class T>
T accumulate(InputIterator first, InputIterator last, T init)
{
    for (; first != last; ++first)
        init = init + *first;
    return init;
}

こうなってます.

要は InputIterator::value_type なんか見てないし返り値の型は init のみで決まるよーということ.
なんとなく unsigned long long になってくれるみたいな思い込みで嵌ってしまった例です.

サフィックスつければ解決です. こんなことで嵌るなんて...
他の解決策は関数テンプレートを明示的にインスタンス化するとか init を static_cast するとかですかね.


すごく冗長だけど accumulate の実装をこんな風にすれば問題ない?(decltype~が2つとも同じ...
C++14 なら decltype(auto) が使えるので綺麗になりそうです.

template <class InputIterator, class T>
auto accumulate(InputIterator first, InputIterator last, T init)
-> decltype(std::declval<typename std::iterator_traits<InputIterator>::value_type>() + std::declval<T>())
{
    using RType = decltype(std::declval<typename std::iterator_traits<InputIterator>::value_type>() + std::declval<T>());
    RType ret = init;
    for (; first != last; ++first)
        ret = ret + *first;
    return ret;
}

Kernel/VM探検隊 北陸 #1 でLTしてきた

今更ですが書きます.

なんの因果か低レイヤーなんて全くわからないわたしがKernel/VM でLTすることに.
発表が初めてだったのでかなり緊張してぐでっていたような気がします.
後でYouTubeで見られるらしいけど、見るの怖いですね...
もともと発表者が不足しそうだったという理由からなのですが、最終的には十分人が集まったようで良かったです.


LTの内容ですが C++ のテンプレートお話でした. スライドは以下から
http://www.slideshare.net/kotoji/tick-36900812

Tick内でテンプレート引数を関数の形にして渡すのとかなるほど~と思いつつ他に方法はないのかなーと思ったり.
依存ライブラリがないのでBoostとか読むよりわかりやすくていい感じです.

人前で発表するので適当なことは言えないと思って、スライドを作るためにかなり一生懸命調べ物をしたりコード読んだり書いたりと必死になってたので結構勉強になりました.
やっぱり勉強会って発表者が勉強する場なんですね.


他の人の発表だとorumin(@kotatsu_mi)さんの CRuby on OSv が興味深かったです.
OSv は基本JVM上で動くアプリケーション前提なのですが libc があるから CRuby 動くのでは?的な話.
実際そう上手くはいかないため様々なハックが必要だったようで.
それを見て楽しそうだなあと思ってしまった自分が悔しい(ry. 低レイヤーの魅力には屈しないぞ.


最後にじゃんけん大会の話を
景品はHHKBでした. Proが1つとLiteが5つだった気がします.
結局一瞬で負けてしまったものの、

このTweetを懇親会で隣になった@Akkiesoftさんが見ていたらしく, 譲っていただけることに.



ありがとうございますっありがとうございますっ.
大事に使わせて頂いてます.

結局発表でアバったものの楽しい気分で勉強会を終えることができました.


その後@sushi514さん達とやっほーしてきたのはまた別のお話.

cpp-netlibを導入した

C++でHTTP通信がしたくなったのでcpp-netlibに手を出したのだが...
情弱ゆえにおかしな行動をとって勝手に嵌っていた.
結論まで読み飛ばしてOKです.

ここから古いものを落として使っていた

https://github.com/cpp-netlib/cpp-netlib/downloads
→ 型が合わないとかで上手くビルドできない
一部の必要な共有ライブラリはビルドできていたのだがまともに使えず(後述).

最新をcloneしてくれば良いのでは??

cpp-netlibをcloneしてくる
git submodule init
git submodule update
cmake .
uri, deps/gmock, deps/gtest のCMakeLists.txtが無いと怒られる(git submodule で引っ張ってくるんじゃないのかよ...)
uri, deps/gmock, deps/gtest は別途cloneする必要がある
その後cmake . するも
/deps/igloo/igloo/external/snowhouse の中身がないとエラー
これも別途cloneが必要
http/test/v2/client/features 以下にある.cpp でエラーがでるので
return TestRunner::RunAllTests(argc, const_cast(argv));

return TestRunner::RunAllTests(argc, argv);
と書き換えて無理やりテストを通す

→ ライブラリが生成されない (テストはしらせてただけっぽい?)

多分設定でどうにか出来るんだろうけどそれまでがめんどくさすぎる...

結論

ここから新しいの持ってきて使いましょう(解決)
http://cpp-netlib.org/
気付かなかった自分が悪い (何故か見逃していた)
基本的にCMakeすればおわりです.
ビルド大変って聞いていたけど昔の話だったようだ.
BoostやOpenSSLが入ってればパス通すだけです.

サンプル

TwitterAPI にあくせす

#define BOOST_NETWORK_ENABLE_HTTPS
#include <boost/network/protocol/http/client.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/asio.hpp>

void callback(boost::shared_ptr<boost::asio::io_service>& io_service,
              const boost::iterator_range<const char*>& range,
              const boost::system::error_code& error) {
    if (!error) {
        std::cout << range << std::endl;
        io_service->stop();
    }
}

int main() {
    using namespace boost::network;
    using client_t = boost::network::http::basic_client<boost::network::http::tags::http_async_8bit_tcp_resolve, 1, 1>;
    using respons_headers = boost::network::headers_range<client_t::response>::type;
    using client_options = boost::network::http::client_options<boost::network::http::tags::http_async_8bit_tcp_resolve>;
    using string_t = boost::network::string<boost::network::http::tags::http_async_8bit_tcp_resolve>::type;

    // Twitterのアクセストークンを手に入れたい
    const std::string credentials = "consumer_key と comsumer_secret をコロンでつなげてbase64エンコードしたもの";
    client_t::request request("https://api.twitter.com/oauth2/token");
    request << header("User-Agent", "asio")
            << header("Connection", "close")
            << header("Authorization", "Basic " + credentials)
            << header("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
            << header("Content-Length", "29");
    
    auto io_service = boost::make_shared<boost::asio::io_service>(); // std::sharedだと怒られる...
    client_options options;
    options.io_service(io_service);
    client_t client(options);
    client_t::response response = client.post(request,
                                              string_t("grant_type=client_credentials"),
                                              boost::bind(&callback, io_service, _1, _2));
    io_service->run();                                        
}

HTTPのリクエストヘッダの追加など見やすくていい感じ.
io_service->run() でPOSTして, 返ってきたデータはcallback関数に処理させてます.
client_t (と名をつけたもの) のコンストラクタに直接 io_service を渡せないので client_optionsを経由させてあげる必要があります.
というのも basic_client のコンストラクタが BOOST_PARAMETER_CONSTRUCTOR で生成されていて io_service を受け取るコンストラクタは生成されないからです.
ちなみに, 古いバージョンでまともに使えないといったのがここで, コンストラクタは io_service を受け付けないし client_options は受け付けてくれるらしいがそもそも古いバージョンに client_options になんてものは存在しなかったのだ.

結果

{"errors":[{"code":99,"label":"authenticity_token_error","message":"Unable to verify your credentials"}]}

ぐぬぬ

brew update のエラー

brew update はよくエラーがでて困るのだけど今回のは初めてだったので書いておく。

$ brew update
error: insufficient permission for adding an object to repository database .git/objects
fatal: failed to write object
fatal: unpack-objects failed
Error: Failure while executing: git pull -q origin refs/heads/master:refs/remotes/origin/master

何がきっかけかわからなかったがgitのリポジトリがおかしくしてしまっていた模様。
.git/objects/ 以下のファイルの所有者がrootになったりしていたのでそれをローカルのユーザに直してやったら直りました。

$ cd /usr/local
$ sudo chown `user-name' .git/objects/*

EclipseでC++11を使おうとした話

今までEclipseC++を書くことがなかったのでふつーに書いたらふつーに怒られてしまった。

そこでEclipseC++11に対応させるためにググってみた。
http://stackoverflow.com/questions/9131763/eclipse-cdt-c11-c0x-support

この方法によると、プロジェクトのPropertiesを開いて左側のC/C++ BuildからSettingsを選択。
すると右側にいくつかタブが存在するのでそこからTool Settingsタブを選択して〜という流れで設定するようだ。

しかし、なぜかわからないけど自分のEclipseさんにはTool Settingsタブなるものは存在しなかった。

それで他にも調べてみたらなんとか方法が見つかった。
http://stackoverflow.com/questions/11420336/cannot-set-eclipse-juno-c-with-std-c11

ようするにmakefileコンパイラオプションを書けばいいということなので、
LOCAL_CFLAGS := -std=c++11
の一行を追加してやればいい。

これで一応怒られずにコンパイルすることができた。けど、IDE使ってるのにmakefile書くのはなんだか負けた感じが…

3D学習帳 2

ワールド座標変換(つづき)

前回のワールド変換行列をDirectXを使ってつくってみる。

拡大縮小

DirectXではD3DXMatrixScaling()なる関数が提供されているのでそれを使います。

D3DXMATRIX* D3DXMatrixScaling(
    D3DXMATRIX *pOut,    // 演算結果である D3DXMATRIX 構造体へのポインタ。
    FLOAT sx,             // x方向の拡大率
    FLOAT sy,             // y方向の拡大率
    FLOAT sz              // z方向の拡大率
);

回転

D3DXMatrixRotationX()
D3DXMatrixRotationY()
D3DXMatrixRotationZ()
の3つの関数が用意されてます。

D3DXMATRIX *D3DXMatrixRotationX(
    D3DXMATRIX *pOut,    // 演算結果である D3DXMATRIX 構造体へのポインタ。
    FLOAT AngleX          // x軸を回転軸としたときの回転角[rad]
);

D3DXMATRIX *D3DXMatrixRotationY(
    D3DXMATRIX *pOut,    // 演算結果である D3DXMATRIX 構造体へのポインタ。
    FLOAT AngleY          // y軸を回転軸としたときの回転角[rad]
);

D3DXMATRIX *D3DXMatrixRotationZ(
    D3DXMATRIX *pOut,    // 演算結果である D3DXMATRIX 構造体へのポインタ。
    FLOAT AngleZ          // z軸を回転軸としたときの回転角[rad]
);

平行移動

D3DXMatrixTranslation()関数が提供されてます。

D3DXMATRIX* D3DXMatrixTranslation(
    D3DXMATRIX *pOut,    // 演算結果である D3DXMATRIX 構造体へのポインタ。
    FLOAT x,              // x方向の移動
    FLOAT y,              // y方向の移動
    FLOAT z               // z方向の移動
);

作る

全体を0.8倍してx軸周りに90度、z軸周りに30度回転した後にx方向に150移動するようなワールド変換行列をつくってみます。
行列を掛ける順番に注意。

D3DXMATRIX matWorld;    // ワールド変換行列

// まずは平行移動
D3DXMatrixTranslation(&matWorld, 150.0f, 0.0f, 0.0f);
// z軸回転
D3DXMatrixRotationZ(&matWorld, D3DX_PI/6.0f);
// x軸回転
D3DXMatrixRotationZ(&matWorld, D3DX_PI/2.0f);
// 最後にスケーリング
D3DXMatrixRotationX(&matWorld, 0.8f, 0.8f, 0.8f);

これでワールド変換行列matWorldが出来上がるので、こいつをデバイスに結び付けてやればいい模様。