2007年10月5日金曜日

matlab: なんちゃって構造体

空の構造体は

>> a = struct([])
a =
0x0 struct array with no fields.

とすれば簡単に作れる.では,「フィールドを持たないけど空ではない構造体」はどうすれば作れるか?

すぐに思いつくのは,rmfield を使って,フィールドを消して行くやり方だろう.

>> b.foo = []; a = rmfield(b, 'foo')
a =
1x1 struct array with no fields.

これはかっこ悪いので却下.だが実現は出来ることがわかる.
では,rmfield はどうやってこれを実現しているか?
rmfield は実は組み込み関数でなく .m 関数なので,type rmfield して中身をのぞくと,どうやら cell2struct を呼び出しているらしい.
ならばはじめから cell2struct を使えばいいのである.しかも cell2struct は組み込み関数だから,わりと根源的なやり方といえるだろう.

>> a = cell2struct(cell(0,1),{})
a =
1x1 struct array with no fields.

おお,できた.これでいいや.

しかし,恒例の whos でみると

>> whos a
  Name      Size                    Bytes  Class
  a         1x1                         0  struct array
Grand total is 0 elements using 0 bytes

のように,メモリが割り当てられていないではないか.しかも a の repmat で b を作ってみても,b も Bytes は 0 のままである.

実際にメモリを割り当てるにはフィールドを定義しないといけないらしい.AMD64 な Linux 上で AMD64 な MatlabR2006a を使った場合,

>> b = repmat(a,[100,1]);
>> whos b
  Name      Size                    Bytes  Class
  b       100x1                         0  struct array
Grand total is 0 elements using 0 bytes
>> b(1).foo = '';
>> whos b
  Name      Size                    Bytes  Class
  b       100x1                       952  struct array
Grand total is 100 elements using 952 bytes

となるが,同じことを IA32 な Windows 上で IA32 な Matlab6.5.1 を使って行った場合,

>> b=repmat(a,[100,1]);
>> whos b
  Name      Size                   Bytes  Class
  b       100x1                        0  struct array
Grand total is 0 elements using 0 bytes
>> b(1).foo = '';
>> whos b
  Name      Size                   Bytes  Class
  b       100x1                      520  struct array
Grand total is 100 elements using 520 bytes

となる.なんで違うんでしょう.