odz buffer

2016-05-30

[]Oracle vs Googleのやつ

単純に疑問に思ったことなど。

Androidの非互換性

従来Javaと非互換な実装で、従来Javaのエコシステムが破壊されてんの?私が知らないだけで、今時のJavaライブラリは#ifdefみたいに、VM実装確認してスイッチしたりしてるんだろうか。

Javaと非互換の癖にJava名乗るなみたいな話であれば、それはそれでわかる。

トップレベルパッケージ

Android はまず、名前衝突を避けるために定められたパッケージ名の naming convention を完全に無視し、勝手に android というトップレベル・パッケージ名を宣言しました。

Android以外にもパッケージにドメイン名を入れない例は多い。ぱっと思いつく例だと、Groovyとか、Wekaとか、OpenNLPとか。

OSSなので、組織名入れたくないみたいな、事情はあるかもしれない。だったら、org.androidでいいんじゃね、という気もしますが。

OSSとして

OpenJDKをGPLでリリースしておいて、その一部であるAPIを無断使用として訴えるというのはどゆことだろ。まぁ、AndroidはOpenJDKではなく、Apache Harmonyの派生なので、そんな単純でもないが、Apache Harmonyを放置しておいて、Apache Harmony派生のAndroidだけ訴えるというのは、それこそ道義的にどうなんだ、という気はする。

仮にOpenJDKの派生として作られたら、GPLに従っている限りは文句を言われる筋合いはないはずだよね。

その他

AndroidのString.indexOf が壊れている件はソースを見る限り、Apache Harmonyから引き継いだバグっぽいですね。

参考

2016-02-15

git の sha1_to_hex のやつ

すこし調べた。

Linus が普通に Mailing List で明言していた。

Nothing magical, it's just "rounded up from 40 + NUL character".

[PATCH] hex.c: reduce memory footprint of sha1_to_hex static buffers

単に、40バイト+NUL文字用の1バイトで切り上げて50バイトらしい。

が、masterのやつを見たら全然違うので、もう少し歴史を見てみる。

最初のは read-cache.c にあった。initial commitですね。

char * sha1_to_hex(unsigned char *sha1)
{
	static char buffer[50];
	static const char hex[] = "0123456789abcdef";
	char *buf = buffer;
	int i;

	for (i = 0; i < 20; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	return buffer;
}
read-cache.c

sha1_file.cに移動されたあと、ちゃんと毎回 NUL terminate されるようになる。commitは@1e80e0

char * sha1_to_hex(const unsigned char *sha1)
{
	static char buffer[50];
	static const char hex[] = "0123456789abcdef";
	char *buf = buffer;
	int i;

	for (i = 0; i < 20; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	*buf = '\0';

	return buffer;
}
sha1_file.c

static 領域のアドレスを返すためにエラーメッセージ作るのが面倒だとかそんな感じの文句が出たのか、簡易LRUキャッシュが導入される。commitは@dcb345

char * sha1_to_hex(const unsigned char *sha1)
{
	static int bufno;
	static char hexbuffer[4][50];
	static const char hex[] = "0123456789abcdef";
	char *buffer = hexbuffer[3 & ++bufno], *buf = buffer;
	int i;

	for (i = 0; i < 20; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	*buf = '\0';

	return buffer;
}
sha1_file.c

さらに hex.c に移動して、マジックナンバーマクロで置き換え、バッファサイズも変更。commit は @aa1c6f

char *sha1_to_hex(const unsigned char *sha1)
{
	static int bufno;
	static char hexbuffer[4][GIT_SHA1_HEXSZ + 1];
	static const char hex[] = "0123456789abcdef";
	char *buffer = hexbuffer[3 & ++bufno], *buf = buffer;
	int i;

	for (i = 0; i < GIT_SHA1_RAWSZ; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	*buf = '\0';

	return buffer;
}
hex.c
#define GIT_SHA1_RAWSZ 20
#define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)
cache.h

で、reentrant版の sha1_to_hex_r と非reentrant版のsha1_to_hexに分離して、だいたい今の形になっている。commitは@af49c6

char *sha1_to_hex_r(char *buffer, const unsigned char *sha1)
{
	static const char hex[] = "0123456789abcdef";
	char *buf = buffer;
	int i;

	for (i = 0; i < GIT_SHA1_RAWSZ; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	*buf = '\0';

	return buffer;
}

char *sha1_to_hex(const unsigned char *sha1)
{
	static int bufno;
	static char hexbuffer[4][GIT_SHA1_HEXSZ + 1];
	return sha1_to_hex_r(hexbuffer[3 & ++bufno], sha1);
}
hex.c

こんな小さな関数でも結構変わっているもんですな。

2016-02-11

近況

唐突にしばらく都内勤務になった。とりあえず、3月までの期限付きの予定。

s/20/40/

どうみても、40バイト書いていると思う。

2016-02-07

データがずれている

ブコメにも書いたけど国立大学の授業料のデータが5年ずれているっぽい。昭和50年1975年ですからね。

というだけなのもなんなので、ちゃんとデータをまとめてみた。

1975年比でいうと、物価で補正すると8.26倍、給与で補正すると5.92倍になっとると。

注意点

  • 授業料のデータは文科省のページから
  • 物価政府統計から「持家の家賃帰属を除く総合」
  • 給与は厚労省のページの所定内給与を使った
  • 1975年の所定内給与のデータがないようなので、1976年、1977年のデータから線形補間
  • 2006年以降の授業料のデータがなかったが、変わっていないようなので、2005年のデータのままとした
  • 一部手打ちしているので、間違っているかも

2015-06-09

[]Emacs Lispでvariance

Lispらしく書くならこんな感じ?

(defun varp-1 (xs)
  (cl-labels ((varp-sub (xs s1 s2 len)
			(if (consp xs)
			    (let ((x (car xs)))
			      (varp-sub
			       (cdr xs)
			       (+ s1 (* x x))
			       (+ s2 x)
			       (1+ len)))
			  (let ((e1 (/ s1 (float len)))
				(e2 (/ s2 (float len))))
			    (- e1 (* e2 e2))))))
    (varp-sub xs 0 0 0)))

慣れないと読みづらいな。Python で書きなおすと、こう。

def varp_1(xs):
    def varp_sub(xs, s1, s2, length):
        if xs:
            x = xs[0]
            return varp_sub(xs[1:], s1 + x * x, s2 + x, length + 1)
        else:
            e1 = s1 / float(length)
            e2 = s2 / float(length)
            return e1 - e2 * e2

    return varp_sub(xs, 0, 0, 0)

Emacs LispはTail Call Optimization効かないのでdolistマクロのが一般的かも。

(defun varp-2 (xs)
  (let ((s1 0)
	(s2 0)
	(len 0))
    (progn
      (dolist (x xs)
	(progn
	  (setq s1 (+ s1 (* x x)))
	  (setq s2 (+ s2 x))
	  (setq len (1+ len))))
      (let ((e1 (/ s1 (float len)))
	    (e2 (/ s2 (float len))))
	(- e1 (* e2 e2))))))
(benchmark-run 100 (varp-1 large-list))
(0.009979 0 0.0)

(benchmark-run 100 (varp-2 large-list))
(0.00844 0 0.0)

dolistを使ったほうが少し早い。