mratsim / Arraymancer

A fast, ergonomic and portable tensor library in Nim with a deep learning focus for CPU, GPU and embedded devices via OpenMP, Cuda and OpenCL backends
https://mratsim.github.io/Arraymancer/
Apache License 2.0
1.34k stars 95 forks source link

Multiply complex tensors with float scalars and vice versa #481

Open cycomanic opened 3 years ago

cycomanic commented 3 years ago

I'm trying to use nim and arraymancer for a scientific project (and teach myself nim in the process). I stumbled across some inconsistency and I'm not sure if this is intentional (and if it is why it is like that).

Essentially I'm trying to multiply a float tensor with a complex number to generate at complex tensor or multiply a complex tensor with a float scalar, both of these fail with a type mismatch error, while multiplying float and complex scalars seems to be valid. Is this intentional? I know I can work around this by casting, but it becomes cumbersome very quickly.

Minimal test case for illustration:

import math, arraymancer, sequtils, complex, sugar

const I = complex64(0,1)

var
  N : int = 2^10
  tmax : float
  x : Complex[float64]
  t = newTensor[float]([N])
  g = newTensor[Complex[float64]]([N])
  gg = newTensor[Complex[float64]]([N])

tmax = 10
t = arange(0.0, tmax)
g = I * t  # does not work
g = I * t.astype(Complex[float64]) # works
x = tmax*I  # works
gg  = g * tmax # does not work
mratsim commented 3 years ago

It's a missing broadcast.

It should be easy to add, only same type broadcast are configured at the moment. https://github.com/mratsim/Arraymancer/blob/bdcdfe13e47d3f6e0c5247e16640e45982b83ecc/src/arraymancer/tensor/operators_broadcasted.nim#L97-L139

alifarazz commented 3 years ago

It's a missing broadcast.

It should be easy to add, only same type broadcast are configured at the moment.

https://github.com/mratsim/Arraymancer/blob/bdcdfe13e47d3f6e0c5247e16640e45982b83ecc/src/arraymancer/tensor/operators_broadcasted.nim#L97-L139

I added the missing broadcasts that I thought you meant. Though they don't seem to help; the same error still persists and compiling it fails.


Alternatively, I tracked down the source code for the * operator in line g = I * t. It's https://github.com/mratsim/Arraymancer/blob/9a575de9e56fe3f5c10a5315765f5ded0332c44b/src/arraymancer/tensor/operators_blas_l1.nim#L67-L70 and https://github.com/mratsim/Arraymancer/blob/9a575de9e56fe3f5c10a5315765f5ded0332c44b/src/arraymancer/tensor/operators_blas_l1.nim#L72-L74

I hacked together a horrible solution with just getting it to compile as my goal. It does compile, but I'm certain there's a much better way of doing this. https://github.com/alifarazz/Arraymancer/blob/37148f36b53e916ac5c00353c3d72a3d3de46b0f/src/arraymancer/tensor/operators_blas_l1.nim#L72-L76