Skip to content

In-place

Vector in-place operations.

>>> from vector import vecimul
>>> v = [1, 2, 3]
>>> vecimul(2, v)
[2, 4, 6]
>>> v
[2, 4, 6]

Prefixed by veci... (vector - in-place).

All functions accept vectors as lists.

They modify them in-place.

The functions are type-independent. However, the coefficients used must support necessary scalar operations. For instance, for vector addition, coefficients must be addable.

For complete type safety a zero argument is available. Default is int(0).

Docstring conventions

Summary

Math notation (vector notation if possible, index notation, domain & codomain)

More information ("More efficient than ...").

Notes

Design choices

See also

Similar functions

References

Wikipedia, numpy, ...

creation

vecizero()

Return a zero vector.

\[ \vec{0} \qquad \mathbb{K}^0 \]

An empty list: [].

Source code in vector\inplace\creation.py
12
13
14
15
16
17
18
19
20
21
def vecizero():
    r"""Return a zero vector.

    $$
        \vec{0} \qquad \mathbb{K}^0
    $$

    An empty list: `[]`.
    """
    return []

vecibasis(i, c=1, zero=0)

Return a basis vector.

\[ c\vec{e}_i \qquad \mathbb{K}^{i+1} \]

Returns a list with i many zeros followed by c.

See also
Source code in vector\inplace\creation.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
def vecibasis(i, c=1, zero=0):
    r"""Return a basis vector.

    $$
        c\vec{e}_i \qquad \mathbb{K}^{i+1}
    $$

    Returns a list with `i` many `zero`s followed by `c`.

    See also
    --------
    - for all basis vectors: [`vecibases`][vector.inplace.creation.vecibases]
    """
    return [zero]*i + [c]

vecibases(start=0, c=1, zero=0)

Yield all basis vectors.

\[ \left(\vec{e}_n\right)_{n\in\mathbb{N}_{\geq\text{start}}} = \left(\vec{e}_\text{start}, \vec{e}_{\text{start}+1}, \dots \right) \]
See also
Source code in vector\inplace\creation.py
38
39
40
41
42
43
44
45
46
47
48
49
50
def vecibases(start=0, c=1, zero=0):
    r"""Yield all basis vectors.

    $$
        \left(\vec{e}_n\right)_{n\in\mathbb{N}_{\geq\text{start}}} = \left(\vec{e}_\text{start}, \vec{e}_{\text{start}+1}, \dots \right)
    $$

    See also
    --------
    - for single basis vector: [`vecibasis`][vector.inplace.creation.vecibasis]
    """
    for i in count(start=start):
        yield vecibasis(i, c=c, zero=zero)

vecirand(n)

Return a random vector of uniform sampled float coefficients.

\[ \vec{v}\sim\mathcal{U}^n([0, 1[) \qquad \mathbb{K}^n \]

The coefficients are sampled from a uniform distribution in [0, 1[.

Notes

Naming like numpy.random, because seems more concise (not random & gauss as in the stdlib).

Source code in vector\inplace\creation.py
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
def vecirand(n):
    r"""Return a random vector of uniform sampled `float` coefficients.

    $$
        \vec{v}\sim\mathcal{U}^n([0, 1[) \qquad \mathbb{K}^n
    $$

    The coefficients are sampled from a uniform distribution in `[0, 1[`.

    Notes
    -----
    Naming like [`numpy.random`](https://numpy.org/doc/stable/reference/random/legacy.html),
    because seems more concise (not `random` & `gauss` as in the stdlib).
    """
    return list(veclrand(n))

vecirandn(n, normed=True, mu=0, sigma=1, weights=None)

Return a random vector of normal sampled float coefficients.

\[ \vec{v}\sim\mathcal{N}^n(\mu, \sigma) \qquad \mathbb{K}^n \]

The coefficients are sampled from a normal distribution.

Notes

Naming like numpy.random, because seems more concise (not random & gauss as in the stdlib).

Source code in vector\inplace\creation.py
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
def vecirandn(n, normed=True, mu=0, sigma=1, weights=None):
    r"""Return a random vector of normal sampled `float` coefficients.

    $$
        \vec{v}\sim\mathcal{N}^n(\mu, \sigma) \qquad \mathbb{K}^n
    $$

    The coefficients are sampled from a normal distribution.

    Notes
    -----
    Naming like [`numpy.random`](https://numpy.org/doc/stable/reference/random/legacy.html),
    because seems more concise (not `random` & `gauss` as in the stdlib).
    """
    v = list(veclrandn(n, mu, sigma))
    return vecitruediv(v, vecabs(v, weights)) if normed else v

utility

vecitrim(v, tol=None)

Remove all trailing near zero (abs(v_i)<=tol) coefficients.

\[ \begin{pmatrix} v_0 \\ \vdots \\ v_m \end{pmatrix} \ \text{where} \ m=\max\{\, j\mid |v_j|>\text{tol}\,\}\cup\{-1\} \qquad \mathbb{K}^n\to\mathbb{K}^{\leq n} \]

tol may also be None, then all coefficients that evaluate to False are trimmed.

Notes
  • Cutting of elements that are abs(v_i)<=tol instead of abs(v_i)<tol to allow cutting of elements that are exactly zero by trim(v, 0) instead of trim(v, sys.float_info.min).
Source code in vector\inplace\utility.py
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def vecitrim(v, tol=None):
    r"""Remove all trailing near zero (`abs(v_i)<=tol`) coefficients.

    $$
        \begin{pmatrix}
            v_0 \\
            \vdots \\
            v_m
        \end{pmatrix} \ \text{where} \ m=\max\{\, j\mid |v_j|>\text{tol}\,\}\cup\{-1\} \qquad \mathbb{K}^n\to\mathbb{K}^{\leq n}
    $$

    `tol` may also be `None`,
    then all coefficients that evaluate to `False` are trimmed.

    Notes
    -----
    - Cutting of elements that are `abs(v_i)<=tol` instead of `abs(v_i)<tol` to
    allow cutting of elements that are exactly zero by `trim(v, 0)` instead
    of `trim(v, sys.float_info.min)`.
    """
    while v and (not v[-1] if tol is None else abs(v[-1])<=tol):
        v.pop()
    return v

vecirshift(v, n, zero=0)

Shift coefficients up.

\[ (v_{i-n})_i \qquad \begin{pmatrix} 0 \\ \vdots \\ 0 \\ v_0 \\ v_1 \\ \vdots \end{pmatrix} \qquad \mathbb{K}^m\to\mathbb{K}^{m+n} \]
Source code in vector\inplace\utility.py
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
def vecirshift(v, n, zero=0):
    r"""Shift coefficients up.

    $$
        (v_{i-n})_i \qquad \begin{pmatrix}
            0 \\
            \vdots \\
            0 \\
            v_0 \\
            v_1 \\
            \vdots
        \end{pmatrix} \qquad \mathbb{K}^m\to\mathbb{K}^{m+n}
    $$
    """
    v[:0] = [zero] * n
    return v

vecilshift(v, n)

Shift coefficients down.

\[ (v_{i+n})_i \qquad \begin{pmatrix} v_n \\ v_{n+1} \\ \vdots \end{pmatrix} \qquad \mathbb{K}^m\to\mathbb{K}^{\max\{m-n, 0\}} \]
Source code in vector\inplace\utility.py
46
47
48
49
50
51
52
53
54
55
56
57
58
def vecilshift(v, n):
    r"""Shift coefficients down.

    $$
        (v_{i+n})_i \qquad \begin{pmatrix}
            v_n \\
            v_{n+1} \\
            \vdots
        \end{pmatrix} \qquad \mathbb{K}^m\to\mathbb{K}^{\max\{m-n, 0\}}
    $$
    """
    del v[:n]
    return v

hilbert_space

veciconj(v)

Complex conjugate.

\[ \vec{v} = \vec{v}^* \qquad \mathbb{K}^n\to\mathbb{K}^n \]

Tries to call a method conjugate on each element. If not found, simply keeps the element as is.

Source code in vector\inplace\hilbert_space.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
def veciconj(v):
    r"""Complex conjugate.

    $$
        \vec{v} = \vec{v}^* \qquad \mathbb{K}^n\to\mathbb{K}^n
    $$

    Tries to call a method `conjugate` on each element.
    If not found, simply keeps the element as is.
    """
    for i, vi in enumerate(v):
        v[i] = try_conjugate(vi)
    return v

vector_space

vecipos(v)

Apply unary positive.

\[ \vec{v} = +\vec{v} \qquad \mathbb{K}^n\to\mathbb{K}^n \]
Source code in vector\inplace\vector_space.py
 6
 7
 8
 9
10
11
12
13
14
15
def vecipos(v):
    r"""Apply unary positive.

    $$
        \vec{v} = +\vec{v} \qquad \mathbb{K}^n\to\mathbb{K}^n
    $$
    """
    for i, vi in enumerate(v):
        v[i] = +vi
    return v

vecineg(v)

Negate.

\[ \vec{v} = -\vec{v} \qquad \mathbb{K}^n\to\mathbb{K}^n \]
Source code in vector\inplace\vector_space.py
17
18
19
20
21
22
23
24
25
26
def vecineg(v):
    r"""Negate.

    $$
        \vec{v} = -\vec{v} \qquad \mathbb{K}^n\to\mathbb{K}^n
    $$
    """
    for i, vi in enumerate(v):
        v[i] = -vi
    return v

veciadd(v, *ws)

Add.

\[ \vec{v} += \vec{w}_0+\vec{w}_1+\cdots \qquad \mathbb{K}^{n_0}\times\mathbb{K}^{n_1}\times\cdots\to\mathbb{K}^{\max_i n_i} \]
See also
  • for sum on a single coefficient: veciaddc
Source code in vector\inplace\vector_space.py
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
def veciadd(v, *ws):
    r"""Add.

    $$
        \vec{v} += \vec{w}_0+\vec{w}_1+\cdots \qquad \mathbb{K}^{n_0}\times\mathbb{K}^{n_1}\times\cdots\to\mathbb{K}^{\max_i n_i}
    $$

    See also
    --------
    - for sum on a single coefficient: [`veciaddc`][vector.inplace.vector_space.veciaddc]
    """
    if ws:
        #extract longest vector so we only have to extend once
        longest = max(ws, key=len)
        ws = tuple(w for w in ws if w is not longest)
        #add longest vector
        for i, wi in enumerate(longest[:len(v)]):
            v[i] += wi
        v.extend(longest[len(v):])
        #add others
        for w in ws:
            for i, wi in enumerate(w):
                v[i] += wi
    return v

veciaddc(v, c, i=0, zero=0)

Add a basis vector.

\[ \vec{v} += c\vec{e}_i \qquad \mathbb{K}^n\to\mathbb{K}^{\max\{n, i+1\}} \]

More efficient than veciadd(v, vecibasis(i, c)).

See also
  • for sum on more coefficients: veciadd
Source code in vector\inplace\vector_space.py
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
def veciaddc(v, c, i=0, zero=0):
    r"""Add a basis vector.

    $$
        \vec{v} += c\vec{e}_i \qquad \mathbb{K}^n\to\mathbb{K}^{\max\{n, i+1\}}
    $$

    More efficient than `veciadd(v, vecibasis(i, c))`.

    See also
    --------
    - for sum on more coefficients: [`veciadd`][vector.inplace.vector_space.veciadd]
    """
    if i >= len(v):
        v.extend([zero] * (i-len(v)))
        v.append(c)
    else:
        v[i] += c
    return v

vecisub(v, w)

Subtract.

\[ \vec{v} -= \vec{w} \qquad \mathbb{K}^m\times\mathbb{K}^n\to\mathbb{K}^{\max\{m, n\}} \]
See also
  • for difference on a single coefficient: vecisubc
Source code in vector\inplace\vector_space.py
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
def vecisub(v, w):
    r"""Subtract.

    $$
        \vec{v} -= \vec{w} \qquad \mathbb{K}^m\times\mathbb{K}^n\to\mathbb{K}^{\max\{m, n\}}
    $$

    See also
    --------
    - for difference on a single coefficient: [`vecisubc`][vector.inplace.vector_space.vecisubc]
    """
    for i, wi in enumerate(w[:len(v)]):
        v[i] -= wi
    if len(w) > len(v):
        v.extend([-wi for wi in w[len(v):]])
    return v

vecisubc(v, c, i=0, zero=0)

Subtract a basis vector.

\[ \vec{v} -= c\vec{e}_i \qquad \mathbb{K}^n\to\mathbb{K}^{\max\{n, i+1\}} \]

More efficient than vecisub(v, vecibasis(i, c)).

See also
  • for difference on more coefficients: vecisub
Source code in vector\inplace\vector_space.py
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
def vecisubc(v, c, i=0, zero=0):
    r"""Subtract a basis vector.

    $$
        \vec{v} -= c\vec{e}_i \qquad \mathbb{K}^n\to\mathbb{K}^{\max\{n, i+1\}}
    $$

    More efficient than `vecisub(v, vecibasis(i, c))`.

    See also
    --------
    - for difference on more coefficients: [`vecisub`][vector.inplace.vector_space.vecisub]
    """
    if i >= len(v):
        v.extend([zero] * (i-len(v)))
        v.append(-c)
    else:
        v[i] -= c
    return v

vecimul(v, a)

Multiply.

\[ \vec{v} \cdot= a \qquad \mathbb{K}\times\mathbb{K}^n\to\mathbb{K}^n \]
Source code in vector\inplace\vector_space.py
110
111
112
113
114
115
116
117
118
119
def vecimul(v, a):
    r"""Multiply.

    $$
        \vec{v} \cdot= a \qquad \mathbb{K}\times\mathbb{K}^n\to\mathbb{K}^n
    $$
    """
    for i in range(len(v)):
        v[i] *= a
    return v

vecitruediv(v, a)

True divide.

\[ \vec{v} /= a \qquad \mathbb{K}^n\times\mathbb{K}\to\mathbb{K}^n \]
Notes

Why called truediv instead of div?

  • div would be more appropriate for an absolute clean mathematical implementation, that doesn't care about the language used. But the package might be used for pure integers/integer arithmetic, so both, truediv and floordiv operations have to be provided, and none should be privileged over the other by getting the universal div name.
  • truediv/floordiv is unambiguous, like Python operators.
Source code in vector\inplace\vector_space.py
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
def vecitruediv(v, a):
    r"""True divide.

    $$
        \vec{v} /= a \qquad \mathbb{K}^n\times\mathbb{K}\to\mathbb{K}^n
    $$

    Notes
    -----
    Why called `truediv` instead of `div`?

    - `div` would be more appropriate for an absolute clean mathematical
    implementation, that doesn't care about the language used. But the package
    might be used for pure integers/integer arithmetic, so both, `truediv`
    and `floordiv` operations have to be provided, and none should be
    privileged over the other by getting the universal `div` name.
    - `truediv`/`floordiv` is unambiguous, like Python `operator`s.
    """
    for i in range(len(v)):
        v[i] /= a
    return v

vecifloordiv(v, a)

Floor divide.

\[ \vec{v} //= a \qquad \mathbb{K}^n\times\mathbb{K}\to\mathbb{K}^n \]
Source code in vector\inplace\vector_space.py
143
144
145
146
147
148
149
150
151
152
def vecifloordiv(v, a):
    r"""Floor divide.

    $$
        \vec{v} //= a \qquad \mathbb{K}^n\times\mathbb{K}\to\mathbb{K}^n
    $$
    """
    for i in range(len(v)):
        v[i] //= a
    return v

vecimod(v, a)

Mod.

\[ \vec{v} \%= a \qquad \mathbb{K}^n\times\mathbb{K}\to\mathbb{K}^n \]
Source code in vector\inplace\vector_space.py
154
155
156
157
158
159
160
161
162
163
def vecimod(v, a):
    r"""Mod.

    $$
        \vec{v} \%= a \qquad \mathbb{K}^n\times\mathbb{K}\to\mathbb{K}^n
    $$
    """
    for i in range(len(v)):
        v[i] %= a
    return v

elementwise

vecihadamard(v, *ws)

Return the elementwise product.

\[ \left((\vec{v})_i\cdot(\vec{w}_0)_i\cdot(\vec{w}_1)_i\cdot\cdots\right)_i \qquad \mathbb{K}^{n_0}\times\mathbb{K}^{n_1}\times\cdots\to\mathbb{K}^{\min_i n_i} \]
Source code in vector\inplace\elementwise.py
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
def vecihadamard(v, *ws):
    r"""Return the elementwise product.

    $$
        \left((\vec{v})_i\cdot(\vec{w}_0)_i\cdot(\vec{w}_1)_i\cdot\cdots\right)_i \qquad \mathbb{K}^{n_0}\times\mathbb{K}^{n_1}\times\cdots\to\mathbb{K}^{\min_i n_i}
    $$
    """
    if ws:
        del v[min(len(w) for w in ws):]
        for w in ws:
            for i, wi in enumerate(w[:len(v)]):
                v[i] *= wi
    return v

vecihadamardtruediv(v, w)

Return the elementwise true quotient.

\[ \left(\frac{v_i}{w_i}\right)_i \qquad \mathbb{K}^m\times\mathbb{K}^n\to\mathbb{K}^m \]
Source code in vector\inplace\elementwise.py
20
21
22
23
24
25
26
27
28
29
def vecihadamardtruediv(v, w):
    r"""Return the elementwise true quotient.

    $$
        \left(\frac{v_i}{w_i}\right)_i \qquad \mathbb{K}^m\times\mathbb{K}^n\to\mathbb{K}^m
    $$
    """
    for i in range(len(v)):
        v[i] /= w[i]
    return v

vecihadamardfloordiv(v, w)

Return the elementwise floor quotient.

\[ \left(\left\lfloor\frac{v_i}{w_i}\right\rfloor\right)_i \qquad \mathbb{K}^m\times\mathbb{K}^n\to\mathbb{K}^m \]
Source code in vector\inplace\elementwise.py
31
32
33
34
35
36
37
38
39
40
def vecihadamardfloordiv(v, w):
    r"""Return the elementwise floor quotient.

    $$
        \left(\left\lfloor\frac{v_i}{w_i}\right\rfloor\right)_i \qquad \mathbb{K}^m\times\mathbb{K}^n\to\mathbb{K}^m
    $$
    """
    for i in range(len(v)):
        v[i] //= w[i]
    return v

vecihadamardmod(v, w)

Return the elementwise remainder.

\[ \left(v_i \bmod w_i\right)_i \qquad \mathbb{K}^m\times\mathbb{K}^n\to\mathbb{K}^m \]
Source code in vector\inplace\elementwise.py
42
43
44
45
46
47
48
49
50
51
def vecihadamardmod(v, w):
    r"""Return the elementwise remainder.

    $$
        \left(v_i \bmod w_i\right)_i \qquad \mathbb{K}^m\times\mathbb{K}^n\to\mathbb{K}^m
    $$
    """
    for i in range(len(v)):
        v[i] %= w[i]
    return v