Repository: pytorch
Issue: New dtype ComplexPolarFloat (phasor)
Labels: low priority,triaged,module: complex,enhancement

## 🚀 Feature
New ScalarType::ComplexPolarFloat and c10::complex_polar C++ type that would allow expressing complex numbers with theirs magnitudes and angles. Original idea comes from @dylanbespalko comments on #35563. 

## Motivation
Multiplication and division is much simpler and faster for complex numbers in polar form. This is balanced though by slower addition and subtraction in this form. Overall I think it might be good to give users option to choose between different forms and letting them decide what is best for them.

## Pitch
Similar dtype to existing ComplexFloat but for complex number in polar form. And similar to a `c10::complex` from a #35524 `c10::complex_polar`.

## Alternatives

I guess alternative is to just ignore and have only standard complex dtypes.

## Additional context
I have run some benchmarks locally.

Standard multiplication of complex numbers:
```
# ----------------------------------------
# PyTorch/Caffe2 Operator Micro-benchmarks
# ----------------------------------------
# Tag : long

# Benchmarking PyTorch: mul
# Mode: Eager
# Name: mul_M32_N2048_dtypetorch.complex64
# Input: M: 32, N: 2048, dtype: torch.complex64
Forward Execution Time (us) : 35.701

# Benchmarking PyTorch: mul
# Mode: Eager
# Name: mul_M32_N2048_dtypetorch.complex128
# Input: M: 32, N: 2048, dtype: torch.complex128
Forward Execution Time (us) : 101.595

# Benchmarking PyTorch: mul
# Mode: Eager
# Name: mul_M32_N512_dtypetorch.complex64
# Input: M: 32, N: 512, dtype: torch.complex64
Forward Execution Time (us) : 11.781

# Benchmarking PyTorch: mul
# Mode: Eager
# Name: mul_M32_N512_dtypetorch.complex128
# Input: M: 32, N: 512, dtype: torch.complex128
Forward Execution Time (us) : 19.879

# Benchmarking PyTorch: mul
# Mode: Eager
# Name: mul_M32_N128_dtypetorch.complex64
# Input: M: 32, N: 128, dtype: torch.complex64
Forward Execution Time (us) : 4.325

# Benchmarking PyTorch: mul
# Mode: Eager
# Name: mul_M32_N128_dtypetorch.complex128
# Input: M: 32, N: 128, dtype: torch.complex128
Forward Execution Time (us) : 6.809
```
Polar multiplication
```
# ----------------------------------------
# PyTorch/Caffe2 Operator Micro-benchmarks
# ----------------------------------------
# Tag : long

# Benchmarking PyTorch: mul
# Mode: Eager
# Name: mul_N2048_M32_dtypetorch.complex64
# Input: N: 2048, M: 32, dtype: torch.complex64
Forward Execution Time (us) : 34.734

# Benchmarking PyTorch: mul
# Mode: Eager
# Name: mul_N2048_M32_dtypetorch.complex128
# Input: N: 2048, M: 32, dtype: torch.complex128
Forward Execution Time (us) : 68.603

# Benchmarking PyTorch: mul
# Mode: Eager
# Name: mul_N512_M32_dtypetorch.complex64
# Input: N: 512, M: 32, dtype: torch.complex64
Forward Execution Time (us) : 10.872

# Benchmarking PyTorch: mul
# Mode: Eager
# Name: mul_N512_M32_dtypetorch.complex128
# Input: N: 512, M: 32, dtype: torch.complex128
Forward Execution Time (us) : 18.276

# Benchmarking PyTorch: mul
# Mode: Eager
# Name: mul_N128_M32_dtypetorch.complex64
# Input: N: 128, M: 32, dtype: torch.complex64
Forward Execution Time (us) : 3.764

# Benchmarking PyTorch: mul
# Mode: Eager
# Name: mul_N128_M32_dtypetorch.complex128
# Input: N: 128, M: 32, dtype: torch.complex128
Forward Execution Time (us) : 6.678
```
Polar overhead
```
# ----------------------------------------
# PyTorch/Caffe2 Operator Micro-benchmarks
# ----------------------------------------
# Tag : long

# Benchmarking PyTorch: polar
# Mode: Eager
# Name: polar_M32_dtypetorch.complex64_N2048
# Input: M: 32, dtype: torch.complex64, N: 2048
Forward Execution Time (us) : 432.961

# Benchmarking PyTorch: polar
# Mode: Eager
# Name: polar_M32_dtypetorch.complex64_N512
# Input: M: 32, dtype: torch.complex64, N: 512
Forward Execution Time (us) : 112.252

# Benchmarking PyTorch: polar
# Mode: Eager
# Name: polar_M32_dtypetorch.complex64_N128
# Input: M: 32, dtype: torch.complex64, N: 128
Forward Execution Time (us) : 28.107

# Benchmarking PyTorch: polar
# Mode: Eager
# Name: polar_M32_dtypetorch.complex128_N2048
# Input: M: 32, dtype: torch.complex128, N: 2048
Forward Execution Time (us) : 933.347

# Benchmarking PyTorch: polar
# Mode: Eager
# Name: polar_M32_dtypetorch.complex128_N512
# Input: M: 32, dtype: torch.complex128, N: 512
Forward Execution Time (us) : 222.800

# Benchmarking PyTorch: polar
# Mode: Eager
# Name: polar_M32_dtypetorch.complex128_N128
# Input: M: 32, dtype: torch.complex128, N: 128
Forward Execution Time (us) : 58.198
```
For small sizes speed up seems roughly about 10%, it is interesting that for complex64 for the largest benchmark speedup is almost not existing but for complex124 is about 35% . Although the overhead of calling polar before multiplication looks a bit intimidating.

cc @ezyang @anjali411 @dylanbespalko