narray_miss 1.2.1.1 → 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1510 @@
1
+ # -*- coding: utf-8 -*-
2
+ =begin
3
+ = NArrayMiss Class
4
+
5
+ NArrayMiss is a additional class processing of missing value with to
6
+ ((<NArray|URL:http://www.ruby-lang.org/en/raa-list.rhtml?name=NArray>))
7
+ for Ruby.
8
+
9
+ To use NArrayMiss class, you need invoking "require 'narray_miss.rb'" in your script.
10
+
11
+ == Index
12
+
13
+ * ((<Class Constants>))
14
+ * ((<Class Methods>))
15
+ * ((<Class Instance Methods>))
16
+ * ((<NArrayMiss information>))
17
+ * ((<Slicing Array>))
18
+ * ((<Filling values>))
19
+ * ((<Arithmetic operator>))
20
+ * ((<Bitwise operator|Bitwise operator (only for byte, sint and int)>))
21
+ * ((<Comparison>))
22
+ * ((<Statistics>))
23
+ * ((<Sort>))
24
+ * ((<Transpose>))
25
+ * ((<Changing Shapes of indices>))
26
+ * ((<Type conversion>))
27
+ * ((<Iteration>))
28
+ * ((<Boolean and mask related|Boolean and mask related (only for byte, sint and int)>))
29
+ * ((<Complex compound number|Complex compound number (only for scomplex and complex)>))
30
+ * ((<Byte swap>))
31
+ * ((<Mask and missing value>))
32
+ * ((<Others>))
33
+
34
+
35
+ =end
36
+
37
+ require 'narray'
38
+
39
+
40
+ class NArrayMiss
41
+
42
+ =begin
43
+ == Class Constants
44
+ --- NArrayMiss::BYTE
45
+ type code for 1 byte unsigned integer.
46
+ --- NArrayMiss::SINT
47
+ type code for 2 byte signed integer.
48
+ --- NArrayMiss::INT
49
+ type code for 4 byte signed integer.
50
+ --- NArrayMiss::SFLOAT
51
+ type code for single precision float.
52
+ --- NArrayMiss::FLOAT
53
+ type code for double precision float.
54
+ --- NArrayMiss::SCOMPLEX
55
+ type code for single precision complex.
56
+ --- NArrayMiss::COMPLEX
57
+ type code for double precision complex.
58
+ --- NArrayMiss::OBJECT
59
+ type code for Ruby object.
60
+
61
+ go back to ((<Index>))
62
+ =end
63
+
64
+ BYTE = NArray::BYTE
65
+ SINT = NArray::SINT
66
+ INT = NArray::INT
67
+ SFLOAT = NArray::SFLOAT
68
+ FLOAT = NArray::FLOAT
69
+ SCOMPLEX = NArray::SCOMPLEX
70
+ COMPLEX = NArray::COMPLEX
71
+ OBJECT = NArray::OBJECT
72
+
73
+ class << self
74
+ alias :__new__ :new
75
+ private :__new__
76
+ end
77
+
78
+ def initialize(array, mask)
79
+ if array.shape!=mask.shape
80
+ raise "array and mask must have the same shape"
81
+ end
82
+ @array = array
83
+ @mask = mask
84
+ end
85
+ private :initialize
86
+
87
+ =begin
88
+ == Class Methods
89
+ --- NArrayMiss.new(typecode, size, ...)
90
+ create (({NArrayMiss})) of ((|typecode|)).
91
+ All elements are initialized with 0.
92
+ --- NArrayMiss.byte(size, ...)
93
+ same as NArrayMiss.new(NArrayMiss::BYTE, ((|size|)), ...).
94
+ --- NArrayMiss.sint(size, ...)
95
+ same as NArrayMiss.new(NArrayMiss::SINT, ((|size|)), ...).
96
+ --- NArrayMiss.int(size, ...)
97
+ same as NArrayMiss.new(NArrayMiss::INT, ((|size|)), ...).
98
+ --- NArrayMiss.sfloat(size, ...)
99
+ same as NArrayMiss.new(NArrayMiss::SFLOAT, ((|size|)), ...).
100
+ --- NArrayMiss.float(size, ...)
101
+ same as NArrayMiss.new(NArrayMiss::FLOAT, ((|size|)), ...).
102
+ --- NArrayMiss.scomplex(size, ...)
103
+ same as NArrayMiss.new(NArrayMiss::SCOMPLEX, ((|size|)), ...).
104
+ --- NArrayMiss.complex(size, ...)
105
+ same as NArrayMiss.new(NArrayMiss::COMPLEX, ((|size|)), ...).
106
+ --- NArrayMiss.object(size, ...)
107
+ same as NArrayMiss.new(NArrayMiss::OBJECT, ((|size|)), ...).
108
+ --- NArrayMiss[](value, ...)
109
+ create (({NArrayMiss})) form [((|value|)), ...].
110
+ --- NArrayMiss.to_nam(array [,mask])
111
+ create (({NArrayMiss})) from ((|array|)).
112
+ ((|array|)) must be (({Numeric})) (({Array})) or (({NArray})).
113
+ --- NArrayMiss.to_nam_no_dup(array [,mask])
114
+ convert from ((|array|)) to (({NArrayMiss})).
115
+
116
+ go back to ((<Index>))
117
+ =end
118
+
119
+ def self.new(*arg)
120
+ array = NArray.new(*arg)
121
+ mask = NArray.byte(*arg[1..-1])
122
+ __new__(array, mask)
123
+ end
124
+ def self.byte(*arg)
125
+ NArrayMiss.new(BYTE,*arg)
126
+ end
127
+ def self.sint(*arg)
128
+ NArrayMiss.new(SINT,*arg)
129
+ end
130
+ def self.int(*arg)
131
+ NArrayMiss.new(INT,*arg)
132
+ end
133
+ def self.sfloat(*arg)
134
+ NArrayMiss.new(SFLOAT,*arg)
135
+ end
136
+ def self.float(*arg)
137
+ NArrayMiss.new(FLOAT,*arg)
138
+ end
139
+ def self.scomplex(*arg)
140
+ NArrayMiss.new(SCOMPLEX,*arg)
141
+ end
142
+ def self.complex(*arg)
143
+ NArrayMiss.new(COMPLEX,*arg)
144
+ end
145
+ def self.object(*arg)
146
+ NArrayMiss.new(OBJECT,*arg)
147
+ end
148
+ def self.[](*arg)
149
+ NArrayMiss.to_nam(NArray[*arg])
150
+ end
151
+ def self.to_nam_no_dup(*arg)
152
+ if arg.length > 2 || arg.length==0 then
153
+ raise("NArrayMiss.to_nar( array [,mask]] )")
154
+ end
155
+
156
+ array = arg[0]
157
+ if Numeric===array then array = NArray[array] end
158
+ if Array===array then array = NArray.to_na(array) end
159
+ if !array.is_a?(NArray) then
160
+ raise("argument must be Numeric, NArray or Array")
161
+ end
162
+
163
+ if arg.length==2 then
164
+ mask = arg[1]
165
+ if Numeric===mask then mask = array.ne(mask) end
166
+ if Array===mask then
167
+ mask = NArray.to_na(mask).ne(0)
168
+ end
169
+ if mask.class == FalseClass then
170
+ mask = NArray.byte(*array.shape)
171
+ end
172
+ if mask.class == TrueClass then
173
+ mask = NArray.byte(*array.shape).fill(1)
174
+ end
175
+ if !(NArray===mask && mask.typecode==BYTE) then
176
+ raise("mask must be Numeric, Array, true, false or NArray(byte)")
177
+ end
178
+ if mask.length!=array.length
179
+ raise "mask.length must be same as array.length"
180
+ end
181
+ else
182
+ mask = NArray.byte(*array.shape).fill(1)
183
+ end
184
+ __new__(array,mask)
185
+ end
186
+ def self.to_nam(*arg)
187
+ if !(Numeric===arg[0]) && !(Array===arg[0]) && !arg[0].is_a?(NArray)
188
+ raise "first argument must be Numeric, NArray or Array"
189
+ end
190
+ arg[0] = arg[0].dup if !(Numeric===arg[0])
191
+ if arg.length==2 && !(Numeric===arg[1]) && arg[1].class!=TrueClass && arg[1].class!=FalseClass then
192
+ arg[1] = arg[1].dup
193
+ end
194
+ NArrayMiss.to_nam_no_dup(*arg)
195
+ end
196
+
197
+
198
+ =begin
199
+ == Class Instance Methods
200
+ =end
201
+
202
+
203
+ =begin
204
+ === NArrayMiss information
205
+ --- NArrayMiss#dim
206
+ return the dimension which is the number of indices.
207
+ --- NArrayMiss#rank
208
+ same as (({NArrayMiss#dim})).
209
+ --- NArrayMiss#shape
210
+ return the (({Array})) of sizes of each index.
211
+ --- NArrayMiss#size
212
+ return the number of total elements.
213
+ --- NArrayMiss#total
214
+ alias to size
215
+ --- NArrayMiss#length
216
+ alias to size
217
+ --- NArrayMiss#rank_total
218
+ return the number of total of the shape.
219
+ --- NArrayMiss#typecode
220
+ return the typecode.
221
+ =end
222
+
223
+ def dim
224
+ @array.dim
225
+ end
226
+ def rank
227
+ @array.rank
228
+ end
229
+ def shape
230
+ @array.shape
231
+ end
232
+ def size
233
+ @array.size
234
+ end
235
+ alias :total :size
236
+ alias :length :size
237
+
238
+ def rank_total(*arg)
239
+ @array.rank_total(*arg)
240
+ end
241
+
242
+ def typecode
243
+ @array.typecode
244
+ end
245
+
246
+
247
+ =begin
248
+ === Slicing Array
249
+ --- NArrayMiss#[](index)
250
+ return the value at [((|index|))].
251
+ ((|index|)) must be (({Integer, Range, Array, true})).
252
+ Index order is FORTRAN type.
253
+ --- NArrayMiss#slice(index)
254
+ same as (({NArrayMiss#[]})) but keeps the rank of original array by not elimiting dimensions whose length became equal to 1 (which (({NArrayMiss#[]})) dose).
255
+ This is not the case with the 1-dimensional indexing and masking.
256
+ --- NArrayMiss#set_without_validation(index,value)
257
+ replace elements at ((|index|)) by ((|value|)).
258
+ --- NArrayMiss#[]=(index, value)
259
+ replace elements at ((|index|)) by ((|value|)) and
260
+ make replaced elements valid.
261
+ =end
262
+
263
+ def [](*arg)
264
+ if arg[0].class == NArrayMiss && arg[0].typecode == BYTE
265
+ obj = @array[arg[0].to_na(0)]
266
+ if Numeric===obj
267
+ return obj
268
+ else
269
+ return NArrayMiss.to_nam_no_dup(obj)
270
+ end
271
+ else
272
+ obj = @array[*arg]
273
+ if Numeric===obj
274
+ return obj
275
+ else
276
+ return NArrayMiss.to_nam_no_dup(obj,@mask[*arg])
277
+ end
278
+ end
279
+ end
280
+ def slice(*arg)
281
+ NArrayMiss.to_nam_no_dup(@array.slice(*arg),@mask.slice(*arg))
282
+ end
283
+
284
+ def set_without_validation(*arg)
285
+ if arg.length==1 then
286
+ if !arg[0] then
287
+ @mask[] = 0
288
+ elsif arg[0].class == NArrayMiss then
289
+ @array[] = arg[0].get_array!
290
+ @mask[] = arg[0].get_mask!
291
+ else
292
+ @array[] = arg[0]
293
+ end
294
+ else
295
+ if !arg[-1] then
296
+ @mask[*arg[0..-2]] = 0
297
+ elsif arg[-1].class == NArrayMiss then
298
+ @array[*arg[0..-2]] = arg[-1].get_array!
299
+ @mask[*arg[0..-2]] = arg[-1].get_mask!
300
+ else
301
+ @array[*arg[0..-2]] = arg[-1]
302
+ end
303
+ end
304
+ return self
305
+ end
306
+
307
+ def []=(*arg)
308
+ if arg.length == 2 && arg[0].class == NArrayMiss && arg[0].typecode == BYTE
309
+ idx = arg[0].to_na(0)
310
+ self.set_without_validation(idx,arg[-1])
311
+ if arg[-1].class != NArrayMiss && arg[-1] then
312
+ @mask[idx] = 1
313
+ end
314
+ else
315
+ self.set_without_validation(*arg)
316
+ if arg[-1].class != NArrayMiss && arg[-1] then
317
+ if arg.length==1 then
318
+ @mask=1
319
+ else
320
+ @mask[*arg[0..-2]] = 1
321
+ end
322
+ end
323
+ end
324
+ return self
325
+ end
326
+
327
+
328
+ =begin
329
+ === Filling values
330
+ --- NArrayMiss#indgen!([start[,step]])
331
+ set values from ((|start|)) with ((|step|)) increment.
332
+ --- NArrayMiss#indgen([start[,step]])
333
+ same as (({NArrayMiss#indgen!})) but create new object.
334
+ --- NArrayMiss#fill!(value)
335
+ fill elements with ((|value|)).
336
+ --- NArrayMiss#fill(value)
337
+ same as (({NArrayMiss#fill!})) but create new object.
338
+ --- NArrayMiss#random!(max)
339
+ set random values between 0<=x<((|max|)).
340
+ --- NArrayMiss#random(max)
341
+ same as (({NArrayMiss#random!})) but create new object.
342
+ --- NArrayMiss#randomn(max)
343
+ set normally distributed random values with mean=0, dispersion=1 (Box-Muller)
344
+ =end
345
+
346
+ for operator in ["indgen","fill","random","randomn"]
347
+ eval(<<-EOL,nil,__FILE__,__LINE__+1)
348
+ def #{operator}(*arg)
349
+ obj = self.dup
350
+ obj.#{operator}!(*arg)
351
+ obj
352
+ end
353
+ def #{operator}!(*arg)
354
+ @array = @array.#{operator}!(*arg)
355
+ @mask[true] = 1
356
+ self
357
+ end
358
+ EOL
359
+ end
360
+
361
+
362
+ =begin
363
+ === Arithmetic operator
364
+ --- NArrayMiss#-@
365
+ --- NArrayMiss#+(other)
366
+ --- NArrayMiss#-(other)
367
+ --- NArrayMiss#*(other)
368
+ --- NArrayMiss#/(other)
369
+ --- NArrayMiss#%(other)
370
+ --- NArrayMiss#**(other)
371
+ --- NArrayMiss#abs
372
+ --- NArrayMiss#add!(other)
373
+ --- NArrayMiss#sbt!(other)
374
+ --- NArrayMiss#mul!(other)
375
+ --- NArrayMiss#div!(other)
376
+ --- NArrayMiss#mod!(other)
377
+ --- NArrayMiss#mul_add(other, dim, ...)
378
+ =end
379
+
380
+ def -@
381
+ array = @array.dup
382
+ array[@mask] = -@array[@mask]
383
+ NArrayMiss.to_nam_no_dup(array, @mask.dup)
384
+ end
385
+ def +(arg)
386
+ binary_operation(arg, 0){|t1, t2| t1 + t2}
387
+ end
388
+ def -(arg)
389
+ binary_operation(arg, 0){|t1, t2| t1 - t2}
390
+ end
391
+ def *(arg)
392
+ binary_operation(arg, 1){|t1, t2| t1 * t2}
393
+ end
394
+ def /(arg)
395
+ binary_operation(arg, 1){|t1, t2| t1 / t2}
396
+ end
397
+ def %(arg)
398
+ binary_operation(arg, 1){|t1, t2| t1 % t2}
399
+ end
400
+ def **(arg)
401
+ binary_operation(arg, 1){|t1, t2| t1 ** t2}
402
+ end
403
+
404
+ def abs
405
+ array = @array.dup
406
+ array[@mask] = @array[@mask].abs
407
+ NArrayMiss.to_nam_no_dup(array, @mask.dup)
408
+ end
409
+
410
+ def add!(arg)
411
+ binary_operation(arg, 0){|t1, t2| t1.add!(t2)}
412
+ end
413
+ def sbt!(arg)
414
+ binary_operation(arg, 0){|t1, t2| t1.sbt!(t2)}
415
+ end
416
+ def mul!(arg)
417
+ binary_operation(arg, 1){|t1, t2| t1.mul!(t2)}
418
+ end
419
+ def div!(arg)
420
+ binary_operation(arg, 1){|t1, t2| t1.div!(t2)}
421
+ end
422
+ def mod!(arg)
423
+ binary_operation(arg, 1){|t1, t2| t1.mod!(t2)}
424
+ end
425
+
426
+ def mul_add(*arg)
427
+ if arg.length==1 then
428
+ return (self*arg[0]).sum
429
+ else
430
+ return (self*arg[0]).sum(*arg[1..-1])
431
+ end
432
+ end
433
+
434
+
435
+ =begin
436
+ === Bitwise operator (only for byte, sint and int)
437
+ --- NArrayMiss#~@
438
+ --- NArrayMiss#&(other)
439
+ --- NArrayMiss#|(other)
440
+ --- NArrayMiss#^(other)
441
+ =end
442
+
443
+ def ~@
444
+ NArrayMiss.to_nam_to_dup(~@array, @mask.dup)
445
+ end
446
+ def &(arg)
447
+ binary_operation(arg, 1){|t1, t2| t1 & t2}
448
+ end
449
+ def |(arg)
450
+ binary_operation(arg, 0){|t1, t2| t1 | t2}
451
+ end
452
+ def ^(arg)
453
+ binary_operation(arg, 1){|t1, t2| t1 ^ t2}
454
+ end
455
+
456
+
457
+ =begin
458
+ === Comparison
459
+ --- NArrayMiss#eq(other)
460
+ --- NArrayMiss#ne(other)
461
+ --- NArrayMiss#gt(other)
462
+ --- NArrayMiss#ge(other)
463
+ --- NArrayMiss#lt(other)
464
+ --- NArrayMiss#le(other)
465
+ --- NArrayMiss#>(other)
466
+ --- NArrayMiss#>=(other)
467
+ --- NArrayMiss#<(other)
468
+ --- NArrayMiss#<=(other)
469
+ --- NArrayMiss#and(other)
470
+ --- NArrayMiss#or(other)
471
+ --- NArrayMiss#xor(other)
472
+ --- NArrayMiss#not(other)
473
+ =end
474
+
475
+ def eq(arg)
476
+ binary_operation(arg, 0){|t1, t2| t1.eq t2}
477
+ end
478
+ def ne(arg)
479
+ binary_operation(arg, 0){|t1, t2| t1.ne t2}
480
+ end
481
+ def gt(arg)
482
+ binary_operation(arg, 0){|t1, t2| t1.gt t2}
483
+ end
484
+ def ge(arg)
485
+ binary_operation(arg, 0){|t1, t2| t1.ge t2}
486
+ end
487
+ def lt(arg)
488
+ binary_operation(arg, 0){|t1, t2| t1.lt t2}
489
+ end
490
+ def le(arg)
491
+ binary_operation(arg, 0){|t1, t2| t1.le t2}
492
+ end
493
+
494
+ def and(arg)
495
+ binary_operation(arg, 1){|t1, t2| t1.and t2}
496
+ end
497
+ def or(arg)
498
+ binary_operation(arg, 0){|t1, t2| t1.or t2}
499
+ end
500
+ def xor(arg)
501
+ binary_operation(arg, 1){|t1, t2| t1.xor t2}
502
+ end
503
+
504
+ def not
505
+ NArrayMiss.to_nam_no_dup(@array.not, @mask.dup)
506
+ end
507
+
508
+ def ==(arg)
509
+ if arg.kind_of?(NArrayMiss) then
510
+ @mask==arg.get_mask! && @array[@mask]==arg.get_array![@mask]
511
+ else
512
+ false
513
+ end
514
+ end
515
+
516
+
517
+ =begin
518
+ === Statistics
519
+ --- NArrayMiss#sum(dim, ... ["min_count"=>i])
520
+ return summation of elements in specified dimensions.
521
+ Elements at which the number of elements for summation is less than ((|i|)) is invalid.
522
+ --- NArrayMiss#accum(dim, ...)
523
+ same as (({NArrayMiss#sum})) but not elimiting dimensions whose length became equal to 1.
524
+ --- NArrayMiss#min(dim, ...)
525
+ return minimum in specified dimensions.
526
+ Elements at which the number of valid elements in the dimension is less than ((|i|)) is invalid.
527
+ --- NArrayMiss#max(dim, ...)
528
+ return maximum in specified dimensions.
529
+ Elements at which the number of valid elements in the dimension is less than ((|i|)) is invalid.
530
+ --- NArrayMiss#median(dim, ...)
531
+ return median in specified dimensions.
532
+ Elements at which the number of valid elements in the dimension is less than ((|i|)) is invalid.
533
+ --- NArrayMiss#mean(dim, ...)
534
+ return mean of elements in specified dimensions.
535
+ Elements at which the number of elements for then mean is less than ((|i|)) is invalid.
536
+ --- NArrayMiss#stddev(dim, ...)
537
+ return standard deviation of elements in specified dimensions.
538
+ Elements at which the number of elements for calculation the standard deviation is less than ((|i|)) is invalid.
539
+ --- NArrayMiss#rms(dim, ...)
540
+ return root mean square of elements in specified dimensions.
541
+ Elements at which the number of elements for calculation the RMS is less than ((|i|)) is invalid.
542
+ --- NArrayMiss#rmsdev(dim, ...)
543
+ return root mean square deviation of elements in specified dimensions.
544
+ Elements at which the number of elements for calculation the RMS deviation is less than ((|i|)) is invalid.
545
+ =end
546
+
547
+ def accum(*arg)
548
+ if @mask.count_true == 0 then
549
+ return nil
550
+ else
551
+ array = @array.dup
552
+ array[@mask.not] = 0
553
+ return NArrayMiss.to_nam_no_dup(array.accum(*arg),
554
+ @mask.to_type(NArray::INT).accum(*arg).ne(0))
555
+ end
556
+ end
557
+
558
+ def sum(*dims)
559
+ min_count = NArrayMiss.check_options(dims, 1)
560
+ # 欠損値に 0 を入れて普通に sum する
561
+ ary0 = @array.dup
562
+ ary0[@mask.not] = 0
563
+ NArrayMiss.reduction(@mask, min_count, dims, false, typecode) do
564
+ ary0.sum(*dims)
565
+ end
566
+ end
567
+ def min(*dims)
568
+ min_count = NArrayMiss.check_options(dims, 1)
569
+ # 欠損値に最大値を入れて普通に min する
570
+ # byte,sint,int,sfloat,float の MAX の値を入れるように変更すべき
571
+ ary0 = @array.dup
572
+ ary0[@mask.not] = @array.max
573
+ NArrayMiss.reduction(@mask, min_count, dims, false, typecode) do
574
+ ary0.min(*dims)
575
+ end
576
+ end
577
+ def max(*dims)
578
+ min_count = NArrayMiss.check_options(dims, 1)
579
+ # 欠損値に最小値を入れて普通に max する
580
+ # byte,sint,int,sfloat,float の MIN の値を入れるように変更すべき
581
+ ary0 = @array.dup
582
+ ary0[@mask.not] = @array.min
583
+ NArrayMiss.reduction(@mask, min_count, dims, false, typecode) do
584
+ ary0.max(*dims)
585
+ end
586
+ end
587
+
588
+ def mean(*dims)
589
+ min_count = NArrayMiss.check_options(dims, 1)
590
+ # 整数型の場合は浮動小数型へ変換
591
+ ary0 = self.integer? ? self.to_type(NArray::DFLOAT) : self
592
+ NArrayMiss.reduction(@mask, min_count, dims, true, typecode) do |count_sum, count_accum|
593
+ var = ary0.sum(*dims)/count_sum
594
+ end
595
+ end
596
+ def stddev(*dims)
597
+ min_count = NArrayMiss.check_options(dims, 2)
598
+ # 整数型の場合は浮動小数型へ変換
599
+ ary0 = self.integer? ? self.to_type(NArray::DFLOAT) : self
600
+ NArrayMiss.reduction(@mask, min_count, dims, true, typecode) do |count_sum, count_accum|
601
+ ary0 = ary0 - ary0.accum(*dims)/count_accum
602
+ ary0 = ary0.abs if ary0.complex?
603
+ ary0 = (ary0**2).sum(*dims) / (count_sum-1)
604
+ NMMath.sqrt(ary0)
605
+ end
606
+ end
607
+ def rms(*dims)
608
+ min_count = NArrayMiss.check_options(dims, 1)
609
+ # 整数型の場合は浮動小数型へ変換
610
+ ary0 = self.integer? ? self.to_type(NArray::DFLOAT) : self
611
+ NArrayMiss.reduction(@mask, min_count, dims, true, typecode) do |count_sum, count_accum|
612
+ ary0 = ary0.abs if ary0.complex?
613
+ ary0 = (ary0**2).sum(*dims) / count_sum
614
+ NMMath.sqrt(ary0)
615
+ end
616
+ end
617
+ def rmsdev(*dims)
618
+ min_count = NArrayMiss.check_options(dims, 1)
619
+ # 整数型の場合は浮動小数型へ変換
620
+ ary0 = self.integer? ? self.to_type(NArray::DFLOAT) : self
621
+ NArrayMiss.reduction(@mask, min_count, dims, true, typecode) do |count_sum, count_accum|
622
+ ary0 = ary0 - ary0.accum(*dims)/count_accum
623
+ ary0 = ary0.abs if ary0.complex?
624
+ ary0 = (ary0**2).sum(*dims) / count_sum
625
+ NMMath.sqrt(ary0)
626
+ end
627
+ end
628
+
629
+ def median(*arg)
630
+ if arg.length==0 then
631
+ return @array[@mask].median
632
+ else
633
+ nshape = NArray.to_na(@array.shape)
634
+ nshape[arg]=1
635
+ nslice = nshape[nshape.ne(1).where]
636
+ index = NArray.object(@mask.rank)
637
+ index[nshape.eq(1).where] = true
638
+ obj = NArrayMiss.new(@array.typecode,*nslice.to_a)
639
+ total = 1
640
+ nslice.each{|n| total *= n}
641
+ for i in 0...total
642
+ index[nshape.ne(1).where] = pos(i,nslice)
643
+ mask = NArray.byte(*@array.shape).fill(0)
644
+ mask[*index] = 1
645
+ mask = @mask&mask
646
+ if mask.count_true != 0 then
647
+ obj[*pos(i,nslice)] = @array[mask].median
648
+ end
649
+ end
650
+ return obj
651
+ end
652
+ end
653
+
654
+
655
+ =begin
656
+ === Sort
657
+ --- NArrayMiss#sort(dim)
658
+ sort in the 0..((|dim|)) (All dimensions if omitted)
659
+ --- NArrayMiss#sort_index(dim)
660
+ return index of sort result.
661
+ =end
662
+
663
+ for operator in ["sort","sort_index"]
664
+ eval(<<-EOL,nil,__FILE__,__LINE__+1)
665
+ def #{operator}(*arg)
666
+ obj=NArrayMiss.new(@array.typecode,*@array.shape)
667
+ if arg.length==0 then
668
+ obj[@mask] = @array[@mask].#{operator}
669
+ return obj
670
+ else
671
+ nshape = NArray.to_na(@array.shape)
672
+ nshape[arg]=1
673
+ nslice = nshape[nshape.ne(1).where]
674
+ index = NArray.object(@mask.rank)
675
+ index[nshape.eq(1).where] = true
676
+ obj = NArrayMiss.new(@array.typecode,*@array.shape)
677
+ total = 1
678
+ nslice.each{|n| total *= n}
679
+ for i in 0...total
680
+ index[nshape.ne(1).where] = pos(i,nslice)
681
+ mask = NArray.byte(*@array.shape).fill(0)
682
+ mask[*index] = 1
683
+ mask = @mask&mask
684
+ if mask.count_true != 0 then
685
+ obj[mask] = @array[mask].#{operator}
686
+ end
687
+ end
688
+ return obj
689
+ end
690
+ end
691
+ EOL
692
+ end
693
+
694
+
695
+ =begin
696
+ === Transpose
697
+ --- NArrayMiss#transpose(dim0, dim1, ...)
698
+ transpose array. The 0-th dimension goes to the ((|dim0|))-th dimension of new array.
699
+ =end
700
+
701
+ def transpose(*arg)
702
+ obj = self.dup
703
+ shape = arg.collect{|i| obj.shape[i]}
704
+ obj.reshape!(*shape)
705
+ obj.set_without_validation( @array.transpose(*arg) )
706
+ obj.set_mask(@mask.transpose(*arg))
707
+ obj
708
+ end
709
+
710
+
711
+ =begin
712
+ === Changing Shapes of indices
713
+ --- NArrayMiss#reshape!(size, ...)
714
+ change shape of array.
715
+ --- NArrayMiss#reshape(size, ...)
716
+ same as (({NArrayMiss#reshape!})) but create new object.
717
+ --- NArrayMiss#shape=(size, ...)
718
+ same as (({NArrayMiss#reshape!})).
719
+ --- NArrayMiss#newdim!(dim)
720
+ insert new dimension with size=1
721
+ --- NArrayMiss#newdim(dim)
722
+ same as (({NArrayMiss#newdim!})) but create new object.
723
+ --- NArrayMiss#rewrank!(dim)
724
+ same as (({NArrayMiss#newdim!})).
725
+ --- NArrayMiss#rewrank=(dim)
726
+ same as (({NArrayMiss#newdim!})).
727
+ =end
728
+
729
+ def reshape!(*arg)
730
+ @array = @array.reshape!(*arg)
731
+ @mask = @mask.reshape!(*arg)
732
+ self
733
+ end
734
+ def reshape(*arg)
735
+ obj = self.dup
736
+ obj.reshape!(*arg)
737
+ end
738
+ alias :shape= :reshape!
739
+ def newdim!(*arg)
740
+ @array = @array.newdim!(*arg)
741
+ @mask = @mask.newdim!(*arg)
742
+ self
743
+ end
744
+ alias :rewrank! :newdim!
745
+ alias :rewrank= :newdim!
746
+ def newdim(*arg)
747
+ obj = self.dup
748
+ obj.newdim!(*arg)
749
+ end
750
+ alias :rewrank :newdim
751
+
752
+
753
+ =begin
754
+ === Type conversion
755
+ --- NArrayMiss#floor
756
+ return (({NArrayMiss})) of integer whose elements processed (({floor})).
757
+ --- NArrayMiss#ceil
758
+ return (({NArrayMiss})) of integer whose elements processed (({ceil})).
759
+ --- NArrayMiss#round
760
+ return (({NArrayMiss})) of integer whose elements processed (({round})).
761
+ --- NArrayMiss#to_i
762
+ return (({NArrayMiss})) of integer whose elements processed (({to_i})).
763
+ --- NArrayMiss#to_f
764
+ return (({NArrayMiss})) of float whose elements processed (({to_f})).
765
+ --- NArrayMiss#to_type(typecode)
766
+ return (({NArrayMiss})) of ((|typecode|)).
767
+ --- NArrayMiss#to_a
768
+ convert (({NArrayMiss})) to (({Array})).
769
+ --- NArrayMiss#to_na!([missing_value])
770
+ convert (({NArrayMiss})) to (({NArray})).
771
+ if there is argument, set missing_value for invalid elements.
772
+ --- NArrayMiss#to_na([missing_value])
773
+ convert (({NArrayMiss})) to (({NArray})).
774
+ if there is argument, set missing_value for invalid elements.
775
+ --- NArrayMiss#to_s
776
+ convert (({NArrayMiss})) to (({String})) as a binary data.
777
+ --- NArrayMiss#to_string
778
+ create (({NArrayMiss})) of object whose elements are processed (({to_s}))
779
+ =end
780
+
781
+ def floor
782
+ NArrayMiss.to_nam_no_dup(@array.floor, @mask.dup)
783
+ end
784
+ def ceil
785
+ NArrayMiss.to_nam_no_dup(@array.ceil, @mask.dup)
786
+ end
787
+ def round
788
+ NArrayMiss.to_nam_no_dup(@array.round, @mask.dup)
789
+ end
790
+ def to_i
791
+ NArrayMiss.to_nam_no_dup(@array.to_i, @mask.dup)
792
+ end
793
+ def to_f
794
+ NArrayMiss.to_nam_no_dup(@array.to_f, @mask.dup)
795
+ end
796
+
797
+ def to_type(typecode)
798
+ NArrayMiss.to_nam_no_dup(@array.to_type(typecode), @mask.dup)
799
+ end
800
+ def to_a
801
+ @array.to_a
802
+ end
803
+ def to_na!(*arg)
804
+ if arg.length==0
805
+ return @array
806
+ elsif arg.length==1 then
807
+ self.set_missing_value!(arg[0])
808
+ return @array
809
+ else
810
+ raise(ArgumentError, "Usage: NArray#to_na([missing_value])")
811
+ end
812
+ end
813
+ def to_na(*arg)
814
+ return self.dup.to_na!(*arg)
815
+ end
816
+ def to_s
817
+ @array.to_s
818
+ end
819
+ def to_string
820
+ obj = NArrayMiss.obj(*@array.shape)
821
+ obj.set_without_validation( @array.to_string )
822
+ obh.set_mask(@mask)
823
+ obj
824
+ end
825
+
826
+
827
+ =begin
828
+ === Iteration
829
+ --- NArrayMiss#each{|x| ...}
830
+ --- NArrayMiss#each_valid{|x| ...}
831
+ --- NArrayMiss#each_valid_with_index{|x,i| ...}
832
+ --- NArrayMiss#collect{|x| ...}
833
+ --- NArrayMiss#collect!{|x| ...}
834
+ =end
835
+
836
+ def each
837
+ for i in 0..self.total-1
838
+ yield(@array[i])
839
+ end
840
+ end
841
+ def each_valid
842
+ for i in 0..self.total-1
843
+ yield(@array[i]) if @mask[i]
844
+ end
845
+ end
846
+ def each_valid_with_index
847
+ for i in 0..self.total-1
848
+ yield(@array[i],i) if @mask[i]
849
+ end
850
+ end
851
+ def collect!
852
+ for i in 0..self.total-1
853
+ self[i] = yield(self[i])
854
+ end
855
+ self
856
+ end
857
+ def collect(&blk)
858
+ self.dup.collect!(&blk)
859
+ end
860
+
861
+
862
+ =begin
863
+ === Boolean and mask related (only for byte, sint and int)
864
+ --- NArrayMiss#count_false
865
+ return the number of elements whose value==0 and valid.
866
+ --- NArrayMiss#count_true
867
+ return the number of elements whose value!=0 and valid.
868
+ --- NArrayMiss#mask(mask)
869
+ return (({NArrayMiss#get_mask!&((|mask|))})).
870
+ --- NArrayMiss#all?
871
+ return true if all the valid elements are not 0, else false.
872
+ --- NArrayMiss#any?
873
+ return true if any valid element is not 0, else false.
874
+ --- NArrayMiss#none?
875
+ return true if none of the valid elements is not 0, else false.
876
+ --- NArrayMiss#where
877
+ return (({NArray})) of indices where valid elements are not 0.
878
+ --- NArrayMiss#where2
879
+ return (({Array})) including two (({NArray}))s of indices,
880
+ where valid elements are not 0, and 0, respectively.
881
+ =end
882
+
883
+ def count_false
884
+ if @array.typecode==BYTE then
885
+ return @array.count_false-@mask.count_false
886
+ else
887
+ raise("cannot count_true NArrayMiss except BYTE type")
888
+ end
889
+ end
890
+ def count_true
891
+ if @array.typecode==BYTE then
892
+ return (@array&@mask).count_true
893
+ else
894
+ raise("cannot count_true NArrayMiss except BYTE type")
895
+ end
896
+ end
897
+ def mask(arg)
898
+ obj = self.dup
899
+ if arg.class==NArrayMiss then
900
+ arg = arg.get_array!&arg.get_mask!
901
+ end
902
+ obj.set_mask(@mask&arg)
903
+ end
904
+
905
+ def all?
906
+ @array[@mask].all?
907
+ end
908
+ def any?
909
+ @array[@mask].any?
910
+ end
911
+ def none?
912
+ @array[@mask].none?
913
+ end
914
+
915
+ def where
916
+ (@array&@mask).where
917
+ end
918
+ def where2
919
+ self.where-@mask.where
920
+ end
921
+
922
+
923
+
924
+
925
+ =begin
926
+ === Complex compound number (only for scomplex and complex)
927
+ --- NArrayMiss#real
928
+ --- NArrayMiss#imag
929
+ --- NArrayMiss#conj
930
+ --- NArrayMiss#angle
931
+ --- NArrayMiss#imag=(other)
932
+ --- NArrayMiss#im
933
+ =end
934
+
935
+ def real
936
+ NArrayMiss.to_nam_no_dup(@array.real,@mask)
937
+ end
938
+ def imag
939
+ NArrayMiss.to_nam_no_dup(@array.imag,@mask)
940
+ end
941
+ def conj
942
+ NArrayMiss.to_nam_no_dup(@array.conj,@mask)
943
+ end
944
+ def angle
945
+ NArrayMiss.to_nam_no_dup(@array.angle,@mask)
946
+ end
947
+ def imag=(arg)
948
+ @array.image=(arg)
949
+ self
950
+ end
951
+ def im
952
+ NArrayMiss.to_nam_no_dup(@array.im,@mask)
953
+ end
954
+
955
+
956
+ =begin
957
+ === Byte swap
958
+ --- NArrayMiss#swap_byte
959
+ swap byte order.
960
+ --- NArrayMiss#hton
961
+ convert to network byte order.
962
+ --- NArrayMiss#ntoh
963
+ convert from network byte order.
964
+ --- NArrayMiss#htov
965
+ convert to VAX byte order.
966
+ --- NArrayMiss#vtoh
967
+ convert from VAX byte order.
968
+ =end
969
+
970
+ def swap_byte
971
+ obj = self.dup
972
+ obj.set_without_validation(@array.swap_byte)
973
+ obj
974
+ end
975
+ def hton
976
+ NArrayMiss.to_nam(@array.hton,@mask.hton)
977
+ end
978
+ alias :ntoh :hton
979
+ def htov
980
+ NArrayMiss.to_nam(@array.htov,@mask.htov)
981
+ end
982
+ alias :vtoh :htov
983
+
984
+
985
+ =begin
986
+ === Mask and missing value
987
+ --- NArrayMiss#set_valid(index)
988
+ validate element at ((|index|)).
989
+ ((|index|)) must be (({Integer, Range, Array, or ture})).
990
+ --- NArrayMiss#validation(index)
991
+ alias to set_valid
992
+ --- NArrayMiss#set_invalid(index)
993
+ invaliadate element at ((|index|)).
994
+ ((|index|)) must be (({Integer, Range, Array, or ture})).
995
+ --- NArrayMiss#invalidation(index)
996
+ alias to set_invalid
997
+ --- NArrayMiss#all_valid
998
+ set all elements valid
999
+ --- NArrayMiss#all_invalid
1000
+ set all elements invalid
1001
+ --- NArrayMiss#set_mask(mask)
1002
+ masking by ((|mask|))
1003
+ --- NArrayMiss#set_missing_value(value)
1004
+ replace invalid elements by ((|value|)).
1005
+ --- NArrayMiss#get_mask!
1006
+ return (({NArray})) of byte as mask.
1007
+ --- NArrayMiss#get_mask
1008
+ return (({NArray})) of byte as mask.
1009
+ --- NArrayMiss#get_array!
1010
+ return (({NArray})) as data.
1011
+ --- NArrayMiss#get_array
1012
+ return (({NArray})) as data.
1013
+ --- NArrayMiss#valid?
1014
+ return (({Array})) whose elements are true or false corresponding to valid or invalid of elements, respectively.
1015
+ --- NArrayMiss#all_valid?
1016
+ return true if all elements are valid, else false.
1017
+ --- NArrayMiss#none_valid?
1018
+ return true if all elements are invalid, else false.
1019
+ --- NArrayMiss#all_invalid?
1020
+ alias to none_valid?
1021
+ --- NArrayMiss#any_valid?
1022
+ return true if any elements are valid, else false.
1023
+
1024
+ --- NArrayMiss#count_valid
1025
+ return the number of valid elements.
1026
+ --- NArrayMiss#count_invalid
1027
+ return the number of invalid elements.
1028
+ =end
1029
+
1030
+ def set_valid(*pos)
1031
+ @mask[*pos] = 1
1032
+ self
1033
+ end
1034
+ alias validation set_valid
1035
+ def set_invalid(*pos)
1036
+ @mask[*pos] = 0
1037
+ self
1038
+ end
1039
+ alias invalidation set_invalid
1040
+ def all_valid
1041
+ @mask[true]=1
1042
+ self
1043
+ end
1044
+ def all_invalid
1045
+ @mask[true]=0
1046
+ self
1047
+ end
1048
+ def set_mask(mask)
1049
+ if mask.class == Array then
1050
+ tmp = NArray.byte(*@mask.shape)
1051
+ tmp[true] = mask
1052
+ mask = tmp
1053
+ end
1054
+ if mask.class == NArrayMiss then
1055
+ mask = mask.to_na(0)
1056
+ end
1057
+ if mask.class == NArray then
1058
+ if mask.typecode != BYTE then
1059
+ raise("mask must be NArrayMiss.byte, NArray.byte or Array")
1060
+ end
1061
+ if @array.shape != mask.shape then
1062
+ raise("mask.shape must be same as array")
1063
+ end
1064
+ @mask = mask.dup
1065
+ return self
1066
+ else
1067
+ raise("mask must be NArray.byte or Array")
1068
+ end
1069
+ end
1070
+
1071
+ def set_missing_value!(val)
1072
+ @array[@mask.not] = val
1073
+ self
1074
+ end
1075
+ def set_missing_value(val)
1076
+ obj = self.dup
1077
+ obj.set_missing_value!(val)
1078
+ end
1079
+
1080
+ def get_mask!
1081
+ @mask
1082
+ end
1083
+ def get_mask
1084
+ @mask.dup
1085
+ end
1086
+ def get_array!
1087
+ @array
1088
+ end
1089
+ def get_array
1090
+ @array.dup
1091
+ end
1092
+
1093
+ def valid?
1094
+ where = self.get_mask!.where2
1095
+ tf = Array.new(self.total)
1096
+ for i in where[0]
1097
+ tf[i] = true
1098
+ end
1099
+ for i in where[1]
1100
+ tf[i] = false
1101
+ end
1102
+ tf
1103
+ end
1104
+ def all_valid?
1105
+ @mask.all?
1106
+ end
1107
+ def none_valid?
1108
+ @mask.none?
1109
+ end
1110
+ alias :all_invalid? :none_valid?
1111
+ def any_valid?
1112
+ @mask.any?
1113
+ end
1114
+
1115
+ def count_valid(*arg)
1116
+ if arg.length==0 then
1117
+ return @mask.count_true
1118
+ else
1119
+ return @mask.to_type(NArray::INT).sum(*arg)
1120
+ end
1121
+ end
1122
+ def count_invalid(*arg)
1123
+ if arg.length==0 then
1124
+ return @mask.count_false
1125
+ else
1126
+ return NArray.int(*@mask.shape).fill(1).sum(*arg)-
1127
+ @mask.to_type(NArray::INT).sum(*arg)
1128
+ end
1129
+ end
1130
+
1131
+
1132
+ =begin
1133
+ === Others
1134
+ --- NArrayMiss#integer?
1135
+ return true if (({NArrayMiss})) is byte, sint or int, else false.
1136
+ --- NArrayMiss#complex?
1137
+ return true if (({NArrayMiss})) is scomplex or complex, else false.
1138
+ --- NArrayMiss#dup
1139
+ --- NArrayMiss#coerce(object)
1140
+ --- NArrayMiss#inspect
1141
+
1142
+ go back to ((<Index>))
1143
+ =end
1144
+
1145
+ def integer?
1146
+ @array.integer?
1147
+ end
1148
+ def complex?
1149
+ @array.complex?
1150
+ end
1151
+
1152
+
1153
+ def dup
1154
+ NArrayMiss.to_nam(@array,@mask)
1155
+ end
1156
+
1157
+ alias __clone__ clone
1158
+ def clone
1159
+ obj = __clone__
1160
+ obj.set_array(@array.clone)
1161
+ obj.set_mask(@mask.clone)
1162
+ return obj
1163
+ end
1164
+
1165
+ def coerce(x)
1166
+ if Numeric===x then
1167
+ return [NArrayMiss.new(NArray[x].typecode,*self.shape).fill(x),self]
1168
+ elsif x.class==Array || x.class==NArray then
1169
+ return [NArrayMiss.to_nam(x), self]
1170
+ else
1171
+ raise("donnot know how to cange #{x.class} to NArrayMiss")
1172
+ end
1173
+ end
1174
+
1175
+
1176
+ def inspect
1177
+ # "array -> " + @array.inspect + "\nmask -> " + @mask.inspect
1178
+ count_line = 0
1179
+ max_line = 10
1180
+ max_col = 80
1181
+ sep = ", "
1182
+ const = Hash.new
1183
+ NArray.constants.each{|c| const[NArray.const_get(c)] = c}
1184
+ str_ret = "NArrayMiss."+const[typecode].to_s.downcase+"("+shape.join(",")+"):"
1185
+ if rank == 0 then
1186
+ str_ret << " []"
1187
+ return str_ret
1188
+ else
1189
+ str_ret << "\n"
1190
+ end
1191
+ str = ""
1192
+ index = Array.new(rank,0)
1193
+ index[0] = true
1194
+ i = 1
1195
+ (rank-1).times{ str_ret << "[ " }
1196
+ while(true)
1197
+ i.times{ str_ret << "[ " }
1198
+
1199
+ str = @array[*index].inspect
1200
+ ary = str[str.index("[")+1..str.index("]")-1].strip.split(/\s*,\s*/)
1201
+ miss = @mask[*index].where2[1]
1202
+ miss = miss[miss<ary.length].to_a
1203
+ if ary[-1]=="..." && miss[-1]==ary.length-1 then miss.pop end
1204
+ for j in miss
1205
+ ary[j] = "-"
1206
+ end
1207
+ while ( rank*4+ary.join(", ").length > max_col )
1208
+ ary.pop
1209
+ ary[-1] = "..."
1210
+ end
1211
+ str_ret << ary.join(", ")
1212
+ i = 1
1213
+ while (i<rank)
1214
+ if index[i]<shape[i]-1 then
1215
+ str_ret << " ]" << sep << "\n"
1216
+ count_line += 1
1217
+ index[i] += 1
1218
+ break
1219
+ else
1220
+ str_ret << " ]"
1221
+ index[i] = 0
1222
+ i += 1
1223
+ end
1224
+ end
1225
+
1226
+ if i>=rank then
1227
+ str_ret << " ]"
1228
+ return str_ret
1229
+ elsif count_line>=max_line then
1230
+ str_ret << " ..."
1231
+ return str_ret
1232
+ end
1233
+
1234
+ (rank-i).times{ str_ret << " " }
1235
+ end
1236
+ return str_ret
1237
+ end
1238
+
1239
+
1240
+ def _dump(limit)
1241
+ Marshal::dump([@array._dump(nil),@mask._dump(nil)])
1242
+ end
1243
+ def self._load(o)
1244
+ ary, mask = Marshal::load(o)
1245
+ ary = NArray._load(ary)
1246
+ mask = NArray._load(mask)
1247
+ NArrayMiss.to_nam_no_dup(ary,mask)
1248
+ end
1249
+
1250
+
1251
+
1252
+
1253
+ # private
1254
+ private
1255
+ def pos(n,shape)
1256
+ rank = shape.length
1257
+ result = NArray.int(rank)
1258
+ m=n
1259
+ for i in 0..rank-2
1260
+ j = rank-1-i
1261
+ result[j] = m/shape[j-1]
1262
+ m = m%shape[j-1]
1263
+ end
1264
+ result[0] = m
1265
+ result
1266
+ end
1267
+ def binary_operation(arg, dummy)
1268
+ # arg: 第2項目のオブジェクト
1269
+ # dummy: 演算を行っても結果に影響を与えない特別な値。(欠損部分に代入する)
1270
+ flag=true
1271
+ case arg
1272
+ when Numeric
1273
+ term1 = @array
1274
+ term2 = arg
1275
+ mask = @mask
1276
+ when Array, NArray
1277
+ term1 = @array.dup
1278
+ term1[@mask.not] = dummy # 欠損部分に dummy を代入
1279
+ term2 = arg.kind_of?(NArray) ? arg : NArray.to_na(arg) # Array -> NArray
1280
+ mask = NArray.byte(*term2.shape).fill(1) # 2項目は欠損無し
1281
+ mask = @mask & mask
1282
+ when NArrayMiss
1283
+ term1 = @array.dup
1284
+ term1[@mask.not] = dummy
1285
+ mask = arg.get_mask!
1286
+ term2 = arg.get_array
1287
+ term2[mask.not] = dummy
1288
+ mask = @mask & mask
1289
+ else
1290
+ term1, term2 = arg.coerce(self)
1291
+ # 演算を arg のクラスに任せるため、yield の結果をそのまま返す
1292
+ flag = false
1293
+ end
1294
+ result = yield(term1, term2)
1295
+ result = NArrayMiss.to_nam_no_dup(result, mask) if flag
1296
+ result
1297
+ end
1298
+
1299
+
1300
+ def self.reduction(mask, min_count, dims, flag, typecode)
1301
+ # flag: リダクションを行う次元方向の有効な値の個数で、割り算を行うかどうかのフラグ
1302
+ count_sum = mask.to_type(NArray::LINT).sum(*dims)
1303
+ # 返り値が配列か、スカラーかによって分岐
1304
+ if count_sum.kind_of?(NArray)
1305
+ mask = count_sum.ge(min_count)
1306
+ # すべての要素が欠損値にならないかチェック
1307
+ if mask.any?
1308
+ count_accum = NArray.ref(count_sum)
1309
+ dims.collect{|d|d<0 ? d+mask.rank : d}.sort.each do |d|
1310
+ count_accum.newdim!(d)
1311
+ end
1312
+ # 割り算を行う場合は、先に count_sum を NArrayMiss 化
1313
+ # yield の戻り値は NArrayMiss
1314
+ # 割り算を行わない場合は、後で NArrayMiss 化
1315
+ # yield の戻り値は NArray
1316
+ count_sum = NArrayMiss.to_nam_no_dup(count_sum,mask) if flag
1317
+ ary = yield(count_sum, count_accum)
1318
+ ary = NArrayMiss.to_nam_no_dup(ary, mask) unless flag
1319
+ else
1320
+ # すべての要素が欠損値の NArrayMiss を返す
1321
+ na = NArray.new(typecode, *mask.shape)
1322
+ ary = NArrayMiss.to_nam_no_dup(na, false)
1323
+ end
1324
+ else
1325
+ # 有効な要素数があるかチェック
1326
+ if count_sum >= min_count
1327
+ count_accum = NArray.int(*([1]*mask.rank)).fill!(count_sum)
1328
+ ary = yield(count_sum, count_accum)
1329
+ else
1330
+ # 有効な要素数が足りない場合は nil を返す
1331
+ return nil
1332
+ end
1333
+ end
1334
+ return ary
1335
+ end
1336
+
1337
+
1338
+ # 引数にオプション (Hash) が指定されているかチェックし、
1339
+ # されている場合は、オプションを取得し戻り値として返す。
1340
+ # 現時点では、オプションは "min_count" のみ
1341
+ def self.check_options(arg, default_mincount)
1342
+ min_count = default_mincount
1343
+ options = %w(min_count)
1344
+ if arg.length!=0 && arg[-1].kind_of?(Hash)
1345
+ option = arg.pop
1346
+ option.each_key{|key|
1347
+ if !options.index(key) then
1348
+ raise(ArgumentError,key+" option is not exist")
1349
+ end
1350
+ }
1351
+ min_count = option["min_count"] || default_mincount
1352
+ min_count = min_count.to_i
1353
+ if min_count < default_mincount
1354
+ raise(ArgumentError, "min_count must be >= #{default_mincount}")
1355
+ end
1356
+ end
1357
+ return min_count
1358
+ end
1359
+ end
1360
+
1361
+
1362
+
1363
+ module NMMath
1364
+
1365
+
1366
+ func1 = ["sqrt","exp","log","log10","log2",
1367
+ "sin","cos","tan","sinh","cosh","tanh",
1368
+ "asin","acos","atan","asinh","acosh","atanh",
1369
+ "csc", "sec", "cot", "csch", "sech", "coth",
1370
+ "acsc", "asec", "acot", "acsch", "asech", "acoth",
1371
+ ]
1372
+ func2 = ["atan2"]
1373
+
1374
+ for operator in func1
1375
+ eval <<-EOL,nil,__FILE__,__LINE__+1
1376
+ def #{operator}(x)
1377
+ case x
1378
+ when Numeric, Array, NArray
1379
+ NMath::#{operator}(x)
1380
+ when NArrayMiss
1381
+ obj = NArrayMiss.new(x.typecode,*x.shape)
1382
+ mask = x.get_mask!
1383
+ obj[mask] = NMath::#{operator}(x.get_array![mask])
1384
+ obj[mask.not] = x[mask.not]
1385
+ obj.set_mask(mask)
1386
+ obj
1387
+ else
1388
+ raise ArgumentError, "argument is invalid class: \#{x.class}"
1389
+ end
1390
+ end
1391
+ module_function :#{operator}
1392
+ EOL
1393
+ end
1394
+
1395
+ for operator in func2
1396
+ eval <<-EOL,nil,__FILE__,__LINE__+1
1397
+ def #{operator}(x,y)
1398
+ obj = nil
1399
+ case x
1400
+ when Numeric, Array, NArray
1401
+ mask1 = nil
1402
+ when NArrayMiss
1403
+ obj = NArrayMiss.new(x.typecode,*x.shape)
1404
+ mask1 = x.get_mask!
1405
+ else
1406
+ raise ArgumentError, "argument is invalid class"
1407
+ end
1408
+ case y
1409
+ when Numeric, Array, NArray
1410
+ mask2 = nil
1411
+ when NArrayMiss
1412
+ obj ||= NArrayMiss.new(y.typecode,*y.shape)
1413
+ mask2 = y.get_mask!
1414
+ else
1415
+ raise ArgumentError, "argument is invalid class"
1416
+ end
1417
+ if mask2.nil? then
1418
+ if mask1.nil? then
1419
+ return NMath::#{operator}(x,y)
1420
+ else
1421
+ obj[mask1] = NMath::#{operator}(x.get_array![mask1],y)
1422
+ obj[mask1.not] = x[mask1.not]
1423
+ obj.set_mask(mask1)
1424
+ return obj
1425
+ end
1426
+ else
1427
+ if mask1.nil? then
1428
+ obj[mask2] = NMath::#{operator}(x,y.get_array![mask2])
1429
+ obj[mask2.not] = y[mask2.not]
1430
+ obj.set_mask(mask2)
1431
+ return obj
1432
+ else
1433
+ obj[mask1&mask2] = NMath::#{operator}(x.get_array![mask1],y.get_array![mask2])
1434
+ obj[(mask1&mask2).not] = x[(mask1&mask2).not]
1435
+ return obj
1436
+ end
1437
+ end
1438
+ end
1439
+ module_function :#{operator}
1440
+ EOL
1441
+ end
1442
+
1443
+ methods = Hash.new
1444
+ methods["covariance"] = {:min_count => 2, :post => <<-EOL}
1445
+ mean0 = ary0.accum(*dims) / count_accum
1446
+ mean1 = ary1.accum(*dims) / count_accum
1447
+ ary = ((ary0-mean0)*(ary1-mean1)).sum(*dims)
1448
+ ary / (count_sum-1)
1449
+ EOL
1450
+ methods.each do |name, hash|
1451
+ eval <<-EOL,nil,__FILE__,__LINE__+1
1452
+ def #{name}(ary0,ary1,*dims)
1453
+ min_count = NArrayMiss.check_options(dims, 2)
1454
+ case ary0
1455
+ when Numeric, Array, NArray
1456
+ mask0 = nil
1457
+ when NArrayMiss
1458
+ mask0 = ary0.get_mask!
1459
+ else
1460
+ raise ArgumentError, "argument is invalid class"
1461
+ end
1462
+ case ary1
1463
+ when Numeric, Array, NArray
1464
+ mask1 = nil
1465
+ when NArrayMiss
1466
+ mask1 = ary1.get_mask!
1467
+ else
1468
+ raise ArgumentError, "argument is invalid class"
1469
+ end
1470
+ if mask1.nil? then
1471
+ if mask0.nil? then
1472
+ return NMath.#{name}(ary0, ary1, *dims)
1473
+ else
1474
+ ary1 = NArrayMiss.to_nam_no_dup(ary1, true)
1475
+ end
1476
+ else
1477
+ if mask0.nil?
1478
+ ary0 = NArrayMiss.to_nam_no_dup(ary0, true)
1479
+ end
1480
+ end
1481
+ if ary1.shape != ary1.shape
1482
+ raise "shape is different"
1483
+ end
1484
+ ary0 = ary0.to_type(NArray::DFLOAT)
1485
+ ary1 = ary1.to_type(NArray::DFLOAT)
1486
+ mask = mask0.nil? ? mask1 : mask1.nil? ? mask0 : mask0&mask1
1487
+ ary0.set_mask(mask)
1488
+ ary1.set_mask(mask)
1489
+ NArrayMiss.reduction(mask, min_count, dims, true, NArray::DFLOAT) do |count_sum, count_accum|
1490
+ #{hash[:post]}
1491
+ end
1492
+ end
1493
+ module_function :#{name}
1494
+ EOL
1495
+ end
1496
+
1497
+ for operator in func1+func2+["covariance"]
1498
+ eval <<-EOL,nil,__FILE__,__LINE__+1
1499
+ def #{operator}(*x)
1500
+ x = [self]+x if NArrayMiss===self
1501
+ NMMath.#{operator}(*x)
1502
+ end
1503
+ EOL
1504
+ end
1505
+
1506
+ end
1507
+
1508
+ class NArrayMiss
1509
+ include NMMath
1510
+ end