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 uniformly 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 uniformly 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 normally 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 normally 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

hilbertspace

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\hilbertspace.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

vectorspace

vecipos(v)

Apply unary positive.

\[ \vec{v} = +\vec{v} \qquad \mathbb{K}^n\to\mathbb{K}^n \]
Source code in vector\inplace\vectorspace.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\vectorspace.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\vectorspace.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.vectorspace.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\vectorspace.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.vectorspace.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\vectorspace.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.vectorspace.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\vectorspace.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.vectorspace.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\vectorspace.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\vectorspace.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\vectorspace.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\vectorspace.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