1 /*
2  * Copyright (c) 2019 Kevin Townsend (KTOWN)
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <errno.h>
8 #include <stdio.h>
9 #include <stdbool.h>
10 #include <string.h>
11 #include <zsl/vectors.h>
12 #include <zsl/zsl.h>
13 
14 /* Enable optimised ARM Thumb/Thumb2 functions if available. */
15 #if (CONFIG_ZSL_PLATFORM_OPT == 1 || CONFIG_ZSL_PLATFORM_OPT == 2)
16 #include <zsl/asm/arm/asm_arm_vectors.h>
17 #endif
18 
zsl_vec_init(struct zsl_vec * v)19 int zsl_vec_init(struct zsl_vec *v)
20 {
21 	memset(v->data, 0, v->sz * sizeof(zsl_real_t));
22 
23 	return 0;
24 }
25 
zsl_vec_from_arr(struct zsl_vec * v,zsl_real_t * a)26 int zsl_vec_from_arr(struct zsl_vec *v, zsl_real_t *a)
27 {
28 	memcpy(v->data, a, v->sz * sizeof(zsl_real_t));
29 
30 	return 0;
31 }
32 
zsl_vec_copy(struct zsl_vec * vdest,struct zsl_vec * vsrc)33 int zsl_vec_copy(struct zsl_vec *vdest, struct zsl_vec *vsrc)
34 {
35 	vdest->sz = vsrc->sz;
36 	memcpy(vdest->data, vsrc->data, sizeof(zsl_real_t) *
37 	       vdest->sz);
38 
39 	return 0;
40 }
41 
zsl_vec_get_subset(struct zsl_vec * v,size_t offset,size_t len,struct zsl_vec * vsub)42 int zsl_vec_get_subset(struct zsl_vec *v, size_t offset, size_t len,
43 		       struct zsl_vec *vsub)
44 {
45 #if CONFIG_ZSL_BOUNDS_CHECKS
46 	/* Make sure offset doesn't exceed v->sz. */
47 	if (offset >= v->sz) {
48 		return -EINVAL;
49 	}
50 	/* If offset+len exceeds v->sz, truncate len. */
51 	if (offset + len >= v->sz) {
52 		len = v->sz - offset;
53 	}
54 	/* Make sure vsub->sz is at least len, otherwise buffer overrun. */
55 	if (vsub->sz < len) {
56 		return -EINVAL;
57 	}
58 #endif
59 
60 	/* Truncate vsub->sz if there is an underrun. */
61 	if (vsub->sz > len) {
62 		vsub->sz = len;
63 	}
64 
65 	memcpy(vsub->data, &v->data[offset], len * sizeof(zsl_real_t));
66 
67 	return 0;
68 }
69 
70 #if !asm_vec_add
zsl_vec_add(struct zsl_vec * v,struct zsl_vec * w,struct zsl_vec * x)71 int zsl_vec_add(struct zsl_vec *v, struct zsl_vec *w, struct zsl_vec *x)
72 {
73 #if CONFIG_ZSL_BOUNDS_CHECKS
74 	/* Make sure v and w are equal length. */
75 	if ((v->sz != w->sz) || (v->sz != x->sz)) {
76 		return -EINVAL;
77 	}
78 #endif
79 
80 	for (size_t i = 0; i < v->sz; i++) {
81 		x->data[i] = v->data[i] + w->data[i];
82 	}
83 
84 	return 0;
85 }
86 #endif
87 
zsl_vec_sub(struct zsl_vec * v,struct zsl_vec * w,struct zsl_vec * x)88 int zsl_vec_sub(struct zsl_vec *v, struct zsl_vec *w, struct zsl_vec *x)
89 {
90 #if CONFIG_ZSL_BOUNDS_CHECKS
91 	/* Make sure v and w are equal length. */
92 	if ((v->sz != w->sz) || (v->sz != x->sz)) {
93 		return -EINVAL;
94 	}
95 #endif
96 
97 	for (size_t i = 0; i < v->sz; i++) {
98 		x->data[i] = v->data[i] - w->data[i];
99 	}
100 
101 	return 0;
102 }
103 
zsl_vec_neg(struct zsl_vec * v)104 int zsl_vec_neg(struct zsl_vec *v)
105 {
106 	for (size_t i = 0; i < v->sz; i++) {
107 		v->data[i] = -v->data[i];
108 	}
109 
110 	return 0;
111 }
112 
zsl_vec_sum(struct zsl_vec ** v,size_t n,struct zsl_vec * w)113 int zsl_vec_sum(struct zsl_vec **v, size_t n, struct zsl_vec *w)
114 {
115 	size_t sz_last;
116 
117 	if (!n) {
118 		return -EINVAL;
119 	}
120 
121 	sz_last = v[0]->sz;
122 
123 #if CONFIG_ZSL_BOUNDS_CHECKS
124 	/* Make sure all vectors have the same size. */
125 	for (size_t i = 0; i < n; i++) {
126 		if (sz_last != v[i]->sz) {
127 			return -EINVAL;
128 		}
129 	}
130 #endif
131 
132 	/* Sum all vectors. */
133 	w->sz = sz_last;
134 	for (size_t i = 0; i < n; i++) {
135 		for (size_t j = 0; j < w->sz; j++) {
136 			w->data[j] += v[i]->data[j];
137 		}
138 	}
139 
140 	return 0;
141 }
142 
143 #if !asm_vec_scalar_add
zsl_vec_scalar_add(struct zsl_vec * v,zsl_real_t s)144 int zsl_vec_scalar_add(struct zsl_vec *v, zsl_real_t s)
145 {
146 	for (size_t i = 0; i < v->sz; i++) {
147 		v->data[i] += s;
148 	}
149 
150 	return 0;
151 }
152 #endif
153 
154 #if !asm_vec_scalar_mult
zsl_vec_scalar_mult(struct zsl_vec * v,zsl_real_t s)155 int zsl_vec_scalar_mult(struct zsl_vec *v, zsl_real_t s)
156 {
157 	for (size_t i = 0; i < v->sz; i++) {
158 		v->data[i] *= s;
159 	}
160 
161 	return 0;
162 }
163 #endif
164 
165 #if !asm_vec_scalar_div
zsl_vec_scalar_div(struct zsl_vec * v,zsl_real_t s)166 int zsl_vec_scalar_div(struct zsl_vec *v, zsl_real_t s)
167 {
168 	/* Avoid divide by zero errors. */
169 	if (s == 0) {
170 		return -EINVAL;
171 	}
172 
173 	for (size_t i = 0; i < v->sz; i++) {
174 		v->data[i] /= s;
175 	}
176 
177 	return 0;
178 }
179 #endif
180 
zsl_vec_dist(struct zsl_vec * v,struct zsl_vec * w)181 zsl_real_t zsl_vec_dist(struct zsl_vec *v, struct zsl_vec *w)
182 {
183 	int rc = 0;
184 
185 	zsl_real_t xdat[v->sz];
186 
187 	struct zsl_vec x = { .sz = v->sz, .data = xdat };
188 
189 	memset(xdat, 0, x.sz * sizeof(zsl_real_t));
190 
191 	rc = zsl_vec_sub(v, w, &x);
192 	if (rc) {
193 		return NAN;
194 	}
195 
196 	return zsl_vec_norm(&x);
197 }
198 
zsl_vec_dot(struct zsl_vec * v,struct zsl_vec * w,zsl_real_t * d)199 int zsl_vec_dot(struct zsl_vec *v, struct zsl_vec *w, zsl_real_t *d)
200 {
201 	zsl_real_t res = 0.0;
202 
203 #if CONFIG_ZSL_BOUNDS_CHECKS
204 	/* Make sure v and w are equal length. */
205 	if (v->sz != w->sz) {
206 		return -EINVAL;
207 	}
208 #endif
209 
210 	for (size_t i = 0; i < v->sz; i++) {
211 		res += v->data[i] * w->data[i];
212 	}
213 
214 	*d = res;
215 
216 	return 0;
217 }
218 
zsl_vec_norm(struct zsl_vec * v)219 zsl_real_t zsl_vec_norm(struct zsl_vec *v)
220 {
221 	/*
222 	 * |v| = sqrt( v[0]^2 + v[1]^2 + V[...]^2 )
223 	 */
224 	if (v == NULL) {
225 		return 0;
226 	}
227 	return ZSL_SQRT(zsl_vec_sum_of_sqrs(v));
228 }
229 
zsl_vec_project(struct zsl_vec * u,struct zsl_vec * v,struct zsl_vec * w)230 int zsl_vec_project(struct zsl_vec *u, struct zsl_vec *v, struct zsl_vec *w)
231 {
232 	zsl_real_t p;
233 	zsl_real_t t;
234 
235 #if CONFIG_ZSL_BOUNDS_CHECKS
236 	/* Make sure v, w and u are equal length. */
237 	if ((v->sz != w->sz) || (v->sz != u->sz)) {
238 		return -EINVAL;
239 	}
240 #endif
241 
242 	zsl_vec_copy(w, u);
243 	zsl_vec_dot(v, u, &p);
244 	zsl_vec_dot(u, u, &t);
245 	zsl_vec_scalar_mult(w, p / t);
246 
247 	return 0;
248 }
249 
zsl_vec_to_unit(struct zsl_vec * v)250 int zsl_vec_to_unit(struct zsl_vec *v)
251 {
252 	zsl_real_t norm = zsl_vec_norm(v);
253 
254 	/*
255 	 *            v
256 	 * unit(v) = ---
257 	 *           |v|
258 	 */
259 
260 	/* Avoid divide by zero errors. */
261 	if (norm != 0.0) {
262 		zsl_vec_scalar_mult(v, 1.0 / norm);
263 	} else {
264 		/* TODO: What is the best approach here? */
265 		/* On div by zero clear vector and return v[0] = 1.0. */
266 		zsl_vec_init(v);
267 		v->data[0] = 1.0;
268 	}
269 
270 	return 0;
271 }
272 
zsl_vec_cross(struct zsl_vec * v,struct zsl_vec * w,struct zsl_vec * c)273 int zsl_vec_cross(struct zsl_vec *v, struct zsl_vec *w, struct zsl_vec *c)
274 {
275 #if CONFIG_ZSL_BOUNDS_CHECKS
276 	/* Make sure this is a 3-vector. */
277 	if ((v->sz != 3) || (w->sz != 3) || (c->sz != 3)) {
278 		return -EINVAL;
279 	}
280 #endif
281 
282 	/*
283 	 * Given:
284 	 *
285 	 *       |Cx|      |Vx|      |Wx|
286 	 *   C = |Cy|, V = |Vy|, W = |Wy|
287 	 *       |Cz|      |Vz|      |Wz|
288 	 *
289 	 * The cross product can be represented as:
290 	 *
291 	 *   Cx = VyWz - VzWy
292 	 *   Cy = VzWx - VxWz
293 	 *   Cz = VxWy - VyWx
294 	 */
295 
296 	c->data[0] = v->data[1] * w->data[2] - v->data[2] * w->data[1];
297 	c->data[1] = v->data[2] * w->data[0] - v->data[0] * w->data[2];
298 	c->data[2] = v->data[0] * w->data[1] - v->data[1] * w->data[0];
299 
300 	return 0;
301 }
302 
zsl_vec_sum_of_sqrs(struct zsl_vec * v)303 zsl_real_t zsl_vec_sum_of_sqrs(struct zsl_vec *v)
304 {
305 	zsl_real_t dot = 0.0;
306 
307 	zsl_vec_dot(v, v, &dot);
308 
309 	return dot;
310 }
311 
zsl_vec_mean(struct zsl_vec ** v,size_t n,struct zsl_vec * m)312 int zsl_vec_mean(struct zsl_vec **v, size_t n, struct zsl_vec *m)
313 {
314 	int rc;
315 
316 #if CONFIG_ZSL_BOUNDS_CHECKS
317 	/* Make sure the mean vector has an approproate size. */
318 	if (m->sz != v[0]->sz) {
319 		return -EINVAL;
320 	}
321 #endif
322 
323 	/* sum also checks that all vectors have the same length. */
324 	rc = zsl_vec_sum(v, n, m);
325 	if (rc) {
326 		return rc;
327 	}
328 
329 	rc = zsl_vec_scalar_mult(m, 1.0 / (zsl_real_t) n);
330 
331 	return 0;
332 }
333 
zsl_vec_ar_mean(struct zsl_vec * v,zsl_real_t * m)334 int zsl_vec_ar_mean(struct zsl_vec *v, zsl_real_t *m)
335 {
336 	/* Avoid divide by zero errors. */
337 	if (v->sz < 1) {
338 		return -EINVAL;
339 	}
340 
341 	*m = 0.0;
342 	for (size_t i = 0; i < v->sz; i++) {
343 		*m += v->data[i];
344 	}
345 
346 	*m /= v->sz;
347 
348 	return 0;
349 }
350 
zsl_vec_rev(struct zsl_vec * v)351 int zsl_vec_rev(struct zsl_vec *v)
352 {
353 	zsl_real_t t;
354 	size_t start = 0;
355 	size_t end = v->sz - 1;
356 
357 	while (start < end) {
358 		t = v->data[start];
359 		v->data[start] = v->data[end];
360 		v->data[end] = t;
361 		start++;
362 		end--;
363 	}
364 
365 	return 0;
366 }
367 
zsl_vec_zte(struct zsl_vec * v)368 int zsl_vec_zte(struct zsl_vec *v)
369 {
370 	size_t x = 0;
371 	zsl_real_t epsilon = 1E-6;
372 
373 	for (size_t g = 0; g < v->sz; g++) {
374 		if ((v->data[g - x] >= 0.0 && v->data[g - x] < epsilon) ||
375 		    (v->data[g - x] <= 0.0 && v->data[g - x] > epsilon)) {
376 			for (size_t p = g - x; p < (v->sz - 1); p++) {
377 				v->data[p] = v->data[p + 1];
378 			}
379 			v->data[v->sz - 1] = 0.0;
380 			x++;
381 		}
382 	}
383 
384 	return 0;
385 }
386 
zsl_vec_is_equal(struct zsl_vec * v,struct zsl_vec * w,zsl_real_t eps)387 bool zsl_vec_is_equal(struct zsl_vec *v, struct zsl_vec *w, zsl_real_t eps)
388 {
389 	zsl_real_t c;
390 
391 	if (v->sz != w->sz) {
392 		return false;
393 	}
394 
395 	for (size_t i = 0; i < v->sz; i++) {
396 		c = v->data[i] - w->data[i];
397 		if (c >= eps || -c >= eps) {
398 			return false;
399 		}
400 	}
401 
402 	return true;
403 }
404 
zsl_vec_is_nonneg(struct zsl_vec * v)405 bool zsl_vec_is_nonneg(struct zsl_vec *v)
406 {
407 	for (size_t i = 0; i < v->sz; i++) {
408 		if (v->data[i] < 0.0) {
409 			return false;
410 		}
411 	}
412 
413 	return true;
414 }
415 
zsl_vec_contains(struct zsl_vec * v,zsl_real_t val,zsl_real_t eps)416 int zsl_vec_contains(struct zsl_vec *v, zsl_real_t val, zsl_real_t eps)
417 {
418 	zsl_real_t c;
419 	int count = 0;
420 
421 	for (size_t i = 0; i < v->sz; i++) {
422 		c = v->data[i] - val;
423 		if (c < eps && -c < eps) {
424 			count++;
425 		}
426 	}
427 
428 	return count;
429 }
430 
431 /**
432  * @brief Quicksort implementation used by zsl_vec_sort.
433  *
434  * @param v    	Unsorted input vector.
435  * @param low 	Low index value.
436  * @param high  High index value.
437  *
438  * @return 0 if everything executed properly, otherwise a negative error code.
439  */
zsl_vec_quicksort(struct zsl_vec * v,size_t low,size_t high)440 static int zsl_vec_quicksort(struct zsl_vec *v, size_t low, size_t high)
441 {
442 	size_t i, j, p;
443 	zsl_real_t t;
444 
445 	if (low < high) {
446 		p = low;
447 		i = low;
448 		j = high;
449 
450 		while (i < j) {
451 			while (v->data[i] <= v->data[p] && i <= high) {
452 				i++;
453 			}
454 			while (v->data[j] > v->data[p] && j >= low) {
455 				j--;
456 			}
457 			if (i < j) {
458 				t = v->data[i];
459 				v->data[i] = v->data[j];
460 				v->data[j] = t;
461 			}
462 		}
463 
464 		t = v->data[j];
465 		v->data[j] = v->data[p];
466 		v->data[p] = t;
467 
468 		zsl_vec_quicksort(v, low, i - 1);
469 		zsl_vec_quicksort(v, j + 1, high);
470 	}
471 
472 	return 0;
473 }
474 
zsl_vec_sort(struct zsl_vec * v,struct zsl_vec * w)475 int zsl_vec_sort(struct zsl_vec *v, struct zsl_vec *w)
476 {
477 	/* Set counters to zero. */
478 	size_t count = 0;
479 	size_t count2 = 0;
480 	size_t i, j, k;
481 
482 	ZSL_VECTOR_DEF(u, v->sz);
483 	zsl_vec_init(&u);
484 
485 	/* Copy the vector 'v' into the vector 'u' with no repeated values. */
486 	for (j = 0; j < v->sz; j++) {
487 		if (v->data[j] >= 1E-5 || v->data[j] <= 1E-5) {
488 			if (zsl_vec_contains(&u, v->data[j], 1E-5) == 0) {
489 				u.data[count] = v->data[j];
490 				count++;
491 			}
492 		}
493 	}
494 
495 	if (zsl_vec_contains(v, 0.0, 1E-5) > 0) {
496 		count++;
497 	}
498 
499 	u.sz = count;
500 
501 	/* Sort the vector with no repeated values 'u'. */
502 	zsl_vec_quicksort(&u, 0, count - 1);
503 
504 	/* Add back the repeated values in the correct order into the vector 'w'. */
505 	for (i = 0; i < count; i++) {
506 		for (k = 0; k < zsl_vec_contains(v, u.data[i], 1E-5); k++) {
507 			w->data[count2] = u.data[i];
508 			count2++;
509 		}
510 	}
511 
512 	return 0;
513 }
514 
zsl_vec_print(struct zsl_vec * v)515 int zsl_vec_print(struct zsl_vec *v)
516 {
517 	for (size_t g = 0; g < v->sz; g++) {
518 		printf("%f ", v->data[g]);
519 	}
520 	printf("\n\n");
521 
522 	return 0;
523 }
524