BOAST 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/BOAST.gemspec ADDED
@@ -0,0 +1,16 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'BOAST'
3
+ s.version = "0.1"
4
+ s.author = "Brice Videau"
5
+ s.email = "brice.videau@imag.fr"
6
+ s.homepage = "https://forge.imag.fr/projects/boast/"
7
+ s.summary = "BOAST is a computing kernel metaprogramming tool."
8
+ s.description = "BOAST aims at providing a framework to metaprogram, benchmark and validate computing kernels"
9
+ s.files = %w( BOAST.gemspec LICENSE lib/BOAST.rb lib/BOAST/Algorithm.rb lib/BOAST/CKernel.rb lib/BOAST/BOAST_OpenCL.rb )
10
+ s.has_rdoc = true
11
+ s.license = 'BSD'
12
+ s.required_ruby_version = '>= 1.9.3'
13
+ s.add_dependency 'narray', '>=0.6.0.8'
14
+ s.add_dependency 'opencl_ruby_ffi', '>=0.4'
15
+ s.add_dependency 'systemu', '>=2.2.0'
16
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012, Brice Videau <brice.videau@imag.fr>
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/lib/BOAST.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'BOAST/Algorithm.rb'
2
+ require 'BOAST/CKernel.rb'
3
+ require 'BOAST/BOAST_OpenCL.rb'
@@ -0,0 +1,1759 @@
1
+ class Object
2
+ alias_method :orig_method_missing, :method_missing
3
+
4
+ def method_missing(m, *a, &b)
5
+ s=nil
6
+ klass = begin
7
+ s = (self.is_a?(Module) ? self : self.class)
8
+ s.const_get(m)
9
+ rescue NameError
10
+ end
11
+
12
+ return klass.send(:parens, *a, &b) if klass.respond_to? :parens
13
+
14
+ return BOAST::FuncCall::new(m,*a,&b) if s == BOAST
15
+
16
+ orig_method_missing m, *a, &b
17
+ end
18
+ end
19
+
20
+ module BOAST
21
+
22
+ FORTRAN = 1
23
+ C = 2
24
+ CL = 3
25
+ CUDA = 4
26
+ @@output = STDOUT
27
+ @@lang = FORTRAN
28
+ @@replace_constants = true
29
+ @@default_int_size = 4
30
+ @@default_int_signed = true
31
+ @@default_real_size = 8
32
+ @@indent_level = 0
33
+ @@indent_increment = 2
34
+ @@array_start = 1
35
+ @@chain_code = false
36
+
37
+ @@env = Hash.new{|h, k| h[k] = []}
38
+
39
+
40
+ def BOAST::push_env(vars = {})
41
+ vars.each { |key,value|
42
+ var = nil
43
+ begin
44
+ var = BOAST::class_variable_get("@@"+key.to_s)
45
+ rescue
46
+ raise "Unknown module variable #{key}!"
47
+ end
48
+ @@env[key].push(var)
49
+ BOAST::class_variable_set("@@"+key.to_s, value)
50
+ }
51
+ end
52
+
53
+ def BOAST::pop_env(*vars)
54
+ vars.each { |key|
55
+ raise "Unknown module variable #{key}!" unless @@env.has_key?(key)
56
+ ret = @@env[key].pop
57
+ raise "No stored value for #{key}!" if ret.nil?
58
+ BOAST::class_variable_set("@@"+key.to_s, ret)
59
+ }
60
+ end
61
+
62
+ def BOAST::print(a)
63
+ a.print
64
+ end
65
+
66
+ def BOAST::decl(*a)
67
+ a.each { |d|
68
+ d.decl
69
+ }
70
+ end
71
+
72
+ def BOAST::close(a)
73
+ a.close
74
+ end
75
+
76
+ def BOAST::set_indent_level(level)
77
+ @@indent_level = level
78
+ end
79
+
80
+ def BOAST::get_indent_level
81
+ return @@indent_level
82
+ end
83
+
84
+ def BOAST::get_indent_increment
85
+ return @@indent_increment
86
+ end
87
+
88
+ def BOAST::increment_indent_level(increment = @@indent_increment)
89
+ @@indent_level += increment
90
+ end
91
+
92
+ def BOAST::decrement_indent_level(increment = @@indent_increment)
93
+ @@indent_level -= increment
94
+ end
95
+
96
+ def BOAST::set_replace_constants(replace_constants)
97
+ @@replace_constants = replace_constants
98
+ end
99
+
100
+ def BOAST::get_replace_constants
101
+ return @@replace_constants
102
+ end
103
+
104
+ def BOAST::set_default_int_signed(signed)
105
+ @@default_int_signed = signed
106
+ end
107
+
108
+ def BOAST::get_default_int_signed
109
+ return @@default_int_signed
110
+ end
111
+
112
+ def BOAST::set_default_int_size(size)
113
+ @@default_int_size = size
114
+ end
115
+
116
+ def BOAST::get_default_int_size
117
+ return @@default_int_size
118
+ end
119
+
120
+ def BOAST::set_default_real_size(size)
121
+ @@default_real_size = size
122
+ end
123
+
124
+ def BOAST::get_default_real_size
125
+ return @@default_real_size
126
+ end
127
+
128
+ def BOAST::set_lang(lang)
129
+ @@lang = lang
130
+ end
131
+
132
+ def BOAST::get_lang
133
+ return @@lang
134
+ end
135
+
136
+ def BOAST::set_output(output)
137
+ @@output = output
138
+ end
139
+
140
+ def BOAST::get_output
141
+ return @@output
142
+ end
143
+
144
+ def BOAST::set_chain_code(chain_code)
145
+ @@chain_code = chain_code
146
+ end
147
+
148
+ def BOAST::get_chain_code
149
+ return @@chain_code
150
+ end
151
+
152
+ def BOAST::set_array_start(array_start)
153
+ @@array_start = array_start
154
+ end
155
+
156
+ def BOAST::get_array_start
157
+ return @@array_start
158
+ end
159
+
160
+ class Pragma
161
+ def self.parens(*args,&block)
162
+ return self::new(*args,&block)
163
+ end
164
+
165
+ attr_reader :name
166
+ attr_reader :options
167
+
168
+ def initialize(name, options)
169
+ @name = name
170
+ @options = options
171
+ end
172
+
173
+ def to_s
174
+ self.to_str
175
+ end
176
+
177
+ def to_str
178
+ s = ""
179
+ if BOAST::get_lang == FORTRAN then
180
+ s += "$!"
181
+ else
182
+ s += "#pragma"
183
+ end
184
+ @options.each{ |opt|
185
+ s += " #{opt}"
186
+ }
187
+ return s
188
+ end
189
+
190
+ def print(final = true)
191
+ s=""
192
+ s += self.to_str
193
+ BOAST::get_output.puts s if final
194
+ return s
195
+ end
196
+ end
197
+
198
+ def BOAST::Return(value)
199
+ return Expression("return",nil, value)
200
+ end
201
+
202
+ class Expression
203
+ def self.parens(*args,&block)
204
+ return self::new(*args,&block)
205
+ end
206
+
207
+ attr_reader :operator
208
+ attr_reader :operand1
209
+ attr_reader :operand2
210
+ def initialize(operator, operand1, operand2)
211
+ @operator = operator
212
+ @operand1 = operand1
213
+ @operand2 = operand2
214
+ end
215
+ def to_s
216
+ self.to_str
217
+ end
218
+
219
+ def ===(x)
220
+ return Expression::new("=",self,x)
221
+ end
222
+
223
+ def ==(x)
224
+ return Expression::new("==",self,x)
225
+ end
226
+
227
+ def +(x)
228
+ return Expression::new("+",self,x)
229
+ end
230
+
231
+ def >(x)
232
+ return Expression::new(">",self,x)
233
+ end
234
+
235
+ def <(x)
236
+ return Expression::new("<",self,x)
237
+ end
238
+
239
+ def >=(x)
240
+ return Expression::new(">=",self,x)
241
+ end
242
+
243
+ def *(x)
244
+ return Expression::new("*",self,x)
245
+ end
246
+
247
+ def /(x)
248
+ return Expression::new("/",self,x)
249
+ end
250
+
251
+ def dereference
252
+ return Expression::new("*",nil,self)
253
+ end
254
+
255
+ def struct_reference(x)
256
+ return Expression::new(".",self,x)
257
+ end
258
+
259
+ def -(x)
260
+ return Expression::new("-",self,x)
261
+ end
262
+
263
+ def !
264
+ return Expression::new("!",nil,self)
265
+ end
266
+
267
+ def -@
268
+ return Expression::new("-",nil,self)
269
+ end
270
+
271
+ def to_str
272
+ s = ""
273
+ if @operand1 then
274
+ s += "(" if (@operator == "*" or @operator == "/")
275
+ s += @operand1.to_s
276
+ s += ")" if (@operator == "*" or @operator == "/")
277
+ end
278
+ s += " " unless @operator.to_s == "++" or @operator.to_s == "."
279
+ s += @operator.to_s
280
+ s += " " unless @operator.to_s == "." or @operator.to_s == "&" or ( @operator.to_s == "*" and @operand1.nil? )
281
+ if @operand2 then
282
+ s += "(" if (@operator == "*" or @operator == "/" or @operator == "-")
283
+ s += @operand2.to_s
284
+ s += ")" if (@operator == "*" or @operator == "/" or @operator == "-")
285
+ end
286
+ return s
287
+ end
288
+ def print(final=true)
289
+ s=""
290
+ s += " "*BOAST::get_indent_level if final
291
+ s += self.to_str
292
+ s += ";" if final and [C, CL, CUDA].include?( BOAST::get_lang )
293
+ BOAST::get_output.puts s if final
294
+ return s
295
+ end
296
+ end
297
+
298
+ class Mult < Expression
299
+ def initialize(operand1, operand2)
300
+ super("*", operand1, operand2)
301
+ end
302
+ end
303
+
304
+ class Add < Expression
305
+ def initialize(operand1, operand2)
306
+ super("+", operand1, operand2)
307
+ end
308
+ end
309
+
310
+ class Affect < Expression
311
+ def initialize(operand1, operand2)
312
+ super("=", operand1, operand2)
313
+ end
314
+ end
315
+
316
+ class Index < Expression
317
+ attr_reader :source
318
+ attr_reader :indexes
319
+ def initialize(source, indexes)
320
+ @source = source
321
+ @indexes = indexes
322
+ end
323
+ def to_s
324
+ self.to_str
325
+ end
326
+ def to_str
327
+ return self.to_str_fortran if BOAST::get_lang == FORTRAN
328
+ return self.to_str_c if [C, CL, CUDA].include?( BOAST::get_lang )
329
+ end
330
+ def to_str_fortran
331
+ s = ""
332
+ s += "#{@source}(#{@indexes.join(", ")})"
333
+ return s
334
+ end
335
+ def to_str_texture
336
+ raise "Unsupported language #{BOAST::get_lang} for texture!" if not [CL, CUDA].include?( BOAST::get_lang )
337
+ raise "Write is unsupported for textures!" if not ( @source.constant or @source.direction == :in )
338
+ dim_number = 1
339
+ if @source.dimension then
340
+ dim_number == @source.dimension.size
341
+ end
342
+ raise "Unsupported number of dimension: #{dim_number}!" if dim_number > 3
343
+ s = ""
344
+ if BOAST::get_lang == CL then
345
+ s += "as_#{@source.type.decl}("
346
+ s += "read_imageui(#{@source}, #{@source.sampler}, "
347
+ if dim_number == 1 then
348
+ s += "int2(#{@indexes[0]},0)"
349
+ else
350
+ if dim_number == 2 then
351
+ s += "int2("
352
+ else
353
+ s += "int3("
354
+ end
355
+ s += "#{@indexes.join(", ")})"
356
+ end
357
+ s += ")"
358
+ if @source.type.size == 4 then
359
+ s += ".x"
360
+ elsif @source.type.size == 8 then
361
+ s += ".xy"
362
+ end
363
+ s += ")"
364
+ else
365
+ s += "tex#{dim_number}Dfetch(#{@source},"
366
+ if dim_number == 1 then
367
+ s += "#{@indexes[0]}"
368
+ else
369
+ if dim_number == 2 then
370
+ s += "int2("
371
+ else
372
+ s += "int3("
373
+ end
374
+ s += "#{@indexes.join(", ")})"
375
+ end
376
+ s += ")"
377
+ end
378
+ return s
379
+ end
380
+ def to_str_c
381
+ return to_str_texture if @source.texture
382
+ dim = @source.dimension.first
383
+ if dim.val2 then
384
+ start = dim.val1
385
+ else
386
+ start = BOAST::get_array_start
387
+ end
388
+ sub = "#{@indexes.first} - #{start}"
389
+ i=1
390
+ ss = ""
391
+ @source.dimension[0..-2].each{ |d|
392
+ if d.size then
393
+ ss += " * (#{d.size})"
394
+ elsif d.val2 then
395
+ ss += " * (#{d.val2} - (#{d.val1}) + 1)"
396
+ else
397
+ raise "Unkwown dimension size!"
398
+ end
399
+ dim = @source.dimension[i]
400
+ if dim.val2 then
401
+ start = dim.val1
402
+ else
403
+ start = BOAST::get_array_start
404
+ end
405
+ sub += " + (#{@indexes[i]} - (#{start}))"+ss
406
+ i+=1
407
+ }
408
+ if BOAST::get_replace_constants then
409
+ begin
410
+ # puts sub
411
+ indx = eval(sub)
412
+ indx = indx.to_i
413
+ # puts indx
414
+ return "#{@source.constant[indx]}"
415
+ rescue Exception => e
416
+ end
417
+ end
418
+ s = "#{@source}[" + sub + "]"
419
+ return s
420
+ end
421
+ def print(final=true)
422
+ s=""
423
+ s += " "*BOAST::get_indent_level if final
424
+ s += self.to_str
425
+ s += ";" if final and [C, CL, CUDA].include?( BOAST::get_lang )
426
+ BOAST::get_output.puts s if final
427
+ return s
428
+ end
429
+ end
430
+
431
+ class CStruct
432
+ attr_reader :name, :members, :members_array
433
+ def self.parens(*args,&block)
434
+ return Variable::new(args[0], self, *args[1..-1], &block)
435
+ end
436
+
437
+ def initialize(hash={})
438
+ @name = hash[:type_name]
439
+ @members = {}
440
+ @members_array = []
441
+ hash[:members].each { |m|
442
+ mc = m.copy
443
+ @members_array.push(mc)
444
+ @members[mc.name] = mc
445
+ }
446
+ end
447
+
448
+ def decl
449
+ return "struct #{@name}" if [C, CL, CUDA].include?( BOAST::get_lang )
450
+ return "TYPE(#{@name})" if BOAST::get_lang == FORTRAN
451
+ end
452
+
453
+ def finalize
454
+ s = ""
455
+ s += ";" if [C, CL, CUDA].include?( BOAST::get_lang )
456
+ s+="\n"
457
+ return s
458
+ end
459
+
460
+ def indent
461
+ return " "*BOAST::get_indent_level
462
+ end
463
+
464
+ def header
465
+ return header_c if [C, CL, CUDA].include?( BOAST::get_lang )
466
+ return header_fortran if BOAST::get_lang == FORTRAN
467
+ raise "Unsupported language!"
468
+ end
469
+
470
+ def header_c(final = true)
471
+ s = ""
472
+ s += self.indent if final
473
+ s += self.decl + " {\n"
474
+ @members_array.each { |value|
475
+ s+= self.indent if final
476
+ s+= " "*BOAST::get_indent_increment + value.decl(false)+";\n"
477
+ }
478
+ s += self.indent if final
479
+ s += "}"
480
+ s += self.finalize if final
481
+ BOAST::get_output.print s if final
482
+ return s
483
+ end
484
+
485
+ def header_fortran(final = true)
486
+ s = ""
487
+ s += self.indent if final
488
+ s += "TYPE :: #{@name}\n"
489
+ members_array.each { |value|
490
+ s+= self.indent if final
491
+ s+= " "*BOAST::get_indent_increment + value.decl(false)+"\n"
492
+ }
493
+ s += self.indent if final
494
+ s += "END TYPE #{@name}"
495
+ s += self.finalize if final
496
+ BOAST::get_output.print s if final
497
+ return s
498
+ end
499
+
500
+ end
501
+ class CustomType
502
+ attr_reader :size, :name, :vector_length
503
+ def initialize(hash={})
504
+ @name = hash[:type_name]
505
+ @size = hash[:size]
506
+ @vector_length = hash[:vector_length]
507
+ end
508
+ def decl
509
+ return "#{@name}" if [C, CL, CUDA].include?( BOAST::get_lang )
510
+ end
511
+ end
512
+
513
+
514
+ class Variable
515
+ alias_method :orig_method_missing, :method_missing
516
+
517
+ def method_missing(m, *a, &b)
518
+ return self.struct_reference(type.members[m.to_s]) if type.members[m.to_s]
519
+ return self.orig_method_missing(m, *a, &b)
520
+ end
521
+
522
+ def self.parens(*args,&block)
523
+ return self::new(*args,&block)
524
+ end
525
+
526
+ attr_reader :name
527
+ attr_accessor :direction
528
+ attr_accessor :constant
529
+ attr_reader :allocate
530
+ attr_reader :type
531
+ attr_reader :dimension
532
+ attr_reader :local
533
+ attr_reader :texture
534
+ attr_reader :sampler
535
+ attr_reader :replace_constant
536
+ attr_accessor :force_replace_constant
537
+
538
+ def initialize(name,type,hash={})
539
+ @name = name
540
+ @direction = hash[:direction] ? hash[:direction] : hash[:dir]
541
+ @constant = hash[:constant] ? hash[:constant] : hash[:const]
542
+ @dimension = hash[:dimension] ? hash[:dimension] : hash[:dim]
543
+ @local = hash[:local] ? hash[:local] : hash[:shared]
544
+ @texture = hash[:texture]
545
+ @allocate = hash[:allocate]
546
+ @force_replace_constant = false
547
+ if not hash[:replace_constant].nil? then
548
+ @replace_constant = hash[:replace_constant]
549
+ else
550
+ @replace_constant = true
551
+ end
552
+ if @texture and BOAST::get_lang == CL then
553
+ @sampler = Variable::new("sampler_#{name}", BOAST::CustomType,:type_name => "sampler_t" ,:replace_constant => false, :constant => "CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE | CLK_FILTER_NEAREST")
554
+ else
555
+ @sampler = nil
556
+ end
557
+ @type = type::new(hash)
558
+ @hash = hash
559
+ end
560
+
561
+ def copy(name=@name)
562
+ return Variable::new(name, @type.class, @hash)
563
+ end
564
+
565
+ def to_s
566
+ self.to_str
567
+ end
568
+
569
+ def to_str
570
+ if @force_replace_constant or ( @replace_constant and @constant and BOAST::get_replace_constants and not @dimension ) then
571
+ s = @constant.to_s
572
+ s += "_wp" if BOAST::get_lang == FORTRAN and @type and @type.size == 8
573
+ return s
574
+ end
575
+ return @name.to_str
576
+ end
577
+
578
+ def ===(x)
579
+ return Expression::new("=",self,x)
580
+ end
581
+
582
+ def ==(x)
583
+ return Expression::new("==",self,x)
584
+ end
585
+
586
+ def >(x)
587
+ return Expression::new(">",self,x)
588
+ end
589
+
590
+ def <(x)
591
+ return Expression::new("<",self,x)
592
+ end
593
+
594
+ def >=(x)
595
+ return Expression::new(">=",self,x)
596
+ end
597
+
598
+ def +(x)
599
+ return Expression::new("+",self,x)
600
+ end
601
+
602
+ def *(x)
603
+ return Expression::new("*",self,x)
604
+ end
605
+
606
+ def /(x)
607
+ return Expression::new("/",self,x)
608
+ end
609
+
610
+ def -(x)
611
+ return Expression::new("-",self,x)
612
+ end
613
+
614
+ def !
615
+ return Expression::new("!",nil,self)
616
+ end
617
+
618
+ def -@
619
+ return Expression::new("-",nil,self)
620
+ end
621
+
622
+ def address
623
+ return Expression::new("&",nil,self)
624
+ end
625
+
626
+ def dereference
627
+ return Expression::new("*",nil,self)
628
+ end
629
+
630
+ def struct_reference(x)
631
+ return x.copy(self.name+"."+x.name) if [C, CL, CUDA].include?( BOAST::get_lang )
632
+ return x.copy(self.name+"%"+x.name) if BOAST::get_lang == FORTRAN
633
+ end
634
+
635
+ def inc
636
+ return Expression::new("++",self,nil)
637
+ end
638
+
639
+ def [](*args)
640
+ return Index::new(self,args)
641
+ end
642
+
643
+ def indent
644
+ return " "*BOAST::get_indent_level
645
+ end
646
+
647
+ def finalize
648
+ s = ""
649
+ s += ";" if [C, CL, CUDA].include?( BOAST::get_lang )
650
+ s+="\n"
651
+ return s
652
+ end
653
+
654
+ def decl_c(final=true, device=false)
655
+ return decl_texture(final) if @texture
656
+ s = ""
657
+ s += self.indent if final
658
+ s += "const " if @constant or @direction == :in
659
+ s += "__global " if @direction and @dimension and not (@hash[:register] or @hash[:private] or @local) and BOAST::get_lang == CL
660
+ s += "__local " if @local and BOAST::get_lang == CL
661
+ s += "__shared__ " if @local and not device and BOAST::get_lang == CUDA
662
+ s += @type.decl
663
+ if(@dimension and not @constant and not @allocate and (not @local or (@local and device))) then
664
+ s += " *"
665
+ end
666
+ s += " #{@name}"
667
+ if @dimension and @constant then
668
+ s += "[]"
669
+ end
670
+ if @dimension and ((@local and not device) or (@allocate and not @constant)) then
671
+ s +="["
672
+ s += @dimension.reverse.join("*")
673
+ s +="]"
674
+ end
675
+ s += " = #{@constant}" if @constant
676
+ s += self.finalize if final
677
+ BOAST::get_output.print s if final
678
+ return s
679
+ end
680
+
681
+ def header(lang=C,final=true)
682
+ return decl_texture(final) if @texture
683
+ s = ""
684
+ s += self.indent if final
685
+ s += "const " if @constant or @direction == :in
686
+ s += "__global " if @direction and @dimension and BOAST::get_lang == CL
687
+ s += "__local " if @local and BOAST::get_lang == CL
688
+ s += "__shared__ " if @local and BOAST::get_lang == CUDA
689
+ s += @type.decl
690
+ if(@dimension and not @constant and not @local) then
691
+ s += " *"
692
+ end
693
+ if not @dimension and lang == FORTRAN then
694
+ s += " *"
695
+ end
696
+ s += " #{@name}"
697
+ if(@dimension and @constant) then
698
+ s += "[]"
699
+ end
700
+ if(@dimension and @local) then
701
+ s +="["
702
+ s += @dimension.reverse.join("*")
703
+ s +="]"
704
+ end
705
+ s += " = #{@constant}" if @constant
706
+ s += self.finalize if final
707
+ BOAST::get_output.print s if final
708
+ return s
709
+ end
710
+
711
+ def decl(final=true,device=false)
712
+ return self.decl_fortran(final) if BOAST::get_lang == FORTRAN
713
+ return self.decl_c(final, device) if [C, CL, CUDA].include?( BOAST::get_lang )
714
+ end
715
+
716
+ def decl_texture(final=true)
717
+ raise "Unsupported language #{BOAST::get_lang} for texture!" if not [CL, CUDA].include?( BOAST::get_lang )
718
+ raise "Write is unsupported for textures!" if not (@constant or @direction == :in)
719
+ dim_number = 1
720
+ if @dimension then
721
+ dim_number == @dimension.size
722
+ end
723
+ raise "Unsupported number of dimension: #{dim_number}!" if dim_number > 3
724
+ s = ""
725
+ s += self.indent if final
726
+ if BOAST::get_lang == CL then
727
+ s += "__read_only "
728
+ if dim_number < 3 then
729
+ s += "image2d_t " #from OCL 1.2+ image1d_t is defined
730
+ else
731
+ s += "image3d_t "
732
+ end
733
+ else
734
+ s += "texture<#{@type.decl}, cudaTextureType#{dim_number}D, cudaReadModeElementType> "
735
+ end
736
+ s += @name
737
+ s += self.finalize if final
738
+ BOAST::get_output.print s if final
739
+ return s
740
+ end
741
+
742
+
743
+ def decl_fortran(final=true)
744
+ s = ""
745
+ s += self.indent if final
746
+ s += @type.decl
747
+ s += ", intent(#{@direction})" if @direction
748
+ s += ", parameter" if @constant
749
+ if(@dimension) then
750
+ s += ", dimension("
751
+ dim = @dimension[0].to_str
752
+ if dim then
753
+ s += dim
754
+ @dimension[1..-1].each { |d|
755
+ s += ", "
756
+ s += d
757
+ }
758
+ else
759
+ s += ":"
760
+ end
761
+ s += ")"
762
+ end
763
+ s += " :: #{@name}"
764
+ if @constant
765
+ s += " = #{@constant}"
766
+ s += "_wp" if not @dimension and @type and @type.size == 8
767
+ end
768
+ s += self.finalize if final
769
+ BOAST::get_output.print s if final
770
+ return s
771
+ end
772
+
773
+ end
774
+
775
+
776
+
777
+ class Real
778
+ def self.parens(*args,&block)
779
+ return Variable::new(args[0], self, *args[1..-1], &block)
780
+ end
781
+
782
+ attr_reader :size
783
+ def initialize(hash={})
784
+ if hash[:size] then
785
+ @size = hash[:size]
786
+ else
787
+ @size = BOAST::get_default_real_size
788
+ end
789
+ if hash[:vector_length] and hash[:vector_length] > 1 then
790
+ @vector_length = hash[:vector_length]
791
+ else
792
+ @vector_length = 1
793
+ end
794
+ end
795
+ def decl
796
+ return "real(kind=#{@size})" if BOAST::get_lang == FORTRAN
797
+ if [C, CL, CUDA].include?( BOAST::get_lang ) and @vector_length == 1 then
798
+ return "float" if @size == 4
799
+ return "double" if @size == 8
800
+ elsif [CL, CUDA].include?(BOAST::get_lang) and @vector_length > 1 then
801
+ return "float#{@vector_length}" if @size == 4
802
+ return "double#{@vector_length}" if @size == 8
803
+ end
804
+ end
805
+ end
806
+
807
+ class CodeBlock
808
+ def initialize(&block)
809
+ @block = block
810
+ end
811
+
812
+ def print(final=true)
813
+ s=""
814
+ s += " "*BOAST::get_indent_level if final
815
+ BOAST::increment_indent_level
816
+ BOAST::get_output.puts s if final
817
+ if @block then
818
+ s += "\n"
819
+ @block.call
820
+ end
821
+ return s
822
+ end
823
+ end
824
+
825
+ class Procedure
826
+ def self.parens(*args,&block)
827
+ return self::new(*args,&block)
828
+ end
829
+
830
+ attr_reader :name
831
+ attr_reader :parameters
832
+ attr_reader :constants
833
+ attr_reader :properties
834
+ attr_reader :headers
835
+ def initialize(name, parameters=[], constants=[], properties={}, &block)
836
+ @name = name
837
+ @parameters = parameters
838
+ @constants = constants
839
+ @block = block
840
+ @properties = properties
841
+ @headers = properties[:headers]
842
+ @headers = [] if not @headers
843
+ end
844
+
845
+ def header(lang=C,final=true)
846
+ s = ""
847
+ headers.each { |h|
848
+ s += "#include <#{h}>\n"
849
+ }
850
+ if BOAST::get_lang == CL then
851
+ s += "__kernel "
852
+ wgs = @properties[:reqd_work_group_size]
853
+ if wgs then
854
+ s += "__attribute__((reqd_work_group_size(#{wgs[0]},#{wgs[1]},#{wgs[2]}))) "
855
+ end
856
+ end
857
+ trailer = ""
858
+ trailer += "_" if lang == FORTRAN
859
+ trailer += "_wrapper" if lang == CUDA
860
+ if @properties[:return] then
861
+ s += "#{@properties[:return].type.decl} "
862
+ elsif lang == CUDA
863
+ s += "unsigned long long int "
864
+ else
865
+ s += "void "
866
+ end
867
+ s += "#{@name}#{trailer}("
868
+ if parameters.first then
869
+ s += parameters.first.header(lang,false)
870
+ parameters[1..-1].each { |p|
871
+ s += ", "
872
+ s += p.header(lang,false)
873
+ }
874
+ end
875
+ if lang == CUDA then
876
+ s += ", " if parameters.first
877
+ s += "size_t *block_number, size_t *block_size"
878
+ end
879
+ s += ")"
880
+ s += ";\n" if final
881
+ BOAST::get_output.print s if final
882
+ return s
883
+ end
884
+
885
+ def call(*parameters)
886
+ prefix = ""
887
+ prefix += "call " if BOAST::get_lang==FORTRAN
888
+ f = FuncCall::new(@name, *parameters)
889
+ f.prefix = prefix
890
+ return f
891
+ end
892
+ def decl(final=true)
893
+ return self.decl_fortran(final) if BOAST::get_lang==FORTRAN
894
+ return self.decl_c(final) if [C, CL, CUDA].include?( BOAST::get_lang )
895
+ end
896
+ def close(final=true)
897
+ return self.close_fortran(final) if BOAST::get_lang==FORTRAN
898
+ return self.close_c(final) if [C, CL, CUDA].include?( BOAST::get_lang )
899
+ end
900
+ def close_c(final=true)
901
+ BOAST::decrement_indent_level
902
+ s = ""
903
+ s += " return #{@properties[:return]};\n" if @properties[:return]
904
+ s += "}"
905
+ BOAST::get_output.puts s if final
906
+ return s
907
+ end
908
+ def close_fortran(final=true)
909
+ BOAST::decrement_indent_level
910
+ s = ""
911
+ if @properties[:return] then
912
+ s += " #{@name} = #{@properties[:return]}\n"
913
+ s += "END FUNCTION #{@name}"
914
+ else
915
+ s += "END SUBROUTINE #{@name}"
916
+ end
917
+ BOAST::get_output.puts s if final
918
+ return s
919
+ end
920
+
921
+ def print(final=true)
922
+ s = self.decl
923
+ if @block then
924
+ @block.call
925
+ s += self.close
926
+ end
927
+ return s
928
+ end
929
+
930
+ def decl_c(final=true)
931
+ s = ""
932
+ # s += self.header(BOAST::get_lang,false)
933
+ # s += ";\n"
934
+ if BOAST::get_lang == CL then
935
+ if not @properties[:local] then
936
+ s += "__kernel "
937
+ end
938
+ wgs = @properties[:reqd_work_group_size]
939
+ if wgs then
940
+ s += "__attribute__((reqd_work_group_size(#{wgs[0]},#{wgs[1]},#{wgs[2]}))) "
941
+ end
942
+ elsif BOAST::get_lang == CUDA then
943
+ if @properties[:local] then
944
+ s += "__device__ "
945
+ else
946
+ s += "__global__ "
947
+ end
948
+ end
949
+ if @properties[:return] then
950
+ s += "#{@properties[:return].type.decl} "
951
+ else
952
+ s += "void "
953
+ end
954
+ s += "#{@name}("
955
+ if parameters.first then
956
+ s += parameters.first.decl(false, @properties[:local])
957
+ parameters[1..-1].each { |p|
958
+ s += ", "+p.decl(false, @properties[:local])
959
+ }
960
+ end
961
+ s += "){\n"
962
+ BOAST::increment_indent_level
963
+ constants.each { |c|
964
+ s += " "*BOAST::get_indent_level
965
+ s += c.decl(false)
966
+ s += ";\n"
967
+ }
968
+ BOAST::get_output.print s if final
969
+ return s
970
+ end
971
+ def decl_fortran(final=true)
972
+ s = ""
973
+ if @properties[:return] then
974
+ s += "#{@properties[:return].type.decl} FUNCTION "
975
+ else
976
+ s += "SUBROUTINE "
977
+ end
978
+ s += "#{@name}("
979
+ if parameters.first then
980
+ s += parameters.first
981
+ parameters[1..-1].each { |p|
982
+ s += ", "+p
983
+ }
984
+ end
985
+ s += ")\n"
986
+ BOAST::increment_indent_level
987
+ s += " "*BOAST::get_indent_level + "integer, parameter :: wp=kind(1.0d0)\n"
988
+ constants.each { |c|
989
+ s += " "*BOAST::get_indent_level
990
+ s += c.decl(false)
991
+ s += "\n"
992
+ }
993
+ parameters.each { |p|
994
+ s += " "*BOAST::get_indent_level
995
+ s += p.decl(false)
996
+ s += "\n"
997
+ }
998
+ BOAST::get_output.print s if final
999
+ return s
1000
+ end
1001
+ end
1002
+
1003
+ class Dimension
1004
+ def self.parens(*args,&block)
1005
+ return self::new(*args,&block)
1006
+ end
1007
+
1008
+ attr_reader :val1
1009
+ attr_reader :val2
1010
+ attr_reader :size
1011
+ def initialize(v1=nil,v2=nil)
1012
+ @size = nil
1013
+ @val1 = nil
1014
+ @val2 = nil
1015
+ if v2.nil? and v1 then
1016
+ @val1 = BOAST::get_array_start
1017
+ @val2 = v1 + BOAST::get_array_start - 1
1018
+ @size = v1
1019
+ else
1020
+ @val1 = v1
1021
+ @val2 = v2
1022
+ end
1023
+ end
1024
+ def to_str
1025
+ s = ""
1026
+ if @val2 then
1027
+ if BOAST::get_lang == FORTRAN then
1028
+ s += @val1.to_s
1029
+ s += ":"
1030
+ s += @val2.to_s
1031
+ elsif [C, CL, CUDA].include?( BOAST::get_lang ) then
1032
+ s += (@val2 - @val1 + 1).to_s
1033
+ end
1034
+ elsif @val1.nil? then
1035
+ return nil
1036
+ else
1037
+ s += @val1.to_s
1038
+ end
1039
+ return s
1040
+ end
1041
+ def to_s
1042
+ self.to_str
1043
+ end
1044
+ end
1045
+
1046
+ class Sizet
1047
+ def self.parens(*args,&block)
1048
+ return Variable::new(args[0], self, *args[1..-1], &block)
1049
+ end
1050
+
1051
+ attr_reader :signed
1052
+ def initialize(hash={})
1053
+ if hash[:signed] != nil then
1054
+ @signed = hash[:signed]
1055
+ end
1056
+ end
1057
+ def decl
1058
+ return "integer(kind=#{BOAST::get_default_int_signed})" if BOAST::get_lang == FORTRAN
1059
+ if not @signed then
1060
+ return "size_t" if [C, CL, CUDA].include?( BOAST::get_lang )
1061
+ else
1062
+ return "ptrdiff_t" if [C, CL, CUDA].include?( BOAST::get_lang )
1063
+ end
1064
+ end
1065
+ end
1066
+
1067
+ class Int
1068
+ def self.parens(*args,&block)
1069
+ return Variable::new(args[0], self, *args[1..-1], &block)
1070
+ end
1071
+
1072
+ attr_reader :size
1073
+ attr_reader :signed
1074
+ def initialize(hash={})
1075
+ if hash[:size] then
1076
+ @size = hash[:size]
1077
+ else
1078
+ @size = BOAST::get_default_int_size
1079
+ end
1080
+ if hash[:signed] != nil then
1081
+ @signed = hash[:signed]
1082
+ else
1083
+ @signed = BOAST::get_default_int_signed
1084
+ end
1085
+ end
1086
+ def decl
1087
+ return "integer(kind=#{@size})" if BOAST::get_lang == FORTRAN
1088
+ return "int#{8*@size}_t" if BOAST::get_lang == C
1089
+ if BOAST::get_lang == CL then
1090
+ #char="cl_"
1091
+ char=""
1092
+ char += "u" if not @signed
1093
+ return char += "char" if @size==1
1094
+ return char += "short" if @size==2
1095
+ return char += "int" if @size==4
1096
+ return char += "long" if @size==8
1097
+ elsif BOAST::get_lang == CUDA then
1098
+ char = ""
1099
+ char += "unsigned " if not @signed
1100
+ return char += "char" if @size==1
1101
+ return char += "short" if @size==2
1102
+ return char += "int" if @size==4
1103
+ return char += "long long" if @size==8
1104
+ end
1105
+ end
1106
+ end
1107
+
1108
+ class ConstArray < Array
1109
+ def initialize(array,type = nil)
1110
+ super(array)
1111
+ @type = type::new if type
1112
+ end
1113
+ def to_s
1114
+ self.to_str
1115
+ end
1116
+ def to_str
1117
+ return self.to_str_fortran if BOAST::get_lang == FORTRAN
1118
+ return self.to_str_c if [C, CL, CUDA].include?( BOAST::get_lang )
1119
+ end
1120
+ def to_str_fortran
1121
+ s = ""
1122
+ return s if self.first.nil?
1123
+ s += "(/ &\n"
1124
+ s += self.first
1125
+ s += "_wp" if @type and @type.size == 8
1126
+ self[1..-1].each { |v|
1127
+ s += ", &\n"+v
1128
+ s += "_wp" if @type and @type.size == 8
1129
+ }
1130
+ s += " /)"
1131
+ end
1132
+ def to_str_c
1133
+ s = ""
1134
+ return s if self.first.nil?
1135
+ s += "{\n"
1136
+ s += self.first
1137
+ self[1..-1].each { |v|
1138
+ s += ",\n"+v
1139
+ }
1140
+ s += "}"
1141
+ end
1142
+ end
1143
+
1144
+ class Ternary
1145
+
1146
+ def self.parens(*args,&block)
1147
+ return self::new(*args,&block)
1148
+ end
1149
+
1150
+ attr_reader :operand1
1151
+ attr_reader :operand2
1152
+ attr_reader :operand3
1153
+
1154
+ def initialize(x,y,z)
1155
+ @operand1 = x
1156
+ @operand2 = y
1157
+ @operand3 = z
1158
+ end
1159
+
1160
+ def ==(x)
1161
+ return Expression::new("==",self,x)
1162
+ end
1163
+
1164
+ def +(x)
1165
+ return Expression::new("+",self,x)
1166
+ end
1167
+
1168
+ def <(x)
1169
+ return Expression::new("<",self,x)
1170
+ end
1171
+
1172
+ def >=(x)
1173
+ return Expression::new(">=",self,x)
1174
+ end
1175
+
1176
+ def *(x)
1177
+ return Expression::new("*",self,x)
1178
+ end
1179
+
1180
+ def -(x)
1181
+ return Expression::new("-",self,x)
1182
+ end
1183
+
1184
+ def -@
1185
+ return Expression::new("-",nil,self)
1186
+ end
1187
+
1188
+ def [](*args)
1189
+ return Index::new(self,args)
1190
+ end
1191
+
1192
+ def to_s
1193
+ self.to_str
1194
+ end
1195
+
1196
+ def to_str
1197
+ raise "Ternary operator unsupported in FORTRAN!" if BOAST::get_lang == FORTRAN
1198
+ return self.to_str_c if [C, CL, CUDA].include?( BOAST::get_lang )
1199
+ end
1200
+ def to_str_c
1201
+ s = ""
1202
+ s += "(#{@operand1} ? #{@operand2} : #{@operand3})"
1203
+ end
1204
+ def print(final=true)
1205
+ s=""
1206
+ s += " "*BOAST::get_indent_level if final
1207
+ s += self.to_str
1208
+ s += ";" if final and [C, CL, CUDA].include?( BOAST::get_lang )
1209
+ BOAST::get_output.puts s if final
1210
+ return s
1211
+ end
1212
+
1213
+ end
1214
+
1215
+ class FuncCall
1216
+ def self.parens(*args,&block)
1217
+ return self::new(*args,&block)
1218
+ end
1219
+
1220
+ attr_reader :func_name
1221
+ attr_reader :args
1222
+ attr_accessor :prefix
1223
+
1224
+ def initialize(func_name, *args)
1225
+ @func_name = func_name
1226
+ @args = args
1227
+ end
1228
+
1229
+ def to_s
1230
+ self.to_str
1231
+ end
1232
+
1233
+ def ==(x)
1234
+ return Expression::new("==",self,x)
1235
+ end
1236
+
1237
+ def +(x)
1238
+ return Expression::new("+",self,x)
1239
+ end
1240
+
1241
+ def *(x)
1242
+ return Expression::new("*",self,x)
1243
+ end
1244
+
1245
+ def /(x)
1246
+ return Expression::new("/",self,x)
1247
+ end
1248
+
1249
+ def -(x)
1250
+ return Expression::new("-",self,x)
1251
+ end
1252
+
1253
+ def -@
1254
+ return Expression::new("-",nil,self)
1255
+ end
1256
+
1257
+ def [](*args)
1258
+ return Index::new(self,args)
1259
+ end
1260
+
1261
+
1262
+ def to_str
1263
+ return self.to_str_fortran if BOAST::get_lang == FORTRAN
1264
+ return self.to_str_c if [C, CL, CUDA].include?( BOAST::get_lang )
1265
+ end
1266
+ def to_str_fortran
1267
+ s = ""
1268
+ s += @prefix if @prefix
1269
+ s += "#{func_name}(#{@args.join(", ")})"
1270
+ end
1271
+ def to_str_c
1272
+ s = ""
1273
+ s += @prefix if @prefix
1274
+ s += "#{func_name}(#{@args.join(", ")})"
1275
+ end
1276
+ def print(final=true)
1277
+ s=""
1278
+ s += " "*BOAST::get_indent_level if final
1279
+ s += self.to_str
1280
+ s += ";" if final and [C, CL, CUDA].include?( BOAST::get_lang )
1281
+ BOAST::get_output.puts s if final
1282
+ return s
1283
+ end
1284
+ end
1285
+
1286
+ class While
1287
+ def self.parens(*args,&block)
1288
+ return self::new(*args,&block)
1289
+ end
1290
+
1291
+ attr_reader :condition
1292
+ def initialize(condition, &block)
1293
+ @condition = condition
1294
+ @block = block
1295
+ end
1296
+ def to_s
1297
+ self.to_str
1298
+ end
1299
+ def to_str
1300
+ return self.to_str_fortran if BOAST::get_lang == FORTRAN
1301
+ return self.to_str_c if [C, CL, CUDA].include?( BOAST::get_lang )
1302
+ end
1303
+ def to_str_fortran
1304
+ s = ""
1305
+ s += "do while( #{@condition} )"
1306
+ return s
1307
+ end
1308
+ def to_str_c
1309
+ s = ""
1310
+ s += "while(#{@condition}){"
1311
+ return s
1312
+ end
1313
+ def print(*args)
1314
+ final = true
1315
+ s=""
1316
+ s += " "*BOAST::get_indent_level if final
1317
+ s += self.to_str
1318
+ BOAST::increment_indent_level
1319
+ BOAST::get_output.puts s if final
1320
+ if @block then
1321
+ s += "\n"
1322
+ @block.call(*args)
1323
+ s += self.close
1324
+ end
1325
+ return s
1326
+ end
1327
+ def close(final=true)
1328
+ return self.close_fortran(final) if BOAST::get_lang == FORTRAN
1329
+ return self.close_c(final) if [C, CL, CUDA].include?( BOAST::get_lang )
1330
+ end
1331
+ def close_c(final=true)
1332
+ s = ""
1333
+ BOAST::decrement_indent_level
1334
+ s += " "*BOAST::get_indent_level if final
1335
+ s += "}"
1336
+ BOAST::get_output.puts s if final
1337
+ return s
1338
+ end
1339
+ def close_fortran(final=true)
1340
+ s = ""
1341
+ BOAST::decrement_indent_level
1342
+ s += " "*BOAST::get_indent_level if final
1343
+ s += "end do"
1344
+ BOAST::get_output.puts s if final
1345
+ return s
1346
+ end
1347
+
1348
+ end
1349
+
1350
+ class Else
1351
+ def self.parens(*args,&block)
1352
+ return self::new(*args,&block)
1353
+ end
1354
+
1355
+ attr_reader :condition
1356
+ def initialize(condition=nil, &block)
1357
+ @condition = condition
1358
+ @block = block
1359
+ end
1360
+ def to_s
1361
+ self.to_str
1362
+ end
1363
+ def to_str
1364
+ return self.to_str_fortran if BOAST::get_lang == FORTRAN
1365
+ return self.to_str_c if [C, CL, CUDA].include?( BOAST::get_lang )
1366
+ end
1367
+ def to_str_fortran
1368
+ s = ""
1369
+ if @condition then
1370
+ s += "else if #{@condition} then"
1371
+ else
1372
+ s += "else"
1373
+ end
1374
+ return s
1375
+ end
1376
+ def to_str_c
1377
+ s = ""
1378
+ if @condition then
1379
+ s += "else if(#{@condition}){"
1380
+ else
1381
+ s += "else {"
1382
+ end
1383
+ return s
1384
+ end
1385
+ def print(*args)
1386
+ final = true
1387
+ s=""
1388
+ s += " "*BOAST::get_indent_level if final
1389
+ s += self.to_str
1390
+ BOAST::increment_indent_level
1391
+ BOAST::get_output.puts s if final
1392
+ if @block then
1393
+ s += "\n"
1394
+ @block.call(*args)
1395
+ s += self.close
1396
+ end
1397
+ return s
1398
+ end
1399
+ def close(final=true)
1400
+ return self.close_fortran(final) if BOAST::get_lang == FORTRAN
1401
+ return self.close_c(final) if [C, CL, CUDA].include?( BOAST::get_lang )
1402
+ end
1403
+ def close_c(final=true)
1404
+ s = ""
1405
+ BOAST::decrement_indent_level
1406
+ s += " "*BOAST::get_indent_level if final
1407
+ s += "}"
1408
+ BOAST::get_output.puts s if final
1409
+ return s
1410
+ end
1411
+ def close_fortran(final=true)
1412
+ s = ""
1413
+ BOAST::decrement_indent_level
1414
+ s += " "*BOAST::get_indent_level if final
1415
+ s += "end if"
1416
+ BOAST::get_output.puts s if final
1417
+ return s
1418
+ end
1419
+
1420
+ end
1421
+
1422
+ class Case
1423
+ def self.parens(*args,&block)
1424
+ return self::new(*args,&block)
1425
+ end
1426
+
1427
+ attr_reader :expression
1428
+ attr_reader :constants_list
1429
+
1430
+ def initialize(expression, *control)
1431
+ @expression = expression
1432
+ @constants_list = []
1433
+ @blocks = []
1434
+ if control.size < 1 then
1435
+ raise "No block given!"
1436
+ elsif control.size.even? then
1437
+ (0..control.size-1).step(2) { |i|
1438
+ @constants_list[i/2] = [control[i]].flatten
1439
+ @blocks[i/2] = control[i+1]
1440
+ }
1441
+ else
1442
+ (0..control.size-2).step(2) { |i|
1443
+ @constants_list[i/2] = [control[i]].flatten
1444
+ @blocks[i/2] = control[i+1]
1445
+ }
1446
+ @blocks.push(control.last)
1447
+ end
1448
+ end
1449
+
1450
+ def to_s(*args)
1451
+ self.to_str(*args)
1452
+ end
1453
+
1454
+ def to_str(constants, first= true)
1455
+ return self.to_str_fortran(constants, first) if BOAST::get_lang == FORTRAN
1456
+ return self.to_str_c(constants, first) if [C, CL, CUDA].include?( BOAST::get_lang )
1457
+ end
1458
+
1459
+ def to_str_fortran(constants, first)
1460
+ s = ""
1461
+ if first then
1462
+ s += "select case #{@expression}\n"
1463
+ BOAST::increment_indent_level
1464
+ else
1465
+ BOAST::decrement_indent_level
1466
+ end
1467
+ s += " "*BOAST::get_indent_level
1468
+ if constants and constants.size>0 then
1469
+ s += "case #{constants.join(" : ")}"
1470
+ else
1471
+ s += "case default"
1472
+ end
1473
+ BOAST::increment_indent_level
1474
+ return s
1475
+ end
1476
+
1477
+ def to_str_c(constants, first)
1478
+ s = ""
1479
+ if first then
1480
+ s += " "*BOAST::get_indent_level
1481
+ s += "switch(#{@expression}){\n"
1482
+ BOAST::increment_indent_level
1483
+ else
1484
+ s += " "*BOAST::get_indent_level + "break;\n"
1485
+ BOAST::decrement_indent_level
1486
+ end
1487
+ s += " "*BOAST::get_indent_level
1488
+ if constants and constants.size>0 then
1489
+ s += "case #{constants.join(" : case")} :"
1490
+ else
1491
+ s += "default :"
1492
+ end
1493
+ BOAST::increment_indent_level
1494
+ return s
1495
+ end
1496
+
1497
+ def print(*args)
1498
+ first = true
1499
+ @blocks.each_index { |indx|
1500
+ s = self.to_str(@constants_list[indx],first)
1501
+ BOAST::get_output.puts s
1502
+ @blocks[indx].call(*args)
1503
+ first = false
1504
+ }
1505
+ self.close
1506
+ return self
1507
+ end
1508
+ def close(final=true)
1509
+ return self.close_fortran(final) if BOAST::get_lang == FORTRAN
1510
+ return self.close_c(final) if [C, CL, CUDA].include?( BOAST::get_lang )
1511
+ end
1512
+ def close_c(final=true)
1513
+ s = ""
1514
+ s += " "*BOAST::get_indent_level if final
1515
+ s += "break;\n"
1516
+ BOAST::decrement_indent_level
1517
+ s += " "*BOAST::get_indent_level if final
1518
+ s += "}"
1519
+ BOAST::decrement_indent_level
1520
+ BOAST::get_output.puts s if final
1521
+ return s
1522
+ end
1523
+ def close_fortran(final=true)
1524
+ s = ""
1525
+ BOAST::decrement_indent_level
1526
+ s += " "*BOAST::get_indent_level if final
1527
+ s += "end select"
1528
+ BOAST::decrement_indent_level
1529
+ BOAST::get_output.puts s if final
1530
+ return s
1531
+ end
1532
+
1533
+ end
1534
+ class If
1535
+ def self.parens(*args,&block)
1536
+ return self::new(*args,&block)
1537
+ end
1538
+
1539
+ attr_reader :conditions
1540
+ def initialize(*conditions, &block)
1541
+ @conditions = []
1542
+ @blocks = []
1543
+ if conditions.size == 0 then
1544
+ raise "Illegal if construct!"
1545
+ elsif conditions.size == 1 then
1546
+ @conditions.push(conditions[0])
1547
+ @blocks.push(block)
1548
+ elsif conditions.size.even? then
1549
+ (0..conditions.size-1).step(2) { |i|
1550
+ @conditions[i/2] = conditions[i]
1551
+ @blocks[i/2] = conditions[i+1]
1552
+ }
1553
+ else
1554
+ (0..conditions.size-2).step(2) { |i|
1555
+ @conditions[i/2] = conditions[i]
1556
+ @blocks[i/2] = conditions[i+1]
1557
+ }
1558
+ @blocks.push(conditions.last)
1559
+ end
1560
+ end
1561
+ def to_s(*args)
1562
+ self.to_str(*args)
1563
+ end
1564
+ def to_str(condition, first= true)
1565
+ return self.to_str_fortran(condition, first) if BOAST::get_lang == FORTRAN
1566
+ return self.to_str_c(condition, first) if [C, CL, CUDA].include?( BOAST::get_lang )
1567
+ end
1568
+ def to_str_fortran(condition, first)
1569
+ s = ""
1570
+ if first then
1571
+ s += "if #{condition} then"
1572
+ else
1573
+ if condition then
1574
+ s += "else if #{condition} then"
1575
+ else
1576
+ s += "else"
1577
+ end
1578
+ end
1579
+ return s
1580
+ end
1581
+ def to_str_c(condition, first)
1582
+ s = ""
1583
+ if first then
1584
+ s += "if(#{condition}){"
1585
+ else
1586
+ if condition then
1587
+ s += "} else if(#{condition}){"
1588
+ else
1589
+ s += "} else {"
1590
+ end
1591
+ end
1592
+ return s
1593
+ end
1594
+ def print(*args)
1595
+ s=""
1596
+ s += " "*BOAST::get_indent_level
1597
+ s += self.to_str(@conditions.first)
1598
+ BOAST::increment_indent_level
1599
+ BOAST::get_output.puts s
1600
+ if @blocks.size > 0 then
1601
+ if @blocks[0] then
1602
+ @blocks[0].call(*args)
1603
+ end
1604
+ @blocks[1..-1].each_index { |indx|
1605
+ BOAST::decrement_indent_level
1606
+ s=""
1607
+ s += " "*BOAST::get_indent_level
1608
+ s += self.to_str(@conditions[1..-1][indx],false)
1609
+ BOAST::increment_indent_level
1610
+ BOAST::get_output.puts s
1611
+ @blocks[1..-1][indx].call(*args)
1612
+ }
1613
+ self.close
1614
+ end
1615
+ return self
1616
+ end
1617
+ def close(final=true)
1618
+ return self.close_fortran(final) if BOAST::get_lang == FORTRAN
1619
+ return self.close_c(final) if [C, CL, CUDA].include?( BOAST::get_lang )
1620
+ end
1621
+ def close_c(final=true)
1622
+ s = ""
1623
+ BOAST::decrement_indent_level
1624
+ s += " "*BOAST::get_indent_level if final
1625
+ s += "}"
1626
+ BOAST::get_output.puts s if final
1627
+ return s
1628
+ end
1629
+ def close_fortran(final=true)
1630
+ s = ""
1631
+ BOAST::decrement_indent_level
1632
+ s += " "*BOAST::get_indent_level if final
1633
+ s += "end if"
1634
+ BOAST::get_output.puts s if final
1635
+ return s
1636
+ end
1637
+
1638
+ end
1639
+
1640
+ class For
1641
+ attr_reader :iterator
1642
+ attr_reader :begin
1643
+ attr_reader :end
1644
+ attr_reader :step
1645
+
1646
+ def self.parens(*args,&block)
1647
+ return self::new(*args,&block)
1648
+ end
1649
+
1650
+ def initialize(i, b, e, s=1, &block)
1651
+ @iterator = i
1652
+ @begin = b
1653
+ @end = e
1654
+ @step = s
1655
+ @block = block
1656
+ end
1657
+ def to_s
1658
+ self.to_str
1659
+ end
1660
+ def to_str
1661
+ return self.to_str_fortran if BOAST::get_lang == FORTRAN
1662
+ return self.to_str_c if [C, CL, CUDA].include?( BOAST::get_lang )
1663
+ end
1664
+ def to_str_fortran
1665
+ s = ""
1666
+ s += "do #{@iterator}=#{@begin}, #{@end}"
1667
+ s += ", #{@step}" if @step != 1
1668
+ return s
1669
+ end
1670
+ def to_str_c
1671
+ s = ""
1672
+ s += "for(#{@iterator}=#{@begin}; #{@iterator}<=#{@end}; #{@iterator}+=#{@step}){"
1673
+ return s
1674
+ end
1675
+
1676
+ def unroll(*args)
1677
+ raise "Block not given!" if not @block
1678
+ BOAST::push_env( :replace_constants => true )
1679
+ begin
1680
+ if @begin.kind_of?(Variable) then
1681
+ start = @begin.constant
1682
+ elsif @begin.kind_of?(Expression) then
1683
+ start = eval "#{@begin}"
1684
+ else
1685
+ start = @begin.to_i
1686
+ end
1687
+ if @end.kind_of?(Variable) then
1688
+ e = @end.constant
1689
+ elsif @end.kind_of?(Expression) then
1690
+ e = eval "#{@end}"
1691
+ else
1692
+ e = @end.to_i
1693
+ end
1694
+ if @step.kind_of?(Variable) then
1695
+ step = @step.constant
1696
+ elsif @step.kind_of?(Expression) then
1697
+ step = eval "#{@step}"
1698
+ else
1699
+ step = @step.to_i
1700
+ end
1701
+ raise "Invalid bounds (not constants)!" if not ( start and e and step )
1702
+ rescue Exception => ex
1703
+ if not ( start and e and step ) then
1704
+ BOAST::pop_env( :replace_constants )
1705
+ return self.print(*args) if not ( start and e and step )
1706
+ end
1707
+ end
1708
+ BOAST::pop_env( :replace_constants )
1709
+ range = start..e
1710
+ @iterator.force_replace_constant = true
1711
+ range.step(step) { |i|
1712
+ @iterator.constant = i
1713
+ @block.call(*args)
1714
+ }
1715
+ @iterator.force_replace_constant = false
1716
+ @iterator.constant = nil
1717
+ end
1718
+
1719
+ def print(*args)
1720
+ final = true
1721
+ s=""
1722
+ s += " "*BOAST::get_indent_level if final
1723
+ s += self.to_str
1724
+ BOAST::increment_indent_level
1725
+ BOAST::get_output.puts s if final
1726
+ if @block then
1727
+ s += "\n"
1728
+ @block.call(*args)
1729
+ s += self.close
1730
+ end
1731
+ return s
1732
+ end
1733
+
1734
+ def close(final=true)
1735
+ return self.close_fortran(final) if BOAST::get_lang == FORTRAN
1736
+ return self.close_c(final) if [C, CL, CUDA].include?( BOAST::get_lang )
1737
+ end
1738
+ def close_c(final=true)
1739
+ s = ""
1740
+ BOAST::decrement_indent_level
1741
+ s += " "*BOAST::get_indent_level if final
1742
+ s += "}"
1743
+ BOAST::get_output.puts s if final
1744
+ return s
1745
+ end
1746
+ def close_fortran(final=true)
1747
+ s = ""
1748
+ BOAST::decrement_indent_level
1749
+ s += " "*BOAST::get_indent_level if final
1750
+ s += "enddo"
1751
+ BOAST::get_output.puts s if final
1752
+ return s
1753
+ end
1754
+ end
1755
+ Var = Variable
1756
+ Dim = Dimension
1757
+ Call = FuncCall
1758
+ end
1759
+ ConvolutionGenerator = BOAST