diff --git a/spec/std/crystal/compiler_rt/powidf2_spec.cr b/spec/std/crystal/compiler_rt/powidf2_spec.cr new file mode 100644 index 000000000000..832c7a4bfa69 --- /dev/null +++ b/spec/std/crystal/compiler_rt/powidf2_spec.cr @@ -0,0 +1,94 @@ +require "spec" +require "crystal/compiler_rt/pow" + +# Ported from https://github.com/llvm/llvm-project/blob/2e9df860468425645dcd1b241c5dbf76c072e314/compiler-rt/test/builtins/Unit/powidf2_test.c + +it ".__powidf2" do + __powidf2(0, 0).should eq 1 + __powidf2(1, 0).should eq 1 + __powidf2(1.5, 0).should eq 1 + __powidf2(2, 0).should eq 1 + __powidf2(Float64::INFINITY, 0).should eq 1 + __powidf2(-0.0, 0).should eq 1 + __powidf2(-1, 0).should eq 1 + __powidf2(-1.5, 0).should eq 1 + __powidf2(-2, 0).should eq 1 + __powidf2(-Float64::INFINITY, 0).should eq 1 + __powidf2(0, 1).should eq 0 + __powidf2(0, 2).should eq 0 + __powidf2(0, 3).should eq 0 + __powidf2(0, 4).should eq 0 + __powidf2(0, Int32::MAX - 1).should eq 0 + __powidf2(0, Int32::MAX).should eq 0 + __powidf2(-0.0, 1).should eq -0.0 + __powidf2(-0.0, 2).should eq 0 + __powidf2(-0.0, 3).should eq -0.0 + __powidf2(-0.0, 4).should eq 0 + __powidf2(-0.0, Int32::MAX - 1).should eq 0 + __powidf2(-0.0, Int32::MAX).should eq -0.0 + __powidf2(1, 1).should eq 1 + __powidf2(1, 2).should eq 1 + __powidf2(1, 3).should eq 1 + __powidf2(1, 4).should eq 1 + __powidf2(1, Int32::MAX - 1).should eq 1 + __powidf2(1, Int32::MAX).should eq 1 + __powidf2(Float64::INFINITY, 1).should eq Float64::INFINITY + __powidf2(Float64::INFINITY, 2).should eq Float64::INFINITY + __powidf2(Float64::INFINITY, 3).should eq Float64::INFINITY + __powidf2(Float64::INFINITY, 4).should eq Float64::INFINITY + __powidf2(Float64::INFINITY, Int32::MAX - 1).should eq Float64::INFINITY + __powidf2(Float64::INFINITY, Int32::MAX).should eq Float64::INFINITY + __powidf2(-Float64::INFINITY, 1).should eq -Float64::INFINITY + __powidf2(-Float64::INFINITY, 2).should eq Float64::INFINITY + __powidf2(-Float64::INFINITY, 3).should eq -Float64::INFINITY + __powidf2(-Float64::INFINITY, 4).should eq Float64::INFINITY + __powidf2(-Float64::INFINITY, Int32::MAX - 1).should eq Float64::INFINITY + __powidf2(-Float64::INFINITY, Int32::MAX).should eq -Float64::INFINITY + __powidf2(0, -1).should eq Float64::INFINITY + __powidf2(0, -2).should eq Float64::INFINITY + __powidf2(0, -3).should eq Float64::INFINITY + __powidf2(0, -4).should eq Float64::INFINITY + __powidf2(0, Int32::MIN + 2).should eq Float64::INFINITY + __powidf2(0, Int32::MIN + 1).should eq Float64::INFINITY + __powidf2(0, Int32::MIN).should eq Float64::INFINITY + __powidf2(-0.0, -1).should eq -Float64::INFINITY + __powidf2(-0.0, -2).should eq Float64::INFINITY + __powidf2(-0.0, -3).should eq -Float64::INFINITY + __powidf2(-0.0, -4).should eq Float64::INFINITY + __powidf2(-0.0, Int32::MIN + 2).should eq Float64::INFINITY + __powidf2(-0.0, Int32::MIN + 1).should eq -Float64::INFINITY + __powidf2(-0.0, Int32::MIN).should eq Float64::INFINITY + __powidf2(1, -1).should eq 1 + __powidf2(1, -2).should eq 1 + __powidf2(1, -3).should eq 1 + __powidf2(1, -4).should eq 1 + __powidf2(1, Int32::MIN + 2).should eq 1 + __powidf2(1, Int32::MIN + 1).should eq 1 + __powidf2(1, Int32::MIN).should eq 1 + __powidf2(Float64::INFINITY, -1).should eq 0 + __powidf2(Float64::INFINITY, -2).should eq 0 + __powidf2(Float64::INFINITY, -3).should eq 0 + __powidf2(Float64::INFINITY, -4).should eq 0 + __powidf2(Float64::INFINITY, Int32::MIN + 2).should eq 0 + __powidf2(Float64::INFINITY, Int32::MIN + 1).should eq 0 + __powidf2(Float64::INFINITY, Int32::MIN).should eq 0 + __powidf2(-Float64::INFINITY, -1).should eq -0.0 + __powidf2(-Float64::INFINITY, -2).should eq 0 + __powidf2(-Float64::INFINITY, -3).should eq -0.0 + __powidf2(-Float64::INFINITY, -4).should eq 0 + __powidf2(-Float64::INFINITY, Int32::MIN + 2).should eq 0 + __powidf2(-Float64::INFINITY, Int32::MIN + 1).should eq -0.0 + __powidf2(-Float64::INFINITY, Int32::MIN).should eq 0 + __powidf2(2, 10).should eq 1024.0 + __powidf2(-2, 10).should eq 1024.0 + __powidf2(2, -10).should eq 1/1024.0 + __powidf2(-2, -10).should eq 1/1024.0 + __powidf2(2, 19).should eq 524288.0 + __powidf2(-2, 19).should eq -524288.0 + __powidf2(2, -19).should eq 1/524288.0 + __powidf2(-2, -19).should eq -1/524288.0 + __powidf2(2, 31).should eq 2147483648.0 + __powidf2(-2, 31).should eq -2147483648.0 + __powidf2(2, -31).should eq 1/2147483648.0 + __powidf2(-2, -31).should eq -1/2147483648.0 +end diff --git a/spec/std/crystal/compiler_rt/powisf2_spec.cr b/spec/std/crystal/compiler_rt/powisf2_spec.cr new file mode 100644 index 000000000000..aaad225be2d2 --- /dev/null +++ b/spec/std/crystal/compiler_rt/powisf2_spec.cr @@ -0,0 +1,94 @@ +require "spec" +require "crystal/compiler_rt/pow" + +# Ported from https://github.com/llvm/llvm-project/blob/2e9df860468425645dcd1b241c5dbf76c072e314/compiler-rt/test/builtins/Unit/powisf2_test.c + +it ".__powisf2" do + __powisf2(0, 0).should eq 1 + __powisf2(1, 0).should eq 1 + __powisf2(1.5, 0).should eq 1 + __powisf2(2, 0).should eq 1 + __powisf2(Float32::INFINITY, 0).should eq 1 + __powisf2(-0.0, 0).should eq 1 + __powisf2(-1, 0).should eq 1 + __powisf2(-1.5, 0).should eq 1 + __powisf2(-2, 0).should eq 1 + __powisf2(-Float32::INFINITY, 0).should eq 1 + __powisf2(0, 1).should eq 0 + __powisf2(0, 2).should eq 0 + __powisf2(0, 3).should eq 0 + __powisf2(0, 4).should eq 0 + __powisf2(0, Int32::MAX - 1).should eq 0 + __powisf2(0, Int32::MAX).should eq 0 + __powisf2(-0.0, 1).should eq -0.0 + __powisf2(-0.0, 2).should eq 0 + __powisf2(-0.0, 3).should eq -0.0 + __powisf2(-0.0, 4).should eq 0 + __powisf2(-0.0, Int32::MAX - 1).should eq 0 + __powisf2(-0.0, Int32::MAX).should eq -0.0 + __powisf2(1, 1).should eq 1 + __powisf2(1, 2).should eq 1 + __powisf2(1, 3).should eq 1 + __powisf2(1, 4).should eq 1 + __powisf2(1, Int32::MAX - 1).should eq 1 + __powisf2(1, Int32::MAX).should eq 1 + __powisf2(Float32::INFINITY, 1).should eq Float32::INFINITY + __powisf2(Float32::INFINITY, 2).should eq Float32::INFINITY + __powisf2(Float32::INFINITY, 3).should eq Float32::INFINITY + __powisf2(Float32::INFINITY, 4).should eq Float32::INFINITY + __powisf2(Float32::INFINITY, Int32::MAX - 1).should eq Float32::INFINITY + __powisf2(Float32::INFINITY, Int32::MAX).should eq Float32::INFINITY + __powisf2(-Float32::INFINITY, 1).should eq -Float32::INFINITY + __powisf2(-Float32::INFINITY, 2).should eq Float32::INFINITY + __powisf2(-Float32::INFINITY, 3).should eq -Float32::INFINITY + __powisf2(-Float32::INFINITY, 4).should eq Float32::INFINITY + __powisf2(-Float32::INFINITY, Int32::MAX - 1).should eq Float32::INFINITY + __powisf2(-Float32::INFINITY, Int32::MAX).should eq -Float32::INFINITY + __powisf2(0, -1).should eq Float32::INFINITY + __powisf2(0, -2).should eq Float32::INFINITY + __powisf2(0, -3).should eq Float32::INFINITY + __powisf2(0, -4).should eq Float32::INFINITY + __powisf2(0, Int32::MIN + 2).should eq Float32::INFINITY + __powisf2(0, Int32::MIN + 1).should eq Float32::INFINITY + __powisf2(0, Int32::MIN).should eq Float32::INFINITY + __powisf2(-0.0, -1).should eq -Float32::INFINITY + __powisf2(-0.0, -2).should eq Float32::INFINITY + __powisf2(-0.0, -3).should eq -Float32::INFINITY + __powisf2(-0.0, -4).should eq Float32::INFINITY + __powisf2(-0.0, Int32::MIN + 2).should eq Float32::INFINITY + __powisf2(-0.0, Int32::MIN + 1).should eq -Float32::INFINITY + __powisf2(-0.0, Int32::MIN).should eq Float32::INFINITY + __powisf2(1, -1).should eq 1 + __powisf2(1, -2).should eq 1 + __powisf2(1, -3).should eq 1 + __powisf2(1, -4).should eq 1 + __powisf2(1, Int32::MIN + 2).should eq 1 + __powisf2(1, Int32::MIN + 1).should eq 1 + __powisf2(1, Int32::MIN).should eq 1 + __powisf2(Float32::INFINITY, -1).should eq 0 + __powisf2(Float32::INFINITY, -2).should eq 0 + __powisf2(Float32::INFINITY, -3).should eq 0 + __powisf2(Float32::INFINITY, -4).should eq 0 + __powisf2(Float32::INFINITY, Int32::MIN + 2).should eq 0 + __powisf2(Float32::INFINITY, Int32::MIN + 1).should eq 0 + __powisf2(Float32::INFINITY, Int32::MIN).should eq 0 + __powisf2(-Float32::INFINITY, -1).should eq -0.0 + __powisf2(-Float32::INFINITY, -2).should eq 0 + __powisf2(-Float32::INFINITY, -3).should eq -0.0 + __powisf2(-Float32::INFINITY, -4).should eq 0 + __powisf2(-Float32::INFINITY, Int32::MIN + 2).should eq 0 + __powisf2(-Float32::INFINITY, Int32::MIN + 1).should eq -0.0 + __powisf2(-Float32::INFINITY, Int32::MIN).should eq 0 + __powisf2(2, 10).should eq 1024.0 + __powisf2(-2, 10).should eq 1024.0 + __powisf2(2, -10).should eq 1/1024.0 + __powisf2(-2, -10).should eq 1/1024.0 + __powisf2(2, 19).should eq 524288.0 + __powisf2(-2, 19).should eq -524288.0 + __powisf2(2, -19).should eq 1/524288.0 + __powisf2(-2, -19).should eq -1/524288.0 + __powisf2(2, 31).should eq 2147483648.0 + __powisf2(-2, 31).should eq -2147483648.0 + __powisf2(2, -31).should eq 1/2147483648.0 + __powisf2(-2, -31).should eq -1/2147483648.0 +end diff --git a/src/crystal/compiler_rt.cr b/src/crystal/compiler_rt.cr index b96a61e9fe1f..e1681dac4186 100644 --- a/src/crystal/compiler_rt.cr +++ b/src/crystal/compiler_rt.cr @@ -11,8 +11,11 @@ require "./compiler_rt/divmod128.cr" {% end %} {% if flag?(:wasm32) %} - # __ashlti3, __ashrti3 and __lshrti3 were only missing on wasm32 + # __ashlti3, __ashrti3 and __lshrti3 are missing on wasm32 require "./compiler_rt/shift.cr" + + # __powisf2 and __powidf2 are missing on wasm32 + require "./compiler_rt/pow.cr" {% end %} {% if flag?(:win32) && flag?(:bits64) %} diff --git a/src/crystal/compiler_rt/pow.cr b/src/crystal/compiler_rt/pow.cr new file mode 100644 index 000000000000..dcbc29cf3211 --- /dev/null +++ b/src/crystal/compiler_rt/pow.cr @@ -0,0 +1,20 @@ +private macro __pow_impl(name, one, float_type) + # :nodoc: + # Ported from https://github.com/llvm/llvm-project/blob/2e9df860468425645dcd1b241c5dbf76c072e314/compiler-rt/lib/builtins + fun {{name}}(a : {{float_type}}, b : Int32) : {{float_type}} + recip = b < 0 + r = {{one}} + + loop do + r *= a if b & 1 != 0 + b = b.unsafe_div 2 + break if b == 0 + a *= a + end + + recip ? 1 / r : r + end +end + +__pow_impl(__powisf2, 1f32, Float32) +__pow_impl(__powidf2, 1f64, Float64)