exaloop / exaloop/codon

[GPU] complex `sin` op results `nan`

Open
#818 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
16.8k
Forks
603
Avg merge
4d 23h
Merged PRs (30d)
6

Description

### Summary

This issue appears to be a partial manifestation of #781, the uninitialized GV issue.

### MRE
```python
import cmath
import gpu

@gpu.kernel
def kernel(xs, out_real, out_imag):
z = cmath.sin(xs[0])
out_real[0] = z.real
out_imag[0] = z.imag

x = complex(0.5, 0.25)
cpu = cmath.sin(x)
out_real = [0.0]
out_imag = [0.0]

kernel([x], out_real, out_imag, grid=1, block=1)
gpu_result = complex(out_real[0], out_imag[0])

print("input:", x)
print("CPU cmath.sin:", cpu)
print("GPU cmath.sin:", gpu_result)
```

### results
```bash
$ codon run -release mre_complex_sin.codon
input: (0.5+0.25j)
CPU cmath.sin: (0.494486+0.221688j)
GPU cmath.sin: (nan+nanj)
```

### Root Cause
For complex values, `cmath.sin` is not lowered to the primitive `sin(float)` operation directly.

Instead, it is evaluated using the `Euler-based` complex formula:
```
For complex var C = a + bi
sin(C) = sin(a) * cosh(b) + i * cos(a) * sinh(b)
```
The CPU implementation appears to compute this correctly, while the GPU version returns `nan`.

In `cmath.codon`, the complex implementation uses GV-backed constants/functions:
```
if math.fabs(z.real) > _CM_LOG_LARGE_DOUBLE:
x_minus_one = z.real - math.copysign(1., z.real)
r_real = math.cos(z.imag) * math.sinh(x_minus_one) * e
r_imag = math.sin(z.imag) * math.cosh(x_minus_one) * e
else:
r_real = math.cos(z.imag) * math.sinh(z.real)
r_imag = math.sin(z.imag) * math.cosh(z.real)
```

As discussed in #781, this seems likely to be caused by the `uninitialized GV issue`.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.