A fine WordPress.com site

投稿者アーカイブ

boost::multiprecision 仮数部・指数部の取得

ドキュメントが足りてない感じで、理解するのに結構時間を要してしまったので備忘録。 長精度の整数型 cpp_int 、長精度の浮動小数点型 cpp_dec_float, 長精度の分数型 cpp_rational と大別して3タイプの型があり、精度指定ができるなど、それぞれのタイプも細かい設定ができるようになっています。そうすると、無数に型が作成可能な状態になり、爆発する型同士の組み合わせによる演算を、ひとつひとつ書いてたら大変な事になります。これを解決するために MPL を利用して型同士の種類で処理を分岐させています。 系統だって演算できるようにするための基本型が、number < BackendType, ExpressionTemplates > になり、BackendType が先の3タイプの型に相当します。 それぞれのタイプの型のメンバ関数にアクセスしたければ、number::backend() というメンバ関数をコールして、BackendType を取り出しアクセスする感じになります。 以下、サンプルです。


#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>

using namespace boost::multiprecision;


int main() {
number<cpp_int_backend<256, 256, signed_magnitude, unchecked, void> > bi = 323456789012;
number<cpp_dec_float<50> > bf( "123456789012.3456" );

std::cout << bi << std::endl;
std::cout << bf << std::endl;

bf = static_cast< number<cpp_dec_float<50> > >( bi );

std::cout << bf << std::endl;
double m;
boost::int32_t e;
bf.backend().extract_parts(m,e);
std::cout << "mantissa = " << m << ", exponent = " << e << std::endl;
std::cout << "isint ? " << bf.backend().isint() << std::endl;
return 0;
}

NEX-5R レビュー

 レビューと言っても、今まで、ちゃんとしたカメラ持ってなかったので、それから比べると「月とすっぽん」ぐらい違います。だから、比較となる対象が無いんです。カメラにはまってくると、APS-Cじゃなくてフルのカメラが欲しくなってきます。でも、このカメラ、ザックの上にポイと突っ込んで持ち歩けるし、軽いし、ものぐさな自分の性格に合っていて、手持ちでホイホイとブラケット撮影できるので気に入ってます。最初のうちは、カメラの使い方がわからなくて、シーン撮影を選択して喜んでました。でも、ちょっと慣れてくると、ここら辺は全く使っていません。というよりも、邪魔なのでメニューから消して欲しいぐらいです。こんな小細工しなくても十分に綺麗だと思ってます。おまかせオート機能も使っていません。ただし、1枚ものの撮影に、プレミアムおまかせオートを使用する事は多々あります。パノラマ撮影は、たまに使用します。状況に応じた計算をしやすいので、シャッタースピード優先と絞り優先のモードばかり使ってます。
 オートフォーカスですが、撮影してると微妙に違う部分にピントが合ってしまう事が多いので、DMFにて最終的なピント位置はマニュアル調整しています。自分は、風景写真が好きなので、オートフォーカスだけの打率で考えると、ピントが気に入らなくて捨てる写真が半分ぐらいはある感じです。フォーカスを自分で最終調整している関係上、フレキシブルスポットで、撮影する毎にモニタを押してターゲットの位置を変更してます。補助としてフォーカスされている部分を赤色に塗る機能はオンにしてます。撮影してる時は撮影だけに集中したいので、撮った写真が表示されると邪魔です。なので、撮影後の写真レビュー機能はオフにしてます。
 NEX-5Rを選んだ理由のうちのひとつは、Wifiでコントロールできるからで、色々とコントロールできるんじゃないかと楽観的に考えてました。そのために、中華PADも購入して、Root 取ってパケット・キャプチャもしました。Soap だったり、HTTP の Json だったりと、プロトコルに何を使ってるかぐらいまでは解析してみたんですが、RAWで保存してくれない作りっぽくて、ガッカリしてます。リモコンではブラケット撮影できないですし・・・。
 目下の不満は、リモコンでのブラケット撮影ができない部分でしょうか?AndroidにRAWデータを転送して表示しろなんて言いませんから、リモコンで5連とか7連のブラケット撮影モードが欲しいです〜(´;ω;`)。フォーカスは微調整を手でコントロールしているぐらいなので、強制オートフォーカスにされると使い物にならなくて困ります。
 まぁ、なんというか、すっかりHDRにはまって、± 2.0 ev のブラケット撮影を多用してます。そういう意味では、手振れ補正機能のオン・オフも簡単に変更できるようFnキーに割り当てられていると嬉しいかなぁ?


電子帝国時代

 久しぶりに、IT関連に関する雑感を書きます。  うちの会社ではGISを開発しているんですが、まぁ、いろいろと考えて、やってきても、帝国軍は全部根こそぎ持っていくんですわ。  今回、ESRI社のGISフォーラムに参加してきました。FOSS4Gとは対極にあるクローズドな会社だと思います。どこが凄いかというと、痒いところに手が届く、行き届いたサービスです。APPLEのデザイン力が素晴らしいのは周知の事実だと思いますが、ESRIのGISの機能は、柔軟かつ手数が少なく作業ができるようデザインされており、素晴らしいです。そんなESRI社の次なる動向を見て思ったのは、今まで隙間だと思っていた場所を埋め合わせるような新たな製品の投入。弱小企業が必死になって考えだしたビジネス領域を根こそぎ攫うかのような製品投入です。これだけじゃなく、ESRI社が強いのは、そのSIサポート体制と言えるかもしれません。市場開拓・育成・サポートまで一貫して行います。  Google Maps Engine 一般提供も視野に。Googleが B2B の細い分野まで侵食してくるとは思いませんでした。もうね、帝国軍レベルで隙間も注入されたら、どこにも余地ありませんわ。  今までのお客さんがいるので、簡単に辞められないですけど、もう会社たたんだ方が良いんじゃないかと思いますわ。うちの社員もSEのくせに GitHub ってなんですか?ってレベルだし、公開サイトにおいて、IE10やChrome でまともに動作しない状況について何の疑問も持たないセンスですしね。とうとうと、今 Chrome のシェアが一番でな、IEのバージョンも10の割合が増えてきてるんだよ、などと、アンテナベースの話からしなきゃならないとか、戦える気がしないですわ。  Apple が取り沙汰されるようになってから、Google も変わりましたよね?スペックや性能について、あまり語らなくなったと思いませんか?もちろん Google はオープンな企業で、特に隠し立てをしているという事は無いんですが・・・。  クリス・アンダーソンさんのFREEもどうなんでしょう?Makerでは、販売価格は製造原価の3倍で良いとか書いてるじゃないですか、労働コストの手間賃が含まれてるんですよ。なのに、ソフトウェアとコンテンツはFREEなんです。なんで、こうなってしまうのか?クラウドですよ。クラウドは便利ですが、胴元ビジネスなんです。ショバ代を徴収してテラ銭跳ねて、軌道に乗れば絶対に損しないビジネスなんです。ただし、ライバルに出し抜かれない限りは。みんな必死で進軍をやめるわけないですよね?電子帝国時代の到来です。  電子帝国時代に突入して若干空気が変わったと感じる事があります。ビジネス化するつもりのアイディアは口外せずに粛々と進めて、一挙に公開するとか、そんなんが増えてきているのかなぁと…。ま、特に根拠があるわけじゃないです。トップ・インタビューを読んでても、技術的・直接的な表現が減って、オブラートに包んだコンセプト的なものが増えてるような気がしてます。そういう意味じゃ、日本のメディアが日本の強みは、どこどこで、とか全部ノウハウに相当する部分を細かく分析して図表まで書いて披露するのは、へぇ~かもしれませんが、電子帝国時代にはマイナスなのかなぁと思う事もあります。トップの方も、技術的なノウハウに相当する暴露は控えて、テイストとか人間の感性に訴える部分に置き換えて表現した方が良いんじゃないでしょうか?  オープンソースもね。それで食ってくの辛いですよ。労働コストに対して「でも、お高いんでしょ?」の一言で片付けられてしまうような側面を持ってるんですよ。サラリーマン・タイプの人は、自分の職業で自分が働いた対価に対して経営層が、なんかお金に変えて賃金払ってくれるから、自分の労働コストに対しては厳しく文句言うくせに、他人の労働コストに対しては、平気で高いとか言うんですわ。君の給料は、どこからきてると思っているのか?もうちょっと、労働対価に関する価値観を教育していかないと、電子帝国時代は厳しい世界になるんじゃない?そんな風に感じてます。  あまり技術的な話を書くとね、帝国軍にサルベージされて持ってかれそうで嫌なんですけど。クラウドの次は、真の分散が来るんじゃないかと。そうでもしないと、胴元ビジネスの帝国主義は打破できないんじゃないかと。フォッグ・コンピューティングなる言葉があります。意味合いが若干異なりますが、自分も同じような事を考えていました。ジャンルは NoSQLに近いです。NoSQLの世界では、耐故障性能を上げるためにノード間でレプリケーションするやないですか?それって、見ず知らずのデータベース間でもスキーマが同じなら、データ交換が技術的には可能ですよね?て事はですよ?NFCとか使ってスレ違いざまにデータ交換できますよね?東北大震災の時に被災地のデータを人々がスレ違いざまにデータ交換して、自己組織化のようにデータが伝搬していく。クラウド無しでも行けると思いませんか?と、こんな事も考えてるんですが、自分とこではリソースをさく事態にならないと思うんで、面白いと思った人に託しますね。


android ndk と java から sqlite3 でアクセスするとどうなる?備忘録

 ndk からsqlite3 データベースを読みだしている状態で、android sdk の java が、データベース更新時に、時々例外を発生する事がある。どんなカラクリになっているのか気になって調べてみるとtwo connection to sqlite from java application and from ndkの情報が正確そうだ。Android SDK のJavaコードでは、1000mm sec 待っても応答が無ければ例外を送出する仕様であるらしい。言わせてもらえると、例外が発生するようなケースは、レアケースじゃね〜Ze。こんちくしょう。 自分の ndk でのレコードアクセスでは


#pragma once
#ifndef SQLITE_ACCESS_HPP
#define SQLITE_ACCESS_HPP

#include <sqlite3/sqlite3.h>
#include <functional>
#include <memory> // unique_ptr
#include <log.hpp>
#include <unistd.h>

namespace sio {

template <class Container, class ReadOpe>
bool read_rows(
sqlite3* db,
const char* sql,
Container& container,
ReadOpe ope,
const char* target_name
) {
sqlite3_stmt* stmt = nullptr;
int res = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr );
if( SQLITE_OK != res ) {
__android_log_print(ANDROID_LOG_ERROR, target_name, "Fail to read rows: %d", res );
return false;
}
std::unique_ptr<sqlite3_stmt,std::function<void(sqlite3_stmt*)> > stmt_holder( stmt, sqlite3_finalize );
while(true) {
while( res = sqlite3_step(stmt), SQLITE_BUSY == res ) { usleep(10); }
switch( res ) {
case SQLITE_ROW: ope( stmt, container ); break;
case SQLITE_DONE: return true;
default:
__android_log_print(ANDROID_LOG_ERROR, target_name, "Fail to get row: %d", res);
return false;
}
}
}

} // namespace sio

#endif // SQLITE_ACCESS_HPP

こんな感じで処理していて、他のプロセスやスレッドによって書き込みが阻害されている場合には、何mm sec スリープさせれば良いかわからないけど、とりあえず10mm sec 休ませる事にしているのだが、Android SDK は問答無用で1秒タイムアウト。 詰んだ\(^o^)/ まぁ、1秒にでもしとかないとデッドロック等のケースに対処できないから、しょうがないのかもしれない。  多分、例外が発生したら、もう一回同じ更新をJavaの方でかけに行くのが、いいのかなぁ?


HDRにはまってるのだ

 はい、HDR(High Dynamic Range)写真にはまってます。Photomatrix Pro を買いました。まぁ、色々とやってるんですが、大阪の実家の近くに「大阪芸術大学」なんてのがありまして、小学校の頃、よくここで遊んだんです。ここの建物、コンクリートむき出しの打ちっぱなしで、当時、奇天烈なデザインで印象深く、HDRやるなら是非ここをモチーフにしたいと思っていました。HDRの仕上げも、色々あると思いますが、自分は、どちらかというと頭の中の源風景を再現した自然な仕上がりが好きです。若干、カリッと仕上がっていると思いますが、コンクリートの黒ずんだ感じは、個々のパーツをよく観察すると、ほんとに、こんな風になってます。
 1枚目は、芸大正面口からの眺め
正面口から、先ほどの建物の方に向かって坂を登っていきます。

開けた所で特徴的な、この建物

その脇を当時としては変わった天窓付きの宙2階のようなスペースがあります。

こちらは、上の風景の反対側。庭園になりますが、昔はもう少し雑だったような気もします。

入り組んだ、コンクリート打ちっぱなしの建物があります。

コンサートのできる彫り込んだような庭のスペースもあるのですが、写真にパープル・フリンジが起こっていて、やむなく断念しました。まだまだ、新しい建物も面白いのですが、自分が小学生だった頃は、だいたい、ここら辺の建物までで、後は部活用のプレハブだったり、石膏を固めた彫刻模型のようなものが無造作に打ち捨てられていたりと、そんな感じでした。池があったスペースも、今では、だいぶ埋め立てられているようです。
写真の出来には満足してます。


android Intent で画像編集、備忘録

 android.net.Uri の作成の仕方によっては、「ファイルが見つかりません」と、つれなくあしらわれるので備忘録。 以下のようなやり方だと、ファイルを認識できない。


public void editImage( String path, String filename ) {
Uri imageUri = Uri.parse( path + "/" + filename );
Intent launchEditor = new Intent();
launchEditor.setAction(Intent.ACTION_EDIT);
launchEditor.setDataAndType(imageUri, "image/jpeg");
activity.startActivityForResult(launchEditor, 0);
}

 ちゃんと、File クラスを通じて生成する事


public void editImage( String path, String filename ) {
Uri imageUri = Uri.fromFile( new File( path, filename ) );
Intent launchEditor = new Intent();
launchEditor.setAction(Intent.ACTION_EDIT);
launchEditor.setDataAndType(imageUri, "image/jpeg");
activity.startActivityForResult(launchEditor, 0);
}

室蘭散策街中編

 朝起きて、ホテルから昨夜の風景をパチリ、工場は眠らない。時間もあるので街中を散策する事に…

 東室蘭の高架橋から、いたるところから工場が望めます。
 工場の方から鉄パイプが!さすが室蘭
 テツプロさんにやってきました。

 ここで、テツプロさんをあとにし、近所のスーパー、その名も「ぷらっと・てついち」に。

 さすが鉄の街!アートな鉄の看板

 いやはや、なんともオシャレですね!
外には、こんな鉄のオブジェまであります!
 お昼には少し早かったのですが、カレーラーメンを食べました。
 大王ではなく、蘭たん亭さんです。
 地味に福神漬けが良かったです。
帰りは、時間の都合で、東室蘭駅までタクシーにのり登別へと移動しました。随所に鉄を生かしたモチーフがあり、味があります。

室蘭散策ナイトクルージング編

ゴールデンウィーク前半で室蘭に行ってきました。お目当ては、焼き鳥と工場写真です。
もう完全にGoogle+で写真に毒されてきてまして、はまってます。
とは言え、家族旅行なんで、あまりじっくり写真を撮ってる暇はありません。三脚も持参して、あわよくば…と思っていたのですが、ホテルからと、苫小牧駅でしか三脚を使うチャンスはありませんでした。

工場ナイトクルージングに出かけたのですが、車が無くて難儀しました。バスに乗ったら、白鳥大橋の袂まで行くのに、ぐるぐると、あっちこっち寄り道をして、なかなか近づかない。親子3人だったらバス代と時間を考えても、室蘭駅からタクシーに乗った方が安上がりでした。船着場近くで撮った白鳥大橋が上下2枚。上はハレーションを起こしてます。構図的にも、もっと引いて撮りたい感じです。

風は強くて、かなり寒い中、ナイトクルージングに出発です。風が強くて、寒い上に結構上下しました。

見えてきました!工場です!

海上からだと、やっぱ、ハッキリ見えます。

徐々に日は暮れて

刻々と変化していきます。


この辺りから、ピンぼけ&ブレまくりの失敗写真が多くなります。

ふぉおおおお

 ほぇえええ

 ふぉおおおお

そんな感じで、通り過ぎてゆきます。
橋にも明かりが灯ってきました。
間近で見る白鳥大橋は、本当に綺麗でした。
素晴らしい!夢の世界のようです。

フレアスタックが見えますが、9割9分は、これよりもひどい状態でピンぼけかブレブレでした。残念です。

また、リベンジしたいです(>_<)

 雰囲気は伝わるでしょうか?

 奇跡的に撮れた写真その1

奇跡的に撮れた写真その2
終始こんな感じでブレてますが、さらば室蘭!白鳥大橋!
 さて、帰りですが、タクシーで室蘭駅に向かうのが正解です。東室蘭から室蘭間の方がJRの本数は多いです。崎守駅の方は魅力的ですが、家族連れには向いてませんorz JRが来ないのです。
 飯は、またまた鳥辰に行ってしまいました。

ホテルに帰って部屋から三脚使って夜景を撮りました。見えないものを撮るので、ホワイトバランスの調整に悩むところです。オートにするとこんな感じです。ナイトクルージングでは、状況がわからないので、NEX-5RYの標準ズームレンズを使用しました。この写真も同じレンズで、ISO100のシャッター速度が20〜30秒ぐらいで撮影しました。

こちらは、SEL50F18の単焦点レンズで、ホワイトバランスを蛍光灯で撮影しました。なんと、こちらのレンズだとISO100のシャッター速度12秒ぐらいで撮影しても明るすぎて白飛びします。なので、-ev 調整しました。ナイトクルージングでは、高感度がものを言いそうなので、こちらのレンズで勝負すべきだったと思いました。ただ、こちらのレンズの場合、標準ズームレンズに比べてピントを合わせるのが難しいんですね。そういう不安はあります。

boost::any で比較

データベースのデータを透過的に扱おうとすると、型が〜型が〜って、結構面倒くさい。 なるべくなら、楽をしたいです。もっとスマートな書き方無いのかな。


#include <boost/any.hpp>
#include <string>
#include <functional>
#include <iostream>
#include <exception>

template < class T, class OPE = std::binary_function<T,T,bool> >
bool in_type_ope( boost::any data, boost::any value, OPE ope ) {
try {
return ope( boost::any_cast<T>(data), boost::any_cast<T>(value) );
} catch( std::exception& e ) {
return false;
}
}

int main() {
boost::any a = 1;
boost::any b = 2;

std::cout << in_type_ope<int>( a, b, std::less<int>() ) << std::endl;
std::cout << in_type_ope<int>( b, a, std::less<int>() ) << std::endl;
a = 2;
std::cout << in_type_ope<int>( a, b, std::equal_to<int>() ) << std::endl;

return 0;
}

sqlite3でオンメモリDB

sqlite3 でスキーマ関係なく操作したい。オンメモリDBが便利。


#include <iostream>
#include <string>
#include <sqlite3.h>

int main() {
sqlite3* db = nullptr;
int resdb = sqlite3_open(":memory:", &db );
std::cout << resdb << std::endl;
sqlite3_stmt* stmt = nullptr;
sqlite3_prepare_v2( db, "select datetime('now','localtime')", -1, &stmt, 0 );
sqlite3_step( stmt );
std::cout << "type = " << sqlite3_column_type( stmt, 0 ) << std::endl;
std::cout << "value = " << sqlite3_column_text( stmt, 0 ) << std::endl;
sqlite3_finalize( stmt );
sqlite3_close( db );
return 0;
}

C++ レガシー文字列変換で気をつける事

 今更、何を書いてはんの?だとは思いますが、ついつい、うっかりしがちなんで


#include <iostream>
#include <string>

std::string get_string( const char* str ) {
std::string result = str;
return result;
}

int main() {
std::cout << get_string( nullptr ).size() << std::endl;
std::cout << " OK? " << std::endl;
return 0;
}

実行結果


terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid
Abort trap: 6

eclipse ADT で、jar ファイルの依存関係をコントロールする。

 プロジェクトの規模が大きくなってくると、パッケージを分離してライブラリを再利用する事になると思います。 ところが、この依存関係の設定の自由度が低くて頭にきます。  今回は、Android プロジェクトで、jar ファイルの依存関係をコントロールする方法を書きます。 プロジェクト・ディレクトリ直下にある .project という XML ファイルを開きます。 そして、linkedResources 要素の下に link 要素を追加、または、修正します。  $%7BPARENT-2-PROJECT_LOC%7D という怪しい呪文に関しては、こちらを参考にしてください。 こんな感じです。


<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>YourApplicationProject</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
<dictionary>
<key>?children?</key>
<value>?name?=outputEntries\|?children?=?name?=entry\\\\\\\|\\\|?name?=entry\\\\\\\|\\\|\||</value>
</dictionary>
<dictionary>
<key>?name?</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.append_environment</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildArguments</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildCommand</key>
<value>ndk-build</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
<value>clean</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.contents</key>
<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
<value>false</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableFullBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.stopOnError</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
<value>true</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
<linkedResources>
<link>
<name>libs/acra-4.3.0.jar</name>
<type>1</type>
<locationURI>$%7BPARENT-2-PROJECT_LOC%7D/Ref/Java/acra-4.3.0.jar</locationURI>
</link>
<link>
<name>libs/android-support-v4.jar</name>
<type>1</type>
<locationURI>$%7BPARENT-2-PROJECT_LOC%7D/Ref/Java/android-support-v4.jar</locationURI>
</link>
<link>
<name>libs/calc.jar</name>
<type>1</type>
<locationURI>$%7BPARENT-2-PROJECT_LOC%7D/Ref/Java/calc.jar</locationURI>
</link>
</linkedResources>
</projectDescription>

中華PAD mac で adb devices にリストアップされない備忘録

  Android でパケットキャプチャしたくて、root 取ろうとしたんですが、IS03 は、バージョン上がりすぎてて取れず。試行錯誤したけど、どの方法もダメでした。Nexus7 は、一度文鎮化しますた。手順は間違えてないと思うのですが、個体差なのか、仮想マシンのWindows7上で作業したのがまずかったのか?どうも祟られているようで、クラッカーでもないのから、脆弱性を探して root 取るとか、そんな事にリソース(自分の時間)を使うのも、いかがなものかと思いまして、中華Pad を購入しました。
 友人に「赤札天国」なるものを紹介してもらい、そこからゲットです。

 さて、USBに接続しましたが、adb devices で、中華Pad がリストアップされません。困った。adb shell を使えないと、戦力ダウンも甚だしい。ググって、StackOverflow からの情報でデバイスを認識させる事ができました。

 「このMacについて」を選択し、「詳しい情報」を選択し、以下のダイアログを表示したら、「システムレポート…」を選択します。

 続いて、USB を選択し、中華PADだと思われるハブを選択し、「製造元番号」に書かれている値をメモります。

 そして、この場合だと製造元IDが 0x10d6 なので、
$ echo 0x10d6 >> ~/.android/adb_usb.ini
として、
$ /opt/android-sdks/platform-tools/adb kill-server
$ /opt/android-sdks/platform-tools/adb usb
$ /opt/android-sdks/platform-tools/adb devices
でリストアップされるようになります。

GeoTIFFにやられまくり

TIFFTAG_GDAL_NODATA でハマった事を書きましたが、続きがあります。
GeoTIFF では、GDAL_NODATA に設定された値がアルファ値0、つまり透過として扱われる事になります。
RGB3バンドあった場合に、R == 255 && G == 255 && B==255 なら透過扱いなんかなぁ?と思ってたんですが、どうも実装する人によって解釈が違ってて、RGB(255,0,0) が透過色に設定されてたりしました。こうなってくると、RGB(254,255,255) は透過扱いなのか、透過扱いでないのか?これすら怪しいです。
じゃあ、インデックス・カラーの場合は、どうか?というと、カラーインデックス番号 255 が透過扱いでした。いや、もうカオスで、嫌になってきます。
GDAL_NODATA が設定されてるんだから、もちろん、タイル内のブロック全てに、この値が適応されてるんですよね?と思ったら、画像高を越えた領域には、設定されていませんでした。お陰で、黒い領域が出現して何事かと思いましたよ。

関係ないですけど、なんか、ブログの RSS フィードがおかしくなって出力されないですし、Blogger サービスもいつまであるかわからないので、引越しを検討した方がいいのかなぁ?なんて考えてます。


写真にはまってます

 iPadとか、スマフォとかデジカメとか、今まで、おまかせで写真を撮ってたんで、雪の日に「こんなに降ってきたぞー」というのを表現したくても、いざ撮れた写真を見ると、そうでもなかったりして、まぁ、写真とは、こんなもんかな?と思ってました。

 そこそこ良いカメラを手にすると、写りが綺麗で、テンション上がります。色々と深堀りしていくと、シャッタースピードの違いで動いているものがどういう風に映るかが変わってくるみたいなんですよ。

 まぁ、基本体育会系プログラマは、もちろん全部試してみるわけですな。いやー、面白いです。チャリで出かけたのに、雪がワシワシ降ってきて、酷い目にあったというのを表現したくて、G+ の投稿には、1/50s のやつを採用しました。表現に偽りもなく、帰りは、目を開けてられないぐらい雪がバシバシ当たって悲惨でしたorz

ちなみに写真に記録されたタグだと 1/200s  1/125s となってますが、記憶では、設定が逆のような気がしてます。見た目も、逆じゃないかなぁと。


シャッタースピード 1/50s


シャッタースピード 1/200s


シャッタースピード 1/125s


シャッタースピード 1/600s


シャッタースピード 1/800s


シャッタースピード 1/1000s


本日のげんなり TIFF編

 今日は参りました。 TIFFGetField という関数には、前回もやられているんですが、今回も、こてんこてんにやっつけられました。 TIFFTAG_GDAL_NODATA というタグの値を取得したくて、GDALのGeoTIFFパートを参考にコードを組んだら SIGSEGVの嵐。は〜 SIGSEGV、どんどん、ほぇー SIGSEGV、どんどん、ハイヤー SIGSEGV バンバン。


char* pszText = NULL;
if( TIFFGetField( hTIFF, TIFFTAG_GDAL_NODATA, &pszText ) )
{
bNoDataSet = TRUE;
dfNoDataValue = CPLAtofM( pszText );
}

突っ込んで面倒を見ていくと libtiff の tif_dir.c の int _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap) という関数でお亡くなりになっている事が判明しました。


// なんと、field_passcount > 0 が成立しているので
if (fip->field_passcount) {
if (fip->field_readcount == TIFF_VARIABLE2) {
// pszText にデータサイズが格納されて
*va_arg(ap, uint32*) = (uint32)tv->count;
} else /* Assume TIFF_VARIABLE */ {
*va_arg(ap, uint16*) = (uint16)tv->count;
}
// ありもしない第2の可変引数に値が格納されて
// ここであぼ~ん
*va_arg(ap, void **) = tv->value;
ret_val = 1;
}

(゚∀゚)アヒャ(゚∀゚)アヒャ。関数の仕様というか、TAGの仕様が変わっとるがなwww 知らねぇよヽ(`Д´)ノウワァァァン!! と言いながらコードを修正


uint32_t textLen = 0;
char* pszText = NULL;
if( TIFFGetField( hTIFF, TIFFTAG_GDAL_NODATA, &textLen, &pszText ) )
{
bNoDataSet = TRUE;
dfNoDataValue = CPLAtofM( pszText );
}

あれれ?まだまだ SIGSEGV おほー、どんどん SIGSEGV ひ~~。 更に突っ込んで面倒を見ていくと、同じく tif_dir.c にて


// えっ?今度は、field_passcount == 0
if (fip->field_passcount) {
//...
} else if (fip->field_tag == TIFFTAG_DOTRANGE
&& strcmp(fip->field_name,"DotRange") == 0) {
//...
} else {
// そして、field_type == TIFF_ASCII なので
if (fip->field_type == TIFF_ASCII
|| fip->field_readcount == TIFF_VARIABLE
|| fip->field_readcount == TIFF_VARIABLE2
|| fip->field_readcount == TIFF_SPP
|| tv->count > 1) {
// 第1引数 uint32_t にポインタ値が代入され
// 第2引数が放置プレーで、最終的にあぼ~ん
*va_arg(ap, void **) = tv->value;
ret_val = 1;
} else {
//...

 隊長!エスパーじゃないから、推定できましぇんヽ(`Д´)ノウワァァァン!!  ということで、とりあえず、2引数を取る形態で対処しました。


if (fip->field_type == TIFF_ASCII
|| fip->field_readcount == TIFF_VARIABLE
|| fip->field_readcount == TIFF_VARIABLE2
|| fip->field_readcount == TIFF_SPP
|| tv->count > 1) {
if( (tag == TIFFTAG_GDAL_METADATA) || (tag == TIFFTAG_GDAL_NODATA) ) {
*va_arg(ap, uint32*) = (uint32)strlen(tv->value);
}
*va_arg(ap, void **) = tv->value;
ret_val = 1;
} else {

 もの凄く疲れた。


Google Reader 終了で困った

 まぁ、一応書いておこうと思う。現在241フィードほど登録してます。C++ 系が多いのは置いといて、面白いと思ったブログなどは定点観測しています。RSS は死んだとか、ふざけた事を書いてるやつがいますけど、冗談はやめてください。どっちみち、面白いと思ったブログは巡回するんです。それを自動化してくれるITに相応しい手法が RSS Reader なんです。SNS の時代は情報はソーシャルから入手します?寝ぼけてんじゃねーぞコラァ?  という訳で、移行先を探しています。まだまだ保留していますが、第一候補は、livedoor reader かな?でも、なんか違うんですよね。次が Feedly か?まぁ、Google Reader 終了に備えて準備していただけあって、移行はスムーズにできました。ただ、フィードの消化が全くもって無理でした。せめてスペースキーとかでフィードをどんどん消化できるようじゃないと、使い物になりません。ここら辺が改善されれば、Feedly に決めようかなーと思いつつ保留してます。  他にも名乗りを上げているところがたくさんあるようなので、使い勝手をチェックしつつ6月中には移行先を決めたいと考えています。  どうせなら、読者購読とシェア機能を工夫して実装してもらえると、尚良いです。Google+ や Facebook とは違って、この部分のソーシャルは、ほんと面白かったんです。なんと言うか、鋭さが違います。


ポリゴンの髭を取り除く

 標準に無い変形アルゴリズムを晒してみようと思います。


//! 指定間隔の隣接検索
/*!
@note std::adjacent_find の要素間隔指定バージョン
@retval 前方の要素検索位置
*/
template <class FORWARD_ITER, class BINARY_PREDICATE>
FORWARD_ITER interval_adjacent_find(
size_t interval, //!< [in] 間隔
FORWARD_ITER first, //!< [in] 先頭位置
FORWARD_ITER last, //!< [in] 終了位置
BINARY_PREDICATE pred //!< [in] 2項演算子
) {
size_t dist = std::distance( first, last );
if( dist <= interval ) return last;
FORWARD_ITER next;
if( interval < dist / 2 ) {
next = first;
for( size_t i = 0; i < interval; ++i ) ++next;
} else {
next = last;
for( size_t i = dist; i > interval; --i ) --next;
}
while( next != last ) {
if( pred( *first, *next ) ) return first;
++first; ++next;
}
return last;
}

//! 指定間隔の隣接検索
/*!
@note std::adjacent_find の要素間隔指定バージョン
@retval 前方の要素検索位置
*/
template <class FORWARD_ITER>
FORWARD_ITER interval_adjacent_find(
size_t interval, //!< [in] 間隔
FORWARD_ITER first, //!< [in] 先頭位置
FORWARD_ITER last //!< [in] 終了位置
) {
size_t dist = std::distance( first, last );
if( dist <= interval ) return last;
FORWARD_ITER next;
if( interval < dist / 2 ) {
next = first;
for( size_t i = 0; i < interval; ++i ) ++next;
} else {
next = last;
for( size_t i = dist; i > interval; --i ) --next;
}
while( next != last ) {
if( *first == *next ) return first;
++first; ++next;
}
return last;
}

//! 指定間隔の隣接検索
/*!
@note std::adjacent_find の要素間隔指定バージョン
@retval 後方の要素検索位置
*/
template <class FORWARD_ITER, class BINARY_PREDICATE>
FORWARD_ITER interval_adjacent_find_later(
size_t interval, //!< [in] 間隔
FORWARD_ITER first, //!< [in] 先頭位置
FORWARD_ITER last, //!< [in] 終了位置
BINARY_PREDICATE pred //!< [in] 2項演算子
) {
size_t dist = std::distance( first, last );
if( dist <= interval ) return last;
FORWARD_ITER next;
if( interval < dist / 2 ) {
next = first;
for( size_t i = 0; i < interval; ++i ) ++next;
} else {
next = last;
for( size_t i = dist; i > interval; --i ) --next;
}
while( next != last ) {
if( pred( *first, *next ) ) return next;
++first; ++next;
}
return last;
}

//! 指定間隔の隣接検索
/*!
@note std::adjacent_find の要素間隔指定バージョン
@retval 後方の要素検索位置
*/
template <class FORWARD_ITER>
FORWARD_ITER interval_adjacent_find_later(
size_t interval, //!< [in] 間隔
FORWARD_ITER first, //!< [in] 先頭位置
FORWARD_ITER last //!< [in] 終了位置
) {
size_t dist = std::distance( first, last );
if( dist <= interval ) return last;
FORWARD_ITER next;
if( interval < dist / 2 ) {
next = first;
for( size_t i = 0; i < interval; ++i ) ++next;
} else {
next = last;
for( size_t i = dist; i > interval; --i ) --next;
}
while( next != last ) {
if( *first == *next ) return next;
++first; ++next;
}
return last;
}

//! 指定間隔の隣接検索
/*!
@note std::adjacent_find の INTERVAL 要素間隔バージョン
@retval イテレータ(要素検索位置)
*/
template <class FORWARD_ITER, class BINARY_PREDICATE>
FORWARD_ITER interval_adjacent_rotate_find(
size_t interval, //!< [in] 間隔
FORWARD_ITER first, //!< [in] 先頭位置
FORWARD_ITER last, //!< [in] 終了位置
BINARY_PREDICATE pred //!< [in] 2項演算子
) {
size_t dist = std::distance( first, last );
if( dist <= interval ) return last;
FORWARD_ITER result = interval_adjacent_find( interval, first, last, pred );
if( result != last ) return result;
return interval_adjacent_find_later( dist - interval, first, last, pred );
}

//! 指定間隔の隣接検索
/*!
@note std::adjacent_find の INTERVAL 要素間隔バージョン
@retval イテレータ(要素検索位置)
*/
template <class FORWARD_ITER>
FORWARD_ITER interval_adjacent_rotate_find(
size_t interval, //!< [in] 間隔
FORWARD_ITER first, //!< [in] 先頭位置
FORWARD_ITER last //!< [in] 終了位置
) {
size_t dist = std::distance( first, last );
if( dist <= interval ) return last;
FORWARD_ITER result = interval_adjacent_find( interval, first, last );
if( result != last ) return result;
return interval_adjacent_find_later( dist - interval, first, last );
}

何に使うかというと、—ABA— みたいな構成のポリゴンは、髭のように変な辺が飛び出しているので、それを消去するのに使います。–ABCBA–みたいなパターンもあるので、–ABA– を消去しても油断できません。地道に再帰で消し去ります。


//! 単純な連続重複があるか調べる
/*!
@retval true 重複あり
@retval false 重複なし
*/
template <typename T>
bool check_duplicate( const vector<T>& sec ) {
return (std::adjacent_find( sec.begin(), sec.end() ) != sec.end());
}

//! 単純な連続重複点を除去する
/*!
@note 先頭と末尾は連続としない
*/
template <typename T>
void deduce_duplicate( vector<T>& sec ) {
vector<T>::iterator f = std::adjacent_find( sec.begin(), sec.end() );
while( f != sec.end() ) {
sec.erase( f );
f = std::adjacent_find( sec.begin(), sec.end() );
}
}

//! 単純な連続重複があるか調べる
/*!
@retval true 重複あり
@retval false 重複なし
*/
template <typename T>
bool check_closed_duplicate( const vector<T>& sec ) {
if( sec.size() < 3 ) throw std::exception();
return check_duplicate( sec ) || (*(sec.begin()) == *(sec.rbegin()));
}

//! 単純な連続重複点を除去する
/*!
@note 先頭と末尾を連続とする
*/
template <typename T>
void deduce_closed_duplicate( vector<T>& sec ) {
if( sec.size() < 3 ) throw std::exception();
deduce_duplicate( sec );
if( *(sec.begin()) == *(sec.rbegin()) ) sec.pop_back();
}

//! ABAタイプの無駄な尾を除去する
/*!
@note ポリラインに使用する
*/
template <typename T>
void deduce_tail( vector<T>& sec ) {
vector<T>::iterator f = interval_adjacent_find( 2, sec.begin(), sec.end() );
while( f != sec.end() ) {
vector<T>::iterator g = f;
++g; sec.erase( g ); sec.erase( f );
f = interval_adjacent_find( 2, sec.begin(), sec.end() );
}
}

//! ABAタイプの無駄な尾を除去する
/*!
@note ポリゴンに使用する
*/
template <typename T>
void deduce_closed_tail( vector<T>& sec ) {
vector<T>::iterator f = interval_adjacent_rotate_find( 2, sec.begin(), sec.end() );
while( f != sec.end() ) {
vector<T>::iterator g = f;
++g;
if( g == sec.end() ) {
sec.erase( f ); sec.erase( sec.begin() );
} else {
sec.erase( g ); sec.erase( f );
}
f = interval_adjacent_rotate_find( 2, sec.begin(), sec.end() );
}
}

あんま、おもしろくないですかね。


std::move ではまった事

 いまの所、std::move ではまった事なぞを、思い出せる範囲で書いてみようと思います。

 直近では、ndk での話ですが、std::unique に move constructor と move operator しか持たないクラスの deque をかけると、見事にデータが壊れました。move に一部対応している状況なので、文句は言えません。自前で move 用の unique をこさえました。特に、このバグは場所を特定できるまでに凄い時間がかかりました。どこで壊れているのか探すのも大変でした。

 vector を std::move にかけて移動させると、要素が倍で増えました。これは、move 後の変数の状態は不定なので、move した後にも残骸が残っており、残骸要素が加算されていくというバグでした。move した後に clear() をコールする事で回避しました。

move constructor だけでなく、copy constructor も追加したら、copy が優先されて、予期せぬ挙動を引き起こしました。copy constructor は封印して、copy ファンクタを利用するようなアルゴリズムをこさえる事で回避しました。

一応、こんなところでしょうか?


Webサービスの難しさ

 会社で納品しているシステムで、PostgreSQL からデータを引いてサーバ側で地図を描画して配信しているシステムがあるんです。このシステムの難しさは、5分間隔とかでリアルタイムに大量の軌跡を描画しなければならん所です。しかも、24時間以内の長さで、好きな期間を指定できるのと、軌跡を表示する移動体を自由に選択できるところも難しいです。輪をかけて難易度を上げているのが、軌跡の点の上にマウスを置いとくと、その点の通過時刻を表示するという仕様です。この仕様のおかげで、データを点としてデータベースに保持するよりありません。大抵、負荷のかかる見方をするのが、直近の24時間程度という特性もあります。

 ポリラインとか、ポリゴンで登録されていれば、空間インデックスにかけて関係する部分だけを取り出し描画すれば良いんですが、軌跡の場合は、点と点を結ぶ線の情報が必要なので、空間インデックスで絞るわけにもいきません。なので、指定された期間中のデータを総なめする必要があります。

 さて、閲覧する人数が増えて負荷がかかると、PostgreSQL に対する負荷が膨大になり、ストールを起こします。PostgreSQL のチューニングもパンパンにやってて、1個のクエリー自体は普段、10 から 20 mm sec 程度で、それが移動体分になります。しょうがないんで、MySQL でやれば、もっと速いんじゃないの?と指示してテストさせてみましたが、あまりチューニング無しの MySQL だとスタート時点で、100 mm sec 以上かかっていて、MySQLに変更したからと言ってバラ色の人生が待ち受けている訳でもなく、成果も見込めないので、MySQL は辞めました。まぁ、MySQLがそんなに性能が凄い良いとも思っていなかったのを裏付けした格好になります。

 次に、pgpool-2 を使って、接続イニシャルを減らす方法を試してみました。しかし、pgpool-2 だと、通常接続の 1.2倍のペナルティを受けてしまいました。十分にプール数を確保しても、そうだったので、今時のPostgreSQLは、相当に速いんだなぁと実感できました。

 システム構成上、今のところスケール・アウトができないので、今度は memcached を使って PostgreSQL の負荷を低減させる方策を思いつきました。冒頭に示した要件があるので、キーを [移動体番号]-[日付+時刻] にして、5分間隔に軌跡の点を保存して、そこから引くようにしてみました。ところが、実装して試してみると遅い。はい、冷静に考えると5分刻みデータなので24時間だと12*24= 288回のリクエストを発行する計算になります。これが移動体1台分。今度は socket の往復分のコストが馬鹿にならず、性能が 1/2 に落ちました。これを裏付けるべく、15分間隔にして試してみたところ、性能が 1.5 倍になりました。という訳で、memcached も使いよう。今回のケースでは威力を発揮できない感じです。

 結局、結論としては、いつか NoSQL でやらないと、この部分は破綻すると提言していたように、Redis に置き換えてやってみるよりない感じになりました。

 5分間隔でPostgreSQLのテーブルにポリラインを登録しておいて、そこから引くという構成も考えられます。しかし、更新負荷等のバランスから考えて、NoSQL に置き換えるのが王道かな?と考えている次第であります。


本日のバグ lambda

本日のバグ。今回は、boost::shared_ptr と boost::weak_ptr にまつわる話です。
集合セット S に foo クラスが入っており、集合セット S は生成と破棄を行います。
集合セット S に含まれる foo は、それぞれ異なりますが、重複する場合があります。
foo を shared_ptr でラップして、集合セットに保持し、全体としての foo のカタログを weak_ptr で持たそうかなぁ?とも思いましたが、カタログにアクセスする度に weak_ptr::lock を呼び出すのも非効率的です。何よりも、foo オブジェクトを探したいのに死んでいたら foo オブジェクトの値を取り出せないので、lower_bound とかで検索できないのも痛いです。
という事で、shared_ptr::use_count を調べて、カタログ以外に所有者がいなければ、消せばええやん!という風にしましたが、うまく行きませんでした。以下のコードです。


#include <iostream>
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/range/algorithm_ext/erase.hpp>

struct foo {
};

typedef boost::shared_ptr<foo> foo_t;

int main()
{
std::vector<foo_t> v;
for( int i = 0; i < 10; ++i ) v.push_back( foo_t( new foo ) );
std::cout << "=== run remove_erase_if" << std::endl;
boost::remove_erase_if( v,
[](foo_t val) -> bool {
std::cout << val.use_count() << std::endl;
return val.use_count() <= 1;
}
);
std::cout << "erased -> " << v.size() << std::endl;

return 0;
}

はい、正解は、


[](foo_t& val) -> bool {

参照でアクセスしないと、カウント増えますよねwwwwwって事でした。


CentOS に libmemcached をインストール

 rpmforge から入れろとか、情報がありますが、libmemcache-devel までは入るんですが、肝心の libmemcached が影も形も無い。ほぇー。ま、こんな時は、ソースからコンパイルやね。


$ wget https://launchpad.net/libmemcached/1.0/1.0.16/+download/libmemcached-1.0.16.tar.gz
$ sudo mv libmemcached-1.0.16.tar.gz /usr/local/src
$ su
# tar xvf libmemcached-1.0.16.tar.gz
# cd libmemcached-1.0.16
# ./configure --prefix=/usr
# make

はい、tr1/cstdint が無いと怒られます。モンキーパッチで対応です


# vi libmemcached-1.0/memcached.h

こんな感じに修正


#ifdef __cplusplus
//# include <tr1/cinttypes>
# include <inttypes.h>
#ifndef INT64_C
#define INT64_C(c) (c ## LL)
#define UINT64_C(c) (c ## UL)
#endif
# include <cstddef>
# include <cstdlib>
#else
# include <inttypes.h>
# include <stddef.h>
# include <stdlib.h>
# include <stdbool.h>
#endif

気をとりなおして


# make
# make test
# make install

boost::dynamic_bitset で byte配列にコピー

 せっかくサンプルを作ったので…


#include <boost/dynamic_bitset.hpp>
#include <boost/format.hpp>
#include <iostream>

int main() {
typedef boost::dynamic_bitset<unsigned char> ubits;

ubits bitset(16); // 16 bits

for( int i = 0; i < 16; ++i ) {
bitset[i] = i % 2;
}

char buf[2];

boost::to_block_range(bitset, buf);

std::cout << (boost::format("%x %x") % (int)buf[0] % (int)buf[1]).str() << std::endl;

return 0;

}

実行結果


ffffffaa ffffffaa

雪あかりの路2013

 今年も行って来ました。小樽・雪あかりの路。実は Google+ をやっている影響で、だんだんとカメラに毒されてきまして、ミラーレス一眼レフ NEX-5R を買いました。iPad のカメラも十分に綺麗なんですが、やっぱ、カメラが違うと、面白いです。まだまだ、使い方がわからなくて、お任せモードで撮ってます。

 この写真なんかは、手振れ補正夜景モードというので撮ってます。本当は通路に人が居たはずなんですが、5枚ぐらい連続でバシャバシャバシャバシャバシャと撮影して合成されると、人が消えてました( ゚д゚)
 例年だと、あっ!この場所のこの構図が良い!とか、ビビっ!と閃くんですけど、カメラ入手して気負っていたせいか、ちーっともビビっ!と来ませんでしたw。なので、よし!三脚で気合入れて撮影するぞーと、三脚まで買って持って行ったのに、1回も使いませんでした。
 あ!鴨がいっぱいおる!と思って iPad で写しても、なんだかよくわからないですけど、一眼レフだと、ちゃんと写ってるあたりは、さすがだと思います。

運河も綺麗ですね