# PyCall numpy vdot Vector{Float32} returns Float64

**URL:** <https://discourse.julialang.org/t/pycall-numpy-vdot-vector-float32-returns-float64/126768>\
**Category:** General Usage\
**Tags:** pycall, linearalgebra\
**Created:** [March 10, 2025, 3:05pm UTC](https://discourse.julialang.org/t/pycall-numpy-vdot-vector-float32-returns-float64/126768 "2025-03-10T15:05:06Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![osimonn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/osimonn/32/44888_2.png) [@osimonn](https://discourse.julialang.org/u/osimonn)\
**Post date:** [March 10, 2025, 3:05pm UTC](https://discourse.julialang.org/t/pycall-numpy-vdot-vector-float32-returns-float64/126768/1 "2025-03-10T15:05:07Z")

</div>

I have been comparing numpy using PyCall with Julia recently and observed a strange behavior. When I call numpy from Julia and do a dot product of two Vector{Float32} vectors, the result is Float64.

However, when I run a similar code in python directly, the result is float32

Julia code:

```julia
using PyCall

np = pyimport("numpy")

x = Float32[1, 2, 3, 4]
y = Float32[5, 6, 7, 8]

println(typeof(np.vdot(x, y))) # Float64

```

Python code:

```python
import numpy as np

x = np.array([1, 2, 3, 4], dtype=np.float32)
y = np.array([5, 6, 7, 8], dtype=np.float32)

print(np.vdot(x, y).dtype) # float32

```

Information about my environment

Julia:

```julia
julia> versioninfo()
Julia Version 1.11.3
Commit d63adeda50d (2025-01-21 19:42 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 8 × Intel(R) Xeon(R) Gold 6338N CPU @ 2.20GHz
  WORD_SIZE: 64
  LLVM: libLLVM-16.0.6 (ORCJIT, icelake-server)
Threads: 1 default, 0 interactive, 1 GC (on 8 virtual cores)
Environment:
  JULIA_GPG = 3673DF529D9049477F76B37566E3C7DC03D6E495
  JULIA_PATH = /usr/local/julia
  JULIA_VERSION = 1.11.3
  JULIA_EDITOR = code
  JULIA_NUM_THREADS =

(@v1.11) pkg> st
Status `~/.julia/environments/v1.11/Project.toml`
  [6e4b80f9] BenchmarkTools v1.6.0
  [438e738f] PyCall v1.96.4

```

Python:

```python
Python 3.11.2 (main, Nov 30 2024, 21:22:50) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> np.version.full_version
'1.24.2'

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 10, 2025, 4:23pm UTC](https://discourse.julialang.org/t/pycall-numpy-vdot-vector-float32-returns-float64/126768/2 "2025-03-10T16:23:33Z")

</div>

> [@osimonn](#):
>
> `println(typeof(np.vdot(x, y))) `

That’s just the automatic conversion, which doesn’t know about numpy scalars. It’s still actually doing the single precision calculation, as you can see if you tell PyCall to not automatically convert the result to a Julia type:

```julia
julia> pycall(np.vdot, PyObject, x, y)
PyObject 70.0

julia> pycall(np.vdot, PyObject, x, y).dtype
PyObject dtype('float32')

```

If you care about the Julia type being `Float32`, you can do `pycall(np.vdot, Float32, x, y)`.

Alternatively, you can use PythonCall.jl, which never automatically converts the results — you have to convert things to native Julia types manually.

---

<div class="post-metadata">

**Author:** ![osimonn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/osimonn/32/44888_2.png) [@osimonn](https://discourse.julialang.org/u/osimonn)\
**Post date:** [March 10, 2025, 7:38pm UTC](https://discourse.julialang.org/t/pycall-numpy-vdot-vector-float32-returns-float64/126768/3 "2025-03-10T19:38:22Z")

</div>

Thanks for the explanation but is there a reason why the automatic conversion in PyCall.jl does not automatically convert Numpy’s `float32` to Julia’s `Float32`? Sorry, but I am not super familiar with the inner workings of the package.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [March 10, 2025, 7:58pm UTC](https://discourse.julialang.org/t/pycall-numpy-vdot-vector-float32-returns-float64/126768/4 "2025-03-10T19:58:31Z")

</div>

> [@osimonn](#):
>
> Thanks for the explanation but is there a reason why the automatic conversion in [PyCall.jl](https://juliaregistries.github.io/General/packages/redirect_to_repo/PyCall) does not automatically convert Numpy’s `float32` to Julia’s `Float32`?

Because the conversion code doesn’t know about Numpy. It just knows that the value is a subtype of `float` (because `PyFloat_Type` from the Python C API returns `true`) and it calls `PyFloat_AsDouble` from the Python C API.

We _could_ add a numpy-specific scalar conversion pass, of course. But there’s no loss of data if a `float32` is converted to a `Float64`.
