BOAST 1.3.5 → 2.0.0
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.
- 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
|