BOAST 0.1

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.
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