modular icon indicating copy to clipboard operation
modular copied to clipboard

[BUG]: Incorrect output of `Math.pow` with negative `Int` exponent

Open mojodojodev opened this issue 2 years ago • 7 comments

Bug description

Incorrectly calculates the result when SIMD is raised to the power of a negative Int, producing accurate results only when both operands are SIMD.

Steps to reproduce

For example this works when you use the SIMD version for the rhs argument:

from DType import DType
from Math import pow
let x = Float64(4.0)
let res = pow(x, Float64(-1.0))
print(res)
0.25

But using an Int in the rhs will result in the incorrect output:

from DType import DType
from Math import pow
let x = Float64(4.0)
let res = pow(x, -1)
print(res)
1

And the shorthand also produces incorrect results:

let x = float64(4.0)
print(x**-1)
1

System information

11:hugetlb:/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod3c39d252_9da9_4a44_afb3_a4a9d291dbff.slice/cri-containerd-7b08c194ddc8e2965257590ac4ab2f1fe2170ad67c30d825c477b486b0b90d39.scope
10:devices:/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod3c39d252_9da9_4a44_afb3_a4a9d291dbff.slice/cri-containerd-7b08c194ddc8e2965257590ac4ab2f1fe2170ad67c30d825c477b486b0b90d39.scope
9:pids:/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod3c39d252_9da9_4a44_afb3_a4a9d291dbff.slice/cri-containerd-7b08c194ddc8e2965257590ac4ab2f1fe2170ad67c30d825c477b486b0b90d39.scope
8:blkio:/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod3c39d252_9da9_4a44_afb3_a4a9d291dbff.slice/cri-containerd-7b08c194ddc8e2965257590ac4ab2f1fe2170ad67c30d825c477b486b0b90d39.scope
7:cpuset:/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod3c39d252_9da9_4a44_afb3_a4a9d291dbff.slice/cri-containerd-7b08c194ddc8e2965257590ac4ab2f1fe2170ad67c30d825c477b486b0b90d39.scope
6:perf_event:/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod3c39d252_9da9_4a44_afb3_a4a9d291dbff.slice/cri-containerd-7b08c194ddc8e2965257590ac4ab2f1fe2170ad67c30d825c477b486b0b90d39.scope
5:cpu,cpuacct:/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod3c39d252_9da9_4a44_afb3_a4a9d291dbff.slice/cri-containerd-7b08c194ddc8e2965257590ac4ab2f1fe2170ad67c30d825c477b486b0b90d39.scope
4:net_cls,net_prio:/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod3c39d252_9da9_4a44_afb3_a4a9d291dbff.slice/cri-containerd-7b08c194ddc8e2965257590ac4ab2f1fe2170ad67c30d825c477b486b0b90d39.scope
3:memory:/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod3c39d252_9da9_4a44_afb3_a4a9d291dbff.slice/cri-containerd-7b08c194ddc8e2965257590ac4ab2f1fe2170ad67c30d825c477b486b0b90d39.scope
2:freezer:/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod3c39d252_9da9_4a44_afb3_a4a9d291dbff.slice/cri-containerd-7b08c194ddc8e2965257590ac4ab2f1fe2170ad67c30d825c477b486b0b90d39.scope
1:name=systemd:/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod3c39d252_9da9_4a44_afb3_a4a9d291dbff.slice/cri-containerd-7b08c194ddc8e2965257590ac4ab2f1fe2170ad67c30d825c477b486b0b90d39.scope
0::/

mojodojodev avatar Jul 15 '23 02:07 mojodojodev

@abduld FYI

Mogball avatar Jul 17 '23 18:07 Mogball

Thanks for reporting. One question is handling the negative power on integral values.

abduld avatar Jul 17 '23 18:07 abduld

I also don't know what the standard approach here is for "powi" operations, seems like a weird thing to handle given roots typically produce fractional results. Are there examples in other languages that work this way?

lattner avatar Jul 17 '23 19:07 lattner

Are there examples in other languages that work this way?

@lattner In Rust you have powi and powf for floats, for the integer version e.g.:

let f: f64 = 4.0;
f.powi(-1)

The source code is:

/// Raises an `f64` to an integer power.
///
/// The stabilized version of this intrinsic is
/// [`f64::powi`](../../std/primitive.f64.html#method.powi)
#[rustc_nounwind]
pub fn powif64(a: f64, x: i32) -> f64;

The intrinsic is llvm.powi.f64:

‘llvm.powi.*’ Intrinsic Docs

Syntax

This is an overloaded intrinsic. You can use llvm.powi on any floating-point or vector of floating-point type. Not all targets support all types however.

Generally, the only supported type for the exponent is the one matching with the C type int.

declare float     @llvm.powi.f32.i32(float  %Val, i32 %power)
declare double    @llvm.powi.f64.i16(double %Val, i16 %power)
declare x86_fp80  @llvm.powi.f80.i32(x86_fp80  %Val, i32 %power)
declare fp128     @llvm.powi.f128.i32(fp128 %Val, i32 %power)
declare ppc_fp128 @llvm.powi.ppcf128.i32(ppc_fp128  %Val, i32 %power)

Overview

The ‘llvm.powi.*’ intrinsics return the first operand raised to the specified (positive or negative) power. The order of evaluation of multiplications is not defined. When a vector of floating-point type is used, the second argument remains a scalar integer value.

Arguments

The second argument is an integer power, and the first is a value to raise to that power.

Semantics

This function returns the first value raised to the second power with an unspecified sequence of rounding operations.

mojodojodev avatar Jul 17 '23 22:07 mojodojodev

And integer types can't be raised to a negative value in Rust as it expects a u32:

image

mojodojodev avatar Jul 17 '23 23:07 mojodojodev

FYI @abduld

JoeLoser avatar Feb 28 '24 04:02 JoeLoser

It appears at some point this issue was resolved. Granted powi with a negative exponent returning 0 is still odd in my opinion.

fn main():
    var x = Float64(4.0)
    var res = x ** -1
    print(res) # 0.25
    x = Float64(4.0)
    res = x ** Float64(-1)
    print(res) # 0.25
    var y = Int64(4)
    var r = y ** -1
    print(r) # 0

bgreni avatar May 04 '24 03:05 bgreni

Closing as completed, it works now

jackos avatar Jun 18 '24 18:06 jackos