narray_miss 0.1.0

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