# How to satisfy the requirement of LoopVectorization argument check?

**URL:** <https://discourse.julialang.org/t/how-to-satisfy-the-requirement-of-loopvectorization-argument-check/89446>\
**Category:** New to Julia\
**Tags:** question, package\
**Created:** [October 28, 2022, 12:25pm UTC](https://discourse.julialang.org/t/how-to-satisfy-the-requirement-of-loopvectorization-argument-check/89446 "2022-10-28T12:25:32Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![mzd1893](https://avatars.discourse-cdn.com/v4/letter/m/d07c76/32.png) [@mzd1893](https://discourse.julialang.org/u/mzd1893)\
**Post date:** [October 28, 2022, 12:25pm UTC](https://discourse.julialang.org/t/how-to-satisfy-the-requirement-of-loopvectorization-argument-check/89446/1 "2022-10-28T12:25:32Z")

</div>

I want to learn how to use `LoopVectorization`. It is known that `LoopVectorization` cannot deal with complex number directly, and it need `StructArray`, then I write a simple loop for practicing. However there are some errors:

```julia
Start
val=StructArray(0.0+0.0*im);
rd=rand(100);
function f(v)
@turbo for n in 1:100
        v+=StructArray(1.0+im*0.1 - rd[n]);
        end
    v
end
@time f(val)
0.029814 seconds (71.45 k allocations: 3.591 MiB, 97.51% compilation time)
Warning: #= In[6]:2 =#:
│ `LoopVectorization.check_args` on your inputs failed; running fallback `@inbounds @fastmath` loop instead.
│ Use `warn_check_args=false`, e.g. `@turbo warn_check_args=false ...`, to disable this warning.
└ @ Main C:\Users\.julia\packages\LoopVectorization\FMfT8\src\condense_loopset.jl:1049
End

```

The error says that argument check is not pass. To solve this, I make a little modifications on loop:

```julia
function f1(val2)
@turbo for n in 1:100
        v=val2;
        val2 =v+StructArray(1.0+im*0.1 - rd[n])
        end
end
@time f1(val)
0.034055 seconds (70.56 k allocations: 3.684 MiB, 99.82% compilation time)

function f2(v)
@turbo for n in 1:1000
        add=StructArray(1.0+im*0.1 - rd[n]);
        v=v+add;
        end
    v
end
@time f2(val)
0.029021 seconds (71.50 k allocations: 3.598 MiB, 97.83% compilation time)
┌ Warning: #= In[7]:2 =#:
│ `LoopVectorization.check_args` on your inputs failed; running fallback `@inbounds @fastmath` loop instead.
│ Use `warn_check_args=false`, e.g. `@turbo warn_check_args=false ...`, to disable this warning.
└ @ Main C:\Users\.julia\packages\LoopVectorization\FMfT8\src\condense_loopset.jl:1049

```

In `f1`, `LoopVectorization` doesn’t throw error, however all three have the same running time. How could I really solve this and how to use `LoopVectorization` generally?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 28, 2022, 2:00pm UTC](https://discourse.julialang.org/t/how-to-satisfy-the-requirement-of-loopvectorization-argument-check/89446/2 "2022-10-28T14:00:41Z")

</div>

As far as I understand, StructArrays will convert _a vector of complex_ numbers into two vectors, one for the real part other for the imaginary part. To vectorize, I think you must (unless some macro within LoopVectorization is smart enough to do that automatically), operate on each of these vectors independently. For example:

```julia
julia> using LoopVectorization

julia> x = StructArray([rand(ComplexF64) for _ in 1:100]);

julia> @turbo for i in eachindex(x)
           x.re[i] += rand()
           x.im[i] += rand()
       end

```

(I don’t really understand the use of `StructArray` if the input is a scalar. I think that only defines the type of element that the arrays will contain, and you are not really doing anything useful there in your example by adding or subtracting values from `StructArray(1.0 + 1.0im)`).

---

<div class="post-metadata">

**Author:** ![mzd1893](https://avatars.discourse-cdn.com/v4/letter/m/d07c76/32.png) [@mzd1893](https://discourse.julialang.org/u/mzd1893)\
**Post date:** [October 28, 2022, 6:18pm UTC](https://discourse.julialang.org/t/how-to-satisfy-the-requirement-of-loopvectorization-argument-check/89446/3 "2022-10-28T18:18:37Z")

</div>

thx. Your suggestion works.  
What’s the difference between `x.re[i]` and `real(x)[i]`? Both of them can take real part and pick number i element, but only the first works in loop.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 29, 2022, 1:10pm UTC](https://discourse.julialang.org/t/how-to-satisfy-the-requirement-of-loopvectorization-argument-check/89446/4 "2022-10-29T13:10:29Z")

</div>

`real(x)` will return an array with the real part of every element. The equivalent of `x.re[i]` would be `real(x[i])`.

But `x.re[i] = rand()` is a `setindex!` operation, which means that it is assigning to `x.re[i]` a new value.

This is specific of how `StructArrays` work. The vector of complex numbers is converted to a structure that contains two vectors, one for the real part and one for the imaginary part of those numbers. `x.re` is the internal field of that structure that is the array of the real parts, and `x.im` is the internal field of that structure that contains the vector of the imaginary parts.

`x.re` and `x.im` are just to standard vectors or floats, and that is why you can use them without any problem for vectorizing the operations that act on them.
