1 /*
2  * Copyright (c) 2019-2020 Kevin Townsend (KTOWN)
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @defgroup VECTORS Vectors
9  *
10  * @brief Vectors functions
11  *
12  * TODO: Expand with examples, better high-level documentation, etc.
13  */
14 
15 /**
16  * @file
17  * @brief API header file for vectors in zscilib.
18  *
19  * This file contains the zscilib vector APIs
20  */
21 
22 #ifndef ZEPHYR_INCLUDE_ZSL_VECTORS_H_
23 #define ZEPHYR_INCLUDE_ZSL_VECTORS_H_
24 
25 #include <zsl/zsl.h>
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 /**
32  * @addtogroup VEC_STRUCTS Structs, Enums and Macros
33  *
34  * @brief Various struct, enums and macros related to vectors.
35  *
36  * @ingroup VECTORS
37  *  @{ */
38 
39 /** @brief Represents a vector. */
40 struct zsl_vec {
41 	/** The number of elements in the vector. */
42 	size_t sz;
43 	/** The array of real number values assigned to the vector. */
44 	zsl_real_t *data;
45 };
46 
47 /** Macro to declare a vector of size `n`.
48  *
49  * Be sure to also call 'zsl_vec_init' on the vector after this macro, since
50  * matrices declared on the stack may have non-zero values by default!
51  */
52 #define ZSL_VECTOR_DEF(name, n)	     \
53 	zsl_real_t name ## _vec[n];  \
54 	struct zsl_vec name = {	     \
55 		.sz = n,	     \
56 		.data = name ## _vec \
57 	}
58 
59 /** @} */ /* End of VEC_STRUCTS group */
60 
61 /**
62  * @addtogroup VEC_INIT Initialisation
63  *
64  * @brief Vector initisialisation.
65  *
66  * @ingroup VECTORS
67  *  @{ */
68 
69 /**
70  * Initialises vector 'v' with 0.0 values.
71  *
72  * @param v         Pointer to the zsl_vec to initialise/clear.
73  *
74  * @return 0 on success, and non-zero error code on failure
75  */
76 int zsl_vec_init(struct zsl_vec *v);
77 
78 /**
79  * @brief Converts an array of values into a vector. The number of elements in
80  *        array 'a' must match the number of elements in vector 'v'.
81  *        As such, 'v' should be previously initialised with an appropriate
82  *        value assigned to v.sz.
83  *
84  * @param v The vector that the contents of array 'a' should be assigned to.
85  *          The v.sz value must match the number of elements in 'a', meaning
86  *          that the vector should be initialised before being passed in to
87  *          this function.
88  * @param a Pointer to the array containing the values to assign to 'v'.
89  *          The array will be read v.sz elements deep.
90  *
91  * @return 0 on success, and non-zero error code on failure
92  */
93 int zsl_vec_from_arr(struct zsl_vec *v, zsl_real_t *a);
94 
95 /**
96  * @brief Copies the contents of vector 'vsrc' into vector 'vdest'.
97  *
98  * @param vdest Pointer to the destination vector data will be copied to.
99  * @param vsrc  Pointer to the source vector data will be copied from.
100  *
101  * @return 0 on success, and non-zero error code on failure
102  */
103 int zsl_vec_copy(struct zsl_vec *vdest, struct zsl_vec *vsrc);
104 
105 /** @} */ /* End of VEC_INIT group */
106 
107 /**
108  * @addtogroup VEC_SELECTION Data Selection
109  *
110  * @brief Functions used to access subsets of the vector.
111  *
112  * @ingroup VECTORS
113  *  @{ */
114 
115 /**
116  * @brief Returns a subset of source vector 'v' in 'vsub'..
117  *
118  * @param v         The parent vector to read a subset of.
119  * @param offset    The starting index (zero-based) foor the data subset.
120  * @param len       The number of values to read, starting at offset.
121  * @param vsub      The subset vector, which must have a buffer of at least
122  *                  size 'len'. If the data buffer isn't sufficiently large,
123  *                  this function will return -EINVAL.
124  *
125  * @return 0 on success, -EINVAL on a size of index error.
126  */
127 int zsl_vec_get_subset(struct zsl_vec *v, size_t offset, size_t len,
128 		       struct zsl_vec *vsub);
129 
130 /** @} */ /* End of VEC_SELECTION group */
131 
132 /**
133  * @addtogroup VEC_BASICMATH Basic Math
134  *
135  * @brief Basic mathematical operations (add, sum, norm, etc.).
136  *
137  * @ingroup VECTORS
138  *  @{ */
139 
140 /**
141  * @brief Adds corresponding vector elements in 'v' and 'w', saving to 'x'.
142  *
143  * @param v The first vector.
144  * @param w The second vector.
145  * @param x The output vector.
146  *
147  * @return 0 on success, -EINVAL if v and w are not equal length.
148  */
149 int zsl_vec_add(struct zsl_vec *v, struct zsl_vec *w, struct zsl_vec *x);
150 
151 /**
152  * @brief Subtracts corresponding vector elements in 'v' and 'w', saving to 'x'.
153  *
154  * @param v The first vector.
155  * @param w The second vector.
156  * @param x The output vector.
157  *
158  * @return 0 on success, -EINVAL if v and w are not equal length.
159  */
160 int zsl_vec_sub(struct zsl_vec *v, struct zsl_vec *w, struct zsl_vec *x);
161 
162 /**
163  * @brief Negates the elements in vector 'v'.
164  *
165  * @param v The vector to negate.
166  *
167  * @return 0 on success, and non-zero error code on failure
168  */
169 int zsl_vec_neg(struct zsl_vec *v);
170 
171 /**
172  * @brief Component-wise sum of a set of equal-length vectors.
173  *
174  * @param v  Pointer to the array of vectors.
175  * @param n  The number of vectors in 'v'.
176  * @param w  Pointer to the output vector containing the component-wise sum.
177  *
178  * @return 0 on success, -EINVAL if vectors in 'v' are no equal length, or
179  *         -EINVAL if 'n' = 0.
180  */
181 int zsl_vec_sum(struct zsl_vec **v, size_t n, struct zsl_vec *w);
182 
183 /**
184  * @brief Adds a scalar to each element in a vector.
185  *
186  * @param v The vector to scale.
187  * @param s The scalar to add to each element.
188  *
189  * @return 0 on success, and non-zero error code on failure
190  */
191 int zsl_vec_scalar_add(struct zsl_vec *v, zsl_real_t s);
192 
193 /**
194  * @brief Multiply a vector by a scalar.
195  *
196  * @param v The vector to scale.
197  * @param s The scalar to multiply by.
198  *
199  * @return 0 on success, and non-zero error code on failure
200  */
201 int zsl_vec_scalar_mult(struct zsl_vec *v, zsl_real_t s);
202 
203 /**
204  * @brief Divide a vector by a scalar.
205  *
206  * @param v The vector to scale.
207  * @param s The scalar to divide all elements by.
208  *
209  * @return 0 on success, and non-zero error code on failure
210  */
211 int zsl_vec_scalar_div(struct zsl_vec *v, zsl_real_t s);
212 
213 /**
214  * @brief Calculates the distance between two vectors, which is equal to the
215  *        norm of vector v - vector w.
216  *
217  * @param v The first vector.
218  * @param w The second vector.
219  *
220  * @return The norm of vector v - vector w, or NAN is there was a
221  *         size mismatch between vectors v and w.
222  */
223 zsl_real_t zsl_vec_dist(struct zsl_vec *v, struct zsl_vec *w);
224 
225 /**
226  * @brief Computes the dot (aka scalar) product of two equal-length vectors
227  *        (the sum of their component-wise products). The dot product is an
228  *        indicator of the "agreement" between two vectors, or can be used
229  *        to determine how far vector w deviates from vector v.
230  *
231  * @param v The first vector.
232  * @param w The second vector.
233  * @param d The dot product.
234  *
235  * @return 0 on success, or -EINVAL if vectors v and w aren't equal-length.
236  */
237 int zsl_vec_dot(struct zsl_vec *v, struct zsl_vec *w, zsl_real_t *d);
238 
239 /**
240  * @brief Calculates the norm or absolute value of vector 'v' (the
241  *        square root of the vector's dot product).
242  *
243  * @param v The vector to calculate the norm of.
244  *
245  * @return The norm of vector 'v'.
246  */
247 zsl_real_t zsl_vec_norm(struct zsl_vec *v);
248 
249 /**
250  * @brief   Calculates the projection of vector 'u' over vector 'v', placing
251  *          the results in vector 'w'.
252  *
253  * @param u Pointer to the first input vector.
254  * @param v Pointer to the second input vector.
255  * @param w Pointer to the output vector where the proj. results are stored.
256  *
257  * @return  0 if everything executed correctly, otherwise an appropriate
258  *          error code.
259  */
260 int zsl_vec_project(struct zsl_vec *u, struct zsl_vec *v, struct zsl_vec *w);
261 
262 /**
263  * @brief Converts (normalises) vector 'v' to a unit vector (a vector of
264  *        magnitude or length 1). This is accomploished by dividing each
265  *        element by the it's norm.
266  *
267  * @note Unit vectors are important since they have the ability to provide
268  *       'directional' information, without requiring a specific magnitude.
269  *
270  * @param v The vector to convert to a unit vector.
271  *
272  * @return 0 on success, and non-zero error code on failure
273  */
274 int zsl_vec_to_unit(struct zsl_vec *v);
275 
276 /**
277  * @brief Computes the cross (or vector) product of two 3-vectors.
278  *
279  * @param v The first 3-vector.
280  * @param w The second 3-vector.
281  * @param c The cross product 3-vector output.
282  *
283  * @return 0 on success, or -EINVAL if a non 3-vector is provided.
284  *
285  * Given two linearly independent 3-vectors (v and w), the cross product,
286  * (v X w), is a vector that is perpendicular to both v and w and thus 'normal'
287  * to the plane containing them.
288  *
289  * If two vectors have the same direction (or have the exact opposite direction
290  * from one another, i.e. are not linearly independent) or if either one has
291  * zero length, then their cross product is zero.
292  *
293  * The norm of the cross product equals the area of a parallelogram
294  * with vectors v and w for sides.
295  *
296  * For a discusson of geometric and algebraic applications, see:
297  * https://en.wikipedia.org/wiki/Cross_product
298  */
299 int zsl_vec_cross(struct zsl_vec *v, struct zsl_vec *w, struct zsl_vec *c);
300 
301 /**
302  * @brief Computes the vector's sum of squares.
303  *
304  * @param v The vector to use.
305  *
306  * @return The sum of the squares of vector 'v'.
307  */
308 zsl_real_t zsl_vec_sum_of_sqrs(struct zsl_vec *v);
309 
310 /**
311  * @brief Computes the component-wise mean of a set of identically-sized
312  * vectors.
313  *
314  * @param v  Pointer to the array of vectors.
315  * @param n  The number of vectors in 'v'.
316  * @param m  Pointer to the output vector whose i'th element is the mean of
317  *           the i'th elements of the input vectors.
318  *
319  * @return 0 on success, and -EINVAL if all vectors aren't identically sized.
320  */
321 int zsl_vec_mean(struct zsl_vec **v, size_t n, struct zsl_vec *m);
322 
323 /**
324  * @brief Computes the arithmetic mean of a vector.
325  *
326  * @param v  The vector to use.
327  * @param m  The arithmetic mean of vector v.
328  *
329  * @return 0 on success, otherwise an appropriate error code.
330  */
331 int zsl_vec_ar_mean(struct zsl_vec *v, zsl_real_t *m);
332 
333 /**
334  * @brief Reverses the order of the entries in vector 'v'.
335  *
336  * @param v The vector to use.
337  *
338  * @return 0 on success, otherwise an appropriate error code.
339  */
340 int zsl_vec_rev(struct zsl_vec *v);
341 
342 /**
343  * @brief Rearranges the input vector to place any zero-values at the end.
344  *
345  * @param v   The input vector to rearrange.
346  *
347  * @warning   This function is destructive to 'v'!
348  *
349  * @return  0 if everything executed correctly, otherwise an appropriate
350  *          error code.
351  */
352 int zsl_vec_zte(struct zsl_vec *v);
353 
354 /** @} */ /* End of VEC_BASICMATH group */
355 
356 /**
357  * @addtogroup VEC_COMPARE Comparison
358  *
359  * @brief Functions used to compare or verify vectors.
360  *
361  * @ingroup VECTORS
362  *  @{ */
363 
364 /**
365  * @brief Checks if two vectors are identical in size and content.
366  *
367  * @param v     The first vector.
368  * @param w     The second vector.
369  * @param eps   The margin for floating-point equality (ex. '1E-5').
370  *
371  * @return true if the two vectors have the same size and the same values,
372  *         otherwise false.
373  */
374 bool zsl_vec_is_equal(struct zsl_vec *v, struct zsl_vec *w, zsl_real_t eps);
375 
376 /**
377  * @brief Checks if all elements in vector v are >= zero.
378  *
379  * @param v The vector to check.
380  *
381  * @return true if all elements in 'v' are zero or positive, otherwise false.
382  */
383 bool zsl_vec_is_nonneg(struct zsl_vec *v);
384 
385 /**
386  * @brief Checks if vector v contains val, returning the number of occurences.
387  *
388  * @param v     The vector to check.
389  * @param val   The value to check all coefficients for.
390  * @param eps   The margin for floating-point equality (ex. '1E-5').
391  *
392  * @return The number of occurences of val withing range eps, 0 if no
393  *         matching occurences were found, or a negative error code.
394  */
395 int zsl_vec_contains(struct zsl_vec *v, zsl_real_t val, zsl_real_t eps);
396 
397 /**
398  * @brief Sorts the values in vector v from smallest to largest using quicksort,
399  *        and assigns the sorted output to vector w.
400  *
401  * @param v     The unsorted, input vector.
402  * @param w     The sorted, output vector.
403  *
404  * @return 0 if everything executed properly, otherwise a negative error code.
405  */
406 int zsl_vec_sort(struct zsl_vec *v, struct zsl_vec *w);
407 
408 /** @} */ /* End of VEC_COMPARE group */
409 
410 /**
411  * @addtogroup VEC_DISPLAY Display
412  *
413  * @brief Functions used to present vectors in a user-friendly format.
414  *
415  * @ingroup VECTORS
416  *  @{ */
417 
418 /**
419  * @brief Print the supplied vector using printf in a human-readable manner.
420  *
421  * @param v     Pointer to the vector to print.
422  *
423  * @return  0 if everything executed correctly, otherwise an appropriate
424  *          error code.
425  */
426 int zsl_vec_print(struct zsl_vec *v);
427 
428 // int      zsl_vec_fprint(FILE *stream, zsl_vec *v);
429 
430 /** @} */ /* End of VEC_DISPLAY group */
431 
432 #ifdef __cplusplus
433 }
434 #endif
435 
436 #endif /* ZEPHYR_INCLUDE_ZSL_VECTORS_H_ */
437 
438 /** @} */ /* End of vectors group */
439