BOAST 1.3.5 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/BOAST.gemspec +1 -1
- data/LICENSE +13 -1
- data/README.md +62 -13
- data/lib/BOAST.rb +3 -1
- data/lib/BOAST/Language/ARMCPUID_by_name.rb +3752 -0
- data/lib/BOAST/Language/Algorithm.rb +4 -24
- data/lib/BOAST/Language/Architectures.rb +5 -0
- data/lib/BOAST/Language/Arithmetic.rb +38 -5
- data/lib/BOAST/Language/BOAST_OpenCL.rb +7 -8
- data/lib/BOAST/Language/Case.rb +10 -3
- data/lib/BOAST/Language/Config.rb +36 -12
- data/lib/BOAST/Language/ControlStructure.rb +7 -3
- data/lib/BOAST/Language/DataTypes.rb +6 -0
- data/lib/BOAST/Language/Expression.rb +26 -2
- data/lib/BOAST/Language/For.rb +59 -30
- data/lib/BOAST/Language/FuncCall.rb +9 -5
- data/lib/BOAST/Language/Functors.rb +1 -1
- data/lib/BOAST/Language/HighLevelOperators.rb +172 -0
- data/lib/BOAST/Language/If.rb +25 -9
- data/lib/BOAST/Language/Index.rb +5 -5
- data/lib/BOAST/Language/Intrinsics.rb +40 -27
- data/lib/BOAST/Language/OpenMP.rb +1 -0
- data/lib/BOAST/Language/Operators.rb +221 -34
- data/lib/BOAST/Language/Parens.rb +3 -2
- data/lib/BOAST/Language/Procedure.rb +18 -5
- data/lib/BOAST/Language/Slice.rb +176 -44
- data/lib/BOAST/Language/Variable.rb +99 -56
- data/lib/BOAST/Language/While.rb +18 -3
- data/lib/BOAST/Language/{CPUID_by_name.rb → X86CPUID_by_name.rb} +0 -0
- data/lib/BOAST/Optimization/Optimization.rb +2 -0
- data/lib/BOAST/Runtime/AffinityProbe.rb +7 -3
- data/lib/BOAST/Runtime/CKernel.rb +3 -0
- data/lib/BOAST/Runtime/CRuntime.rb +4 -0
- data/lib/BOAST/Runtime/CompiledRuntime.rb +404 -77
- data/lib/BOAST/Runtime/Compilers.rb +44 -18
- data/lib/BOAST/Runtime/Config.rb +9 -0
- data/lib/BOAST/Runtime/EnergyProbe.rb +19 -3
- data/lib/BOAST/Runtime/FFIRuntime.rb +23 -0
- data/lib/BOAST/Runtime/FORTRANRuntime.rb +1 -1
- data/lib/BOAST/Runtime/MAQAO.rb +29 -0
- data/lib/BOAST/Runtime/NonRegression.rb +64 -3
- data/lib/BOAST/Runtime/OpenCLRuntime.rb +16 -6
- data/lib/BOAST/Runtime/Probe.rb +21 -1
- metadata +5 -3
data/lib/BOAST/Language/Index.rb
CHANGED
@@ -37,7 +37,7 @@ module BOAST
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def to_s
|
40
|
-
if get_replace_constants then
|
40
|
+
if get_replace_constants and @source.constant? then
|
41
41
|
begin
|
42
42
|
const = @source.constant
|
43
43
|
indxs = @indexes.reverse
|
@@ -51,7 +51,7 @@ module BOAST
|
|
51
51
|
const = const[ind]
|
52
52
|
}
|
53
53
|
return "#{const}#{@source.type.suffix}"
|
54
|
-
rescue Exception
|
54
|
+
rescue Exception
|
55
55
|
end
|
56
56
|
end
|
57
57
|
return to_s_fortran if lang == FORTRAN
|
@@ -73,13 +73,13 @@ module BOAST
|
|
73
73
|
indexes_dup = []
|
74
74
|
@source.dimension.each_with_index { |d,i|
|
75
75
|
if d.size.nil? and get_array_start != 1 then
|
76
|
-
indexes_dup.push( @indexes[i] - d.start + 1 )
|
76
|
+
indexes_dup.push( (@indexes[i] - d.start + 1).to_s )
|
77
77
|
else
|
78
|
-
indexes_dup.push( @indexes[i] )
|
78
|
+
indexes_dup.push( (@indexes[i]).to_s )
|
79
79
|
end
|
80
80
|
}
|
81
81
|
s = ""
|
82
|
-
s += "#{@source}(#{indexes_dup.join(", ")})"
|
82
|
+
s += "#{@source}(#{@source.vector? ? ":, " : "" }#{indexes_dup.join(", ")})"
|
83
83
|
return s
|
84
84
|
end
|
85
85
|
|
@@ -22,8 +22,10 @@ module BOAST
|
|
22
22
|
|
23
23
|
MODELS = { "native" => native_flags }
|
24
24
|
MODELS.update(X86architectures)
|
25
|
+
MODELS.update(ARMarchitectures)
|
25
26
|
INSTRUCTIONS = {}
|
26
|
-
INSTRUCTIONS
|
27
|
+
INSTRUCTIONS[X86] = X86CPUID_by_name
|
28
|
+
INSTRUCTIONS[ARM] = ARMCPUID_by_name
|
27
29
|
|
28
30
|
class IntrinsicsError < Error
|
29
31
|
end
|
@@ -39,21 +41,24 @@ module BOAST
|
|
39
41
|
CONVERSIONS = Hash::new { |h, k| h[k] = Hash::new { |h2, k2| h2[k2] = {} } }
|
40
42
|
|
41
43
|
def check_coverage
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
instrs = [X86, ARM].collect { |ar|
|
45
|
+
ins = []
|
46
|
+
INTRINSICS[ar].each { |i,v|
|
47
|
+
if i == :CVT then
|
48
|
+
v.each { |type1, h|
|
49
|
+
h.each { |type2, instr|
|
50
|
+
ins.push instr.to_s
|
51
|
+
}
|
52
|
+
}
|
53
|
+
else
|
54
|
+
v.each { |type, instr|
|
47
55
|
ins.push instr.to_s
|
48
56
|
}
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
ins.push instr.to_s
|
53
|
-
}
|
54
|
-
end
|
57
|
+
end
|
58
|
+
}
|
59
|
+
ins - INSTRUCTIONS[ar].keys
|
55
60
|
}
|
56
|
-
return
|
61
|
+
return instrs
|
57
62
|
end
|
58
63
|
|
59
64
|
module_function :check_coverage
|
@@ -65,9 +70,8 @@ module BOAST
|
|
65
70
|
instruction = INTRINSICS[get_architecture][intr_symbol][type]
|
66
71
|
end
|
67
72
|
raise IntrinsicsError, "Unsupported operation #{intr_symbol} for #{type}#{type2 ? " and #{type2}" : ""} on #{get_architecture_name}!" unless instruction
|
68
|
-
return instruction if get_architecture == ARM
|
69
73
|
supported = false
|
70
|
-
INSTRUCTIONS[instruction.to_s].each { |cpuid|
|
74
|
+
INSTRUCTIONS[get_architecture][instruction.to_s].each { |cpuid|
|
71
75
|
if cpuid.kind_of?( Array ) then
|
72
76
|
supported = true if (cpuid - MODELS[get_model.to_s]).empty?
|
73
77
|
else
|
@@ -77,7 +81,7 @@ module BOAST
|
|
77
81
|
# supported = (INSTRUCTIONS[instruction.to_s] & MODELS[get_model.to_s]).size > 0
|
78
82
|
if not supported then
|
79
83
|
required = ""
|
80
|
-
INSTRUCTIONS[instruction.to_s].each { |cpuid|
|
84
|
+
INSTRUCTIONS[get_architecture][instruction.to_s].each { |cpuid|
|
81
85
|
required += " or " if required != ""
|
82
86
|
if cpuid.kind_of?( Array ) then
|
83
87
|
required += "( #{cpuid.join(" and ")} )"
|
@@ -301,7 +305,13 @@ module BOAST
|
|
301
305
|
[:MASK_LOAD, "mask_loadu"], [:MASK_STORE, "mask_storeu"],
|
302
306
|
[:MASK_LOADA, "mask_load"], [:MASK_STOREA, "mask_store"],
|
303
307
|
[:MASKZ_LOAD, "maskz_loadu"],
|
304
|
-
[:MASKZ_LOADA, "maskz_load"]
|
308
|
+
[:MASKZ_LOADA, "maskz_load"],
|
309
|
+
[:MAX, "max"], [:MIN, "min"],
|
310
|
+
[:SQRT, "sqrt"], [:EXP, "exp"], [:LOG, "log"], [:LOG10, "log10"],
|
311
|
+
[:SIN, "sin"], [:COS, "cos"], [:TAN, "tan"],
|
312
|
+
[:SINH, "sinh"], [:COSH, "cosh"], [:TANH, "tanh"],
|
313
|
+
[:ASIN, "asin"], [:ACOS, "acos"], [:ATAN, "atan"],
|
314
|
+
[:ASINH, "asinh"], [:ACOSH, "acosh"], [:ATANH, "atanh"]]
|
305
315
|
instructions.push( [:MASKLOAD, "maskload"], [:MASKSTORE, "maskstore"] ) if vector_size < 512
|
306
316
|
instructions.push( [:ADDSUB, "addsub"] ) if vector_size < 512
|
307
317
|
instructions.each { |cl, ins|
|
@@ -364,14 +374,16 @@ module BOAST
|
|
364
374
|
|
365
375
|
[64, 128].each { |vector_size|
|
366
376
|
q = (vector_size == 128 ? "q" : "")
|
367
|
-
[8, 16, 32
|
377
|
+
scal_sizes = [8, 16, 32]
|
378
|
+
scal_sizes.push 64 if vector_size > 64
|
379
|
+
scal_sizes.each { |size|
|
368
380
|
[:signed, :unsigned].each { |sign|
|
369
381
|
vtype = vector_type_name( :int, size, vector_size, sign )
|
370
382
|
type = type_name_ARM( :int, size, sign )
|
371
383
|
instructions = [[:ADD, "add"], [:SUB, "sub"]]
|
372
384
|
instructions.push( [:MUL, "mul"], [:FMADD, "mla"], [:FNMADD, "mls"] ) if size < 64
|
373
|
-
instructions.push( [:LOAD, "
|
374
|
-
instructions.push( [:STORE, "
|
385
|
+
instructions.push( [:LOAD, "ld1"], [:LOADA, "ld1"] )
|
386
|
+
instructions.push( [:STORE, "st1"], [:STOREA, "st1"] )
|
375
387
|
instructions.each { |cl, ins|
|
376
388
|
INTRINSICS[ARM][cl][vtype] = "v#{ins}#{q}_#{type}".to_sym
|
377
389
|
}
|
@@ -383,13 +395,15 @@ module BOAST
|
|
383
395
|
}
|
384
396
|
}
|
385
397
|
}
|
386
|
-
[32
|
398
|
+
scal_sizes = [32]
|
399
|
+
scal_sizes.push 64 if vector_size > 64
|
400
|
+
scal_sizes.each { |size|
|
387
401
|
vtype = vector_type_name( :float, size, vector_size )
|
388
402
|
type = type_name_ARM( :float, size )
|
389
403
|
[[:ADD, "add"], [:SUB, "sub"], [:MUL, "mul"],
|
390
404
|
[:FMADD, "mla"], [:FNMADD, "mls"],
|
391
|
-
[:LOAD, "
|
392
|
-
[:STORE, "
|
405
|
+
[:LOAD, "ld1"], [:LOADA, "ld1"],
|
406
|
+
[:STORE, "st1"], [:STOREA, "st1"]].each { |cl, ins|
|
393
407
|
INTRINSICS[ARM][cl][vtype] = "v#{ins}#{q}_#{type}".to_sym
|
394
408
|
}
|
395
409
|
[[:SET1, "dup"]].each { |cl, ins|
|
@@ -439,10 +453,9 @@ module BOAST
|
|
439
453
|
cvt_dgraph = RGL::DirectedAdjacencyGraph::new
|
440
454
|
INTRINSICS[arch][:CVT].each { |dest, origs|
|
441
455
|
origs.each { |orig, intrinsic|
|
442
|
-
supported =
|
443
|
-
if
|
444
|
-
|
445
|
-
INSTRUCTIONS[intrinsic.to_s].each { |cpuid|
|
456
|
+
supported = false
|
457
|
+
if MODELS[get_model.to_s] then
|
458
|
+
INSTRUCTIONS[arch][intrinsic.to_s].each { |cpuid|
|
446
459
|
if cpuid.kind_of?( Array ) then
|
447
460
|
supported = true if (cpuid - MODELS[get_model.to_s]).empty?
|
448
461
|
else
|
@@ -15,6 +15,11 @@ module BOAST
|
|
15
15
|
|
16
16
|
def Operator.convert(arg, type)
|
17
17
|
return "#{arg}" if get_vector_name(arg.type) == get_vector_name(type) or lang == CUDA
|
18
|
+
|
19
|
+
if arg.type.vector_length == 1 and type.vector_length > 1 then
|
20
|
+
return "#{Set::new( arg, Variable::new(:dummy, type.class, type.to_hash) )}"
|
21
|
+
end
|
22
|
+
|
18
23
|
return "convert_#{type.decl}( #{arg} )" if lang == CL
|
19
24
|
|
20
25
|
path = get_conversion_path(type, arg.type)
|
@@ -186,23 +191,6 @@ module BOAST
|
|
186
191
|
|
187
192
|
end
|
188
193
|
|
189
|
-
class Affectation < Operator
|
190
|
-
|
191
|
-
def Affectation.string(arg1, arg2, return_type)
|
192
|
-
if arg1.class == Variable and arg1.type.vector_length > 1 then
|
193
|
-
return "#{arg1} = #{Load(arg2, arg1)}"
|
194
|
-
elsif arg2.class == Variable and arg2.type.vector_length > 1 then
|
195
|
-
return "#{Store(arg1, arg2, :store_type => return_type)}"
|
196
|
-
end
|
197
|
-
return basic_usage(arg1, arg2)
|
198
|
-
end
|
199
|
-
|
200
|
-
def Affectation.basic_usage(arg1, arg2)
|
201
|
-
return "#{arg1} = #{arg2}"
|
202
|
-
end
|
203
|
-
|
204
|
-
end
|
205
|
-
|
206
194
|
class Exponentiation < BasicBinaryOperator
|
207
195
|
|
208
196
|
class << self
|
@@ -264,7 +252,7 @@ module BOAST
|
|
264
252
|
|
265
253
|
end
|
266
254
|
|
267
|
-
class
|
255
|
+
class Subtraction < BasicBinaryOperator
|
268
256
|
|
269
257
|
class << self
|
270
258
|
|
@@ -304,6 +292,38 @@ module BOAST
|
|
304
292
|
|
305
293
|
end
|
306
294
|
|
295
|
+
class Min < BasicBinaryOperator
|
296
|
+
|
297
|
+
class << self
|
298
|
+
|
299
|
+
def intr_symbol
|
300
|
+
return :MIN
|
301
|
+
end
|
302
|
+
|
303
|
+
def basic_usage(arg1, arg2)
|
304
|
+
return "min( #{arg1}, #{arg2} )"
|
305
|
+
end
|
306
|
+
|
307
|
+
end
|
308
|
+
|
309
|
+
end
|
310
|
+
|
311
|
+
class Max < BasicBinaryOperator
|
312
|
+
|
313
|
+
class << self
|
314
|
+
|
315
|
+
def intr_symbol
|
316
|
+
return :MAX
|
317
|
+
end
|
318
|
+
|
319
|
+
def basic_usage(arg1, arg2)
|
320
|
+
return "max( #{arg1}, #{arg2} )"
|
321
|
+
end
|
322
|
+
|
323
|
+
end
|
324
|
+
|
325
|
+
end
|
326
|
+
|
307
327
|
class Mask
|
308
328
|
extend Functor
|
309
329
|
|
@@ -388,18 +408,32 @@ module BOAST
|
|
388
408
|
begin
|
389
409
|
instruction = intrinsics(:SET, @return_type.type)
|
390
410
|
raise IntrinsicsError unless instruction
|
391
|
-
|
411
|
+
eff_srcs = @source.collect { |src|
|
412
|
+
eff_src = nil
|
413
|
+
eff_src = src.to_var if src.respond_to?(:to_var)
|
414
|
+
eff_src = src unless eff_src
|
415
|
+
eff_src
|
416
|
+
}
|
417
|
+
return @return_type.copy("#{instruction}( #{eff_srcs.join(", ")} )", DISCARD_OPTIONS)
|
392
418
|
rescue IntrinsicsError
|
393
419
|
instruction = intrinsics(:SET_LANE, @return_type.type)
|
394
420
|
raise IntrinsicsError, "Missing instruction for SET_LANE on #{get_architecture_name}!" unless instruction
|
395
421
|
s = Set(0, @return_type).to_s
|
396
422
|
@source.each_with_index { |v,i|
|
397
|
-
|
423
|
+
eff_src = nil
|
424
|
+
eff_src = v.to_var if v.respond_to?(:to_var)
|
425
|
+
eff_src = v unless eff_src
|
426
|
+
s = "#{instruction}( #{eff_src}, #{s}, #{i} )"
|
398
427
|
}
|
399
428
|
return @return_type.copy(s, DISCARD_OPTIONS)
|
400
429
|
end
|
401
430
|
elsif @source.class != Variable or @source.type.vector_length == 1 then
|
402
|
-
|
431
|
+
eff_src = nil
|
432
|
+
eff_src = @source.to_var if @source.respond_to?(:to_var)
|
433
|
+
eff_src = @source unless eff_src
|
434
|
+
if lang == CL then
|
435
|
+
return @return_type.copy("(#{@return_type.type.decl})( #{eff_src} )", DISCARD_OPTIONS) if lang == CL
|
436
|
+
end
|
403
437
|
if (@source.is_a?(Numeric) and @source == 0) or (@source.class == Variable and @source.constant == 0) then
|
404
438
|
begin
|
405
439
|
instruction = intrinsics(:SETZERO, @return_type.type)
|
@@ -408,12 +442,73 @@ module BOAST
|
|
408
442
|
end
|
409
443
|
end
|
410
444
|
instruction = intrinsics(:SET1, @return_type.type)
|
411
|
-
return @return_type.copy("#{instruction}( #{
|
445
|
+
return @return_type.copy("#{instruction}( #{eff_src} )", DISCARD_OPTIONS)
|
412
446
|
elsif @return_type.type != @source.type
|
413
447
|
return @return_type.copy("#{Operator.convert(@source, @return_type.type)}", DISCARD_OPTIONS)
|
414
448
|
end
|
449
|
+
elsif lang == FORTRAN and @return_type.type.vector_length > 1 then
|
450
|
+
if @source.kind_of?( Array ) then
|
451
|
+
raise OperatorError, "Invalid array length!" unless @source.length == @return_type.type.vector_length
|
452
|
+
return "(/#{@source.join(", ")}/)"
|
453
|
+
end
|
415
454
|
end
|
416
|
-
|
455
|
+
eff_src = nil
|
456
|
+
eff_src = @source.to_var if @source.respond_to?(:to_var)
|
457
|
+
eff_src = @source unless eff_src
|
458
|
+
return @return_type.copy("#{eff_src}", DISCARD_OPTIONS)
|
459
|
+
end
|
460
|
+
|
461
|
+
def to_s
|
462
|
+
return to_var.to_s
|
463
|
+
end
|
464
|
+
|
465
|
+
def pr
|
466
|
+
s=""
|
467
|
+
s += indent
|
468
|
+
s += to_s
|
469
|
+
s += ";" if [C, CL, CUDA].include?( lang )
|
470
|
+
output.puts s
|
471
|
+
return self
|
472
|
+
end
|
473
|
+
|
474
|
+
end
|
475
|
+
|
476
|
+
# @!parse module Functors; functorize Affectation; end
|
477
|
+
class Affectation < Operator
|
478
|
+
extend Functor
|
479
|
+
include Intrinsics
|
480
|
+
include Arithmetic
|
481
|
+
include Inspectable
|
482
|
+
include PrivateStateAccessor
|
483
|
+
|
484
|
+
attr_reader :target
|
485
|
+
attr_reader :source
|
486
|
+
attr_reader :options
|
487
|
+
|
488
|
+
def initialize(target, source, options = {})
|
489
|
+
@target = target
|
490
|
+
@source = source
|
491
|
+
@options = options
|
492
|
+
end
|
493
|
+
|
494
|
+
def type
|
495
|
+
return target.to_var.type
|
496
|
+
end
|
497
|
+
|
498
|
+
def to_var
|
499
|
+
tar = @target
|
500
|
+
tar = @target.to_var if @target.respond_to?(:to_var)
|
501
|
+
src = @source
|
502
|
+
src = @source.to_var if @source.respond_to?(:to_var)
|
503
|
+
if tar.class == Variable and tar.type.vector_length > 1 then
|
504
|
+
return @target.copy("#{@target} = #{Load(@source, @target, @options)}", DISCARD_OPTIONS)
|
505
|
+
elsif src.class == Variable and src.type.vector_length > 1 then
|
506
|
+
r_t, _ = transition(tar, src, Affectation)
|
507
|
+
opts = @options.clone
|
508
|
+
opts[:store_type] = r_t
|
509
|
+
return @target.copy("#{Store(@target, @source, opts)}", DISCARD_OPTIONS)
|
510
|
+
end
|
511
|
+
return tar.copy("#{tar ? tar : @target} = #{src ? src : @source}", DISCARD_OPTIONS)
|
417
512
|
end
|
418
513
|
|
419
514
|
def to_s
|
@@ -431,6 +526,7 @@ module BOAST
|
|
431
526
|
|
432
527
|
end
|
433
528
|
|
529
|
+
|
434
530
|
# @!parse module Functors; functorize Load; end
|
435
531
|
class Load < Operator
|
436
532
|
extend Functor
|
@@ -460,10 +556,11 @@ module BOAST
|
|
460
556
|
if @source.kind_of?(Array) then
|
461
557
|
return Set(@source, @return_type).to_var
|
462
558
|
elsif @source.class == Variable or @source.respond_to?(:to_var) then
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
559
|
+
src_var = source.to_var
|
560
|
+
if src_var.type == @return_type.type then
|
561
|
+
return src_var
|
562
|
+
elsif src_var.type.vector_length == 1 then
|
563
|
+
a2 = "#{src_var}"
|
467
564
|
if a2[0] != "*" then
|
468
565
|
a2 = "&" + a2
|
469
566
|
else
|
@@ -481,7 +578,7 @@ module BOAST
|
|
481
578
|
sym += "Z" if @zero
|
482
579
|
sym += "_"
|
483
580
|
end
|
484
|
-
if
|
581
|
+
if src_var.alignment and @return_type.type.total_size and ( src_var.alignment % @return_type.type.total_size ) == 0 then
|
485
582
|
sym += "LOADA"
|
486
583
|
else
|
487
584
|
sym += "LOAD"
|
@@ -493,7 +590,17 @@ module BOAST
|
|
493
590
|
end
|
494
591
|
return @return_type.copy("#{instruction}( #{a2} )", DISCARD_OPTIONS)
|
495
592
|
else
|
496
|
-
return @return_type.copy("#{Operator.convert(
|
593
|
+
return @return_type.copy("#{Operator.convert(src_var, @return_type.type)}", DISCARD_OPTIONS)
|
594
|
+
end
|
595
|
+
end
|
596
|
+
elsif lang == FORTRAN then
|
597
|
+
if @source.kind_of?(Array) then
|
598
|
+
return Set(@source, @return_type).to_var
|
599
|
+
elsif @source.class == Variable or @source.respond_to?(:to_var) then
|
600
|
+
if @source.to_var.type == @return_type.type then
|
601
|
+
return @source.to_var
|
602
|
+
elsif @source.kind_of?(Index) and @return_type.type.vector_length > 1 then
|
603
|
+
return @return_type.copy("#{Slice::new(@source.source, [@source.indexes[0], @source.indexes[0] + @return_type.type.vector_length - 1], *@source.indexes[1..-1])}", DISCARD_OPTIONS)
|
497
604
|
end
|
498
605
|
end
|
499
606
|
end
|
@@ -601,6 +708,9 @@ module BOAST
|
|
601
708
|
end
|
602
709
|
|
603
710
|
def to_s
|
711
|
+
if @store_type.type == @dest.type then
|
712
|
+
return "#{@dest} = #{@source}"
|
713
|
+
end
|
604
714
|
if lang == C or lang == CL then
|
605
715
|
dst = "#{@dest}"
|
606
716
|
if dst[0] != "*" then
|
@@ -626,8 +736,12 @@ module BOAST
|
|
626
736
|
p_type = type if get_architecture == X86 and type.kind_of?(Int)
|
627
737
|
return "#{instruction}( (#{p_type.decl} * ) #{dst}, (#{mask.value.type.decl})#{mask}, #{@source} )" if mask and not mask.full?
|
628
738
|
return "#{instruction}( (#{p_type.decl} * ) #{dst}, #{@source} )"
|
739
|
+
elsif lang == FORTRAN
|
740
|
+
if @store_type.type.vector_length > 1 and @dest.kind_of?(Index) then
|
741
|
+
return "#{Slice::new(@dest.source, [@dest.indexes[0], @dest.indexes[0] + @store_type.type.vector_length - 1], *@dest.indexes[1..-1])} = #{@source}"
|
742
|
+
end
|
629
743
|
end
|
630
|
-
return
|
744
|
+
return "#{@dest} = #{@source}"
|
631
745
|
end
|
632
746
|
|
633
747
|
def pr
|
@@ -719,8 +833,7 @@ module BOAST
|
|
719
833
|
@operand1 = a
|
720
834
|
@operand2 = b
|
721
835
|
@operand3 = c
|
722
|
-
@return_type =
|
723
|
-
@return_type = @operand3.to_var unless @return_type
|
836
|
+
@return_type = @operand3.to_var
|
724
837
|
end
|
725
838
|
|
726
839
|
def convert_operand(op)
|
@@ -790,8 +903,7 @@ module BOAST
|
|
790
903
|
@operand1 = a
|
791
904
|
@operand2 = b
|
792
905
|
@operand3 = c
|
793
|
-
@return_type =
|
794
|
-
@return_type = @operand3.to_var unless @return_type
|
906
|
+
@return_type = @operand3.to_var
|
795
907
|
end
|
796
908
|
|
797
909
|
def convert_operand(op)
|
@@ -845,6 +957,81 @@ module BOAST
|
|
845
957
|
|
846
958
|
end
|
847
959
|
|
960
|
+
class Modulo < Operator
|
961
|
+
extend Functor
|
962
|
+
include Arithmetic
|
963
|
+
include Inspectable
|
964
|
+
include PrivateStateAccessor
|
965
|
+
include TypeTransition
|
966
|
+
|
967
|
+
attr_reader :operand1
|
968
|
+
attr_reader :operand2
|
969
|
+
attr_reader :return_type
|
970
|
+
|
971
|
+
def initialize(x,y)
|
972
|
+
@operand1 = x
|
973
|
+
@operand2 = y
|
974
|
+
op1, op2 = op_to_var
|
975
|
+
@return_type, _ = transition(op1, op2, Modulo)
|
976
|
+
end
|
977
|
+
|
978
|
+
def to_s
|
979
|
+
return to_s_fortran if lang == FORTRAN
|
980
|
+
return to_s_c if [C, CL, CUDA].include?( lang )
|
981
|
+
end
|
982
|
+
|
983
|
+
def pr
|
984
|
+
s=""
|
985
|
+
s += indent
|
986
|
+
s += to_s
|
987
|
+
s += ";" if [C, CL, CUDA].include?( lang )
|
988
|
+
output.puts s
|
989
|
+
return self
|
990
|
+
end
|
991
|
+
|
992
|
+
def to_var
|
993
|
+
if @return_type then
|
994
|
+
return @return_type.copy( to_s, DISCARD_OPTIONS )
|
995
|
+
else
|
996
|
+
return Variable::new( to_s, get_default_type )
|
997
|
+
end
|
998
|
+
end
|
999
|
+
|
1000
|
+
private
|
1001
|
+
|
1002
|
+
def to_s_fortran
|
1003
|
+
op1, op2 = op_to_var
|
1004
|
+
if @return_type and @return_type.type.kind_of?(Real) and ( not op1.type.kind_of?(Real) or not op2.type.kind_of?(Real) ) then
|
1005
|
+
return "modulo(real(#{op1}, #{@return_type.type.size}), #{op2})" if not op1.type.kind_of?(Real)
|
1006
|
+
return "modulo(#{op1}, real(#{op2}, #{@return_type.type.size}))"
|
1007
|
+
else
|
1008
|
+
return "modulo(#{op1}, #{op2})"
|
1009
|
+
end
|
1010
|
+
end
|
1011
|
+
|
1012
|
+
def to_s_c
|
1013
|
+
op1, op2 = op_to_var
|
1014
|
+
if @return_type and @return_type.type.kind_of?(Real) then
|
1015
|
+
if @return_type.type.size <= 4 then
|
1016
|
+
return "((#{op1} < 0) ^ (#{op2} < 0) ? fmodf(#{op1}, #{op2}) + #{op2} : fmodf(#{op1}, #{op2}));"
|
1017
|
+
else
|
1018
|
+
return "((#{op1} < 0) ^ (#{op2} < 0) ? fmod(#{op1}, #{op2}) + #{op2} : fmod(#{op1}, #{op2}))"
|
1019
|
+
end
|
1020
|
+
else
|
1021
|
+
return "((#{op1} < 0) ^ (#{op2} < 0) ? (#{op1} % #{op2}) + #{op2} : #{op1} % #{op2})"
|
1022
|
+
end
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
def op_to_var
|
1026
|
+
op1 = @operand1.respond_to?(:to_var) ? @operand1.to_var : @operand1
|
1027
|
+
op1 = @operand1 unless op1
|
1028
|
+
op2 = @operand2.respond_to?(:to_var) ? @operand2.to_var : @operand2
|
1029
|
+
op2 = @operand2 unless op2
|
1030
|
+
return [op1, op2]
|
1031
|
+
end
|
1032
|
+
|
1033
|
+
end
|
1034
|
+
|
848
1035
|
# @!parse module Functors; functorize Ternary; end
|
849
1036
|
class Ternary
|
850
1037
|
extend Functor
|