narray_miss 1.2.1.1 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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