GRASS 8 Programmer's Manual 8.6.0dev(2026)-0f6a7341fc
Loading...
Searching...
No Matches
blas_level_1.c
Go to the documentation of this file.
1/*****************************************************************************
2 *
3 * MODULE: Grass numerical math interface
4 * AUTHOR(S): Soeren Gebbert, Berlin (GER) Dec 2006
5 * soerengebbert <at> googlemail <dot> com
6 *
7 * PURPOSE: grass blas implementation
8 * part of the gmath library
9 *
10 * SPDX-FileCopyrightText: 2010 GRASS Development Team
11 * SPDX-License-Identifier: GPL-2.0-or-later
12 *
13 *****************************************************************************/
14
15#include <math.h>
16#include <unistd.h>
17#include <stdio.h>
18#include <string.h>
19#include <stdlib.h>
20
21#include <grass/gis.h>
22#include <grass/gmath.h>
23
24/* **************************************************************** */
25/* *************** D O U B L E ************************************ */
26/* **************************************************************** */
27
28/*!
29 * \brief Compute the dot product of vector x and y
30 *
31 * \f[ a = {\bf x}^T {\bf y} \f]
32 *
33 * The functions creates its own parallel OpenMP region.
34 * It can be called within a parallel OpenMP region if nested parallelism is
35 * supported by the compiler.
36 *
37 * \param x (double *)
38 * \param y (double *)
39 * \param value (double *) -- the return value
40 * \param rows (int)
41 * \return (void)
42 *
43 * */
44void G_math_d_x_dot_y(double *x, double *y, double *value, int rows)
45{
46 int i;
47
48 double s = 0.0;
49
50#pragma omp parallel for schedule(static) reduction(+ : s)
51 for (i = rows - 1; i >= 0; i--) {
52 s += x[i] * y[i];
53 }
54#pragma omp single
55 {
56 *value = s;
57 }
58 return;
59}
60
61/*!
62 * \brief Compute the euclid norm of vector x
63 *
64 * \f[ a = ||{\bf x}||_2 \f]
65 *
66 * The functions creates its own parallel OpenMP region.
67 * It can be called within a parallel OpenMP region if nested parallelism is
68 * supported by the compiler.
69 *
70 * \param x (double *) -- the vector
71 * \param value (double *) -- the return value
72 * \param rows (int)
73 * \return (void)
74 *
75 * */
76void G_math_d_euclid_norm(double *x, double *value, int rows)
77{
78 int i;
79
80 double s = 0.0;
81
82#pragma omp parallel for schedule(static) reduction(+ : s)
83 for (i = rows - 1; i >= 0; i--) {
84 s += x[i] * x[i];
85 }
86#pragma omp single
87 {
88 *value = sqrt(s);
89 }
90 return;
91}
92
93/*!
94 * \brief Compute the asum norm of vector x
95 *
96 * \f[ a = ||{\bf x}||_1 \f]
97 *
98 * The functions creates its own parallel OpenMP region.
99 * It can be called within a parallel OpenMP region if nested parallelism is
100 * supported by the compiler.
101 *
102 * \param x (double *)-- the vector
103 * \param value (double *) -- the return value
104 * \param rows (int)
105 * \return (void)
106 *
107 * */
108void G_math_d_asum_norm(double *x, double *value, int rows)
109{
110 int i = 0;
111
112 double s = 0.0;
113
114#pragma omp parallel for schedule(static) reduction(+ : s)
115 for (i = rows - 1; i >= 0; i--) {
116 s += fabs(x[i]);
117 }
118#pragma omp single
119 {
120 *value = s;
121 }
122 return;
123}
124
125/*!
126 * \brief Compute the maximum norm of vector x
127 *
128 * \f[ a = ||{\bf x}||_\infty \f]
129 *
130 * This function is not multi-threaded
131 *
132 * \param x (double *)-- the vector
133 * \param value (double *) -- the return value
134 * \param rows (int)
135 * \return (void)
136 *
137 * */
138void G_math_d_max_norm(double *x, double *value, int rows)
139{
140 int i;
141
142 double max = 0.0;
143
144 max = fabs(x[rows - 1]);
145 for (i = rows - 2; i >= 0; i--) {
146 if (max < fabs(x[i]))
147 max = fabs(x[i]);
148 }
149
150 *value = max;
151}
152
153/*!
154 * \brief Scales vectors x and y with the scalars a and b and adds them
155 *
156 * \f[ {\bf z} = a{\bf x} + b{\bf y} \f]
157 *
158 * This function is multi-threaded with OpenMP and can be called within a
159 * parallel OpenMP region.
160 *
161 * \param x (double *)
162 * \param y (double *)
163 * \param z (double *)
164 * \param a (double)
165 * \param b (double)
166 * \param rows (int)
167 * \return (void)
168 *
169 * */
170void G_math_d_ax_by(double *x, double *y, double *z, double a, double b,
171 int rows)
172{
173 int i;
174
175 /*find specific cases */
176 if (b == 0.0) {
177#pragma omp for schedule(static)
178 for (i = rows - 1; i >= 0; i--) {
179 z[i] = a * x[i];
180 }
181 }
182 else if ((a == 1.0) && (b == 1.0)) {
183#pragma omp for schedule(static)
184 for (i = rows - 1; i >= 0; i--) {
185 z[i] = x[i] + y[i];
186 }
187 }
188 else if ((a == 1.0) && (b == -1.0)) {
189#pragma omp for schedule(static)
190 for (i = rows - 1; i >= 0; i--) {
191 z[i] = x[i] - y[i];
192 }
193 }
194 else if (a == b) {
195#pragma omp for schedule(static)
196 for (i = rows - 1; i >= 0; i--) {
197 z[i] = a * (x[i] + y[i]);
198 }
199 }
200 else if (b == -1.0) {
201#pragma omp for schedule(static)
202 for (i = rows - 1; i >= 0; i--) {
203 z[i] = a * x[i] - y[i];
204 }
205 }
206 else if (b == 1.0) {
207#pragma omp for schedule(static)
208 for (i = rows - 1; i >= 0; i--) {
209 z[i] = a * x[i] + y[i];
210 }
211 }
212 else {
213#pragma omp for schedule(static)
214 for (i = rows - 1; i >= 0; i--) {
215 z[i] = a * x[i] + b * y[i];
216 }
217 }
218
219 return;
220}
221
222/*!
223 * \brief Copy the vector x to y
224 *
225 * \f[ {\bf y} = {\bf x} \f]
226 *
227 * This function is not multi-threaded
228 *
229 * \param x (double *)
230 * \param y (double *)
231 * \param rows (int)
232 *
233 * */
234void G_math_d_copy(double *x, double *y, int rows)
235{
236 y = memcpy(y, x, rows * sizeof(double));
237
238 return;
239}
240
241/* **************************************************************** */
242/* *************** F L O A T ************************************** */
243/* **************************************************************** */
244
245/*!
246 * \brief Compute the dot product of vector x and y
247 *
248 * \f[ a = {\bf x}^T {\bf y} \f]
249 *
250 * The functions creates its own parallel OpenMP region.
251 * It can be called within a parallel OpenMP region if nested parallelism is
252 * supported by the compiler.
253 *
254 * \param x (float *)
255 * \param y (float *)
256 * \param value (float *) -- the return value
257 * \param rows (int)
258 * \return (void)
259 *
260 * */
261void G_math_f_x_dot_y(float *x, float *y, float *value, int rows)
262{
263 int i;
264
265 float s = 0.0;
266
267#pragma omp parallel for schedule(static) reduction(+ : s)
268 for (i = rows - 1; i >= 0; i--) {
269 s += x[i] * y[i];
270 }
271#pragma omp single
272 {
273 *value = s;
274 }
275 return;
276}
277
278/*!
279 * \brief Compute the euclid norm of vector x
280 *
281 * \f[ a = ||{\bf x}||_2 \f]
282 *
283 * The functions creates its own parallel OpenMP region.
284 * It can be called within a parallel OpenMP region if nested parallelism is
285 * supported by the compiler.
286 *
287 * \param x (double *) -- the vector
288 * \param value (float *) -- the return value
289 * \param rows (int)
290 * \return (void)
291 *
292 * */
293void G_math_f_euclid_norm(float *x, float *value, int rows)
294{
295 int i;
296
297 float s = 0.0;
298
299#pragma omp parallel for schedule(static) reduction(+ : s)
300 for (i = rows - 1; i >= 0; i--) {
301 s += x[i] * x[i];
302 }
303#pragma omp single
304 {
305 *value = sqrt(s);
306 }
307 return;
308}
309
310/*!
311 * \brief Compute the asum norm of vector x
312 *
313 * \f[ a = ||{\bf x}||_1 \f]
314 *
315 * The functions creates its own parallel OpenMP region.
316 * It can be called within a parallel OpenMP region if nested parallelism is
317 * supported by the compiler.
318 *
319 * \param x (float *)-- the vector
320 * \param value (float *) -- the return value
321 * \param rows (int)
322 * \return (void)
323 *
324 * */
325void G_math_f_asum_norm(float *x, float *value, int rows)
326{
327 int i;
328
329 float s = 0.0;
330
331#pragma omp parallel for schedule(static) private(i) reduction(+ : s)
332 for (i = 0; i < rows; i++) {
333 s += fabs(x[i]);
334 }
335#pragma omp single
336 {
337 *value = s;
338 }
339 return;
340}
341
342/*!
343 * \brief Compute the maximum norm of vector x
344 *
345 * \f[ a = ||{\bf x}||_\infty \f]
346 *
347 * This function is not multi-threaded
348 *
349 * \param x (float *)-- the vector
350 * \param value (float *) -- the return value
351 * \param rows (int)
352 * \return (void)
353 *
354 * */
355void G_math_f_max_norm(float *x, float *value, int rows)
356{
357 int i;
358
359 float max = 0.0;
360
361 max = fabs(x[rows - 1]);
362 for (i = rows - 2; i >= 0; i--) {
363 if (max < fabs(x[i]))
364 max = fabs(x[i]);
365 }
366 *value = max;
367 return;
368}
369
370/*!
371 * \brief Scales vectors x and y with the scalars a and b and adds them
372 *
373 * \f[ {\bf z} = a{\bf x} + b{\bf y} \f]
374 *
375 * This function is multi-threaded with OpenMP and can be called within a
376 * parallel OpenMP region.
377 *
378 * \param x (float *)
379 * \param y (float *)
380 * \param z (float *)
381 * \param a (float)
382 * \param b (float)
383 * \param rows (int)
384 * \return (void)
385 *
386 * */
387void G_math_f_ax_by(float *x, float *y, float *z, float a, float b, int rows)
388{
389 int i;
390
391 /*find specific cases */
392 if (b == 0.0) {
393#pragma omp for schedule(static)
394 for (i = rows - 1; i >= 0; i--) {
395 z[i] = a * x[i];
396 }
397 }
398 else if ((a == 1.0) && (b == 1.0)) {
399#pragma omp for schedule(static)
400 for (i = rows - 1; i >= 0; i--) {
401 z[i] = x[i] + y[i];
402 }
403 }
404 else if ((a == 1.0) && (b == -1.0)) {
405#pragma omp for schedule(static)
406 for (i = rows - 1; i >= 0; i--) {
407 z[i] = x[i] - y[i];
408 }
409 }
410 else if (a == b) {
411#pragma omp for schedule(static)
412 for (i = rows - 1; i >= 0; i--) {
413 z[i] = a * (x[i] + y[i]);
414 }
415 }
416 else if (b == -1.0) {
417#pragma omp for schedule(static)
418 for (i = rows - 1; i >= 0; i--) {
419 z[i] = a * x[i] - y[i];
420 }
421 }
422 else if (b == 1.0) {
423#pragma omp for schedule(static)
424 for (i = rows - 1; i >= 0; i--) {
425 z[i] = a * x[i] + y[i];
426 }
427 }
428 else {
429#pragma omp for schedule(static)
430 for (i = rows - 1; i >= 0; i--) {
431 z[i] = a * x[i] + b * y[i];
432 }
433 }
434
435 return;
436}
437
438/*!
439 * \brief Copy the vector x to y
440 *
441 * \f[ {\bf y} = {\bf x} \f]
442 *
443 * This function is not multi-threaded
444 *
445 * \param x (float *)
446 * \param y (float *)
447 * \param rows (int)
448 *
449 * */
450void G_math_f_copy(float *x, float *y, int rows)
451{
452 y = memcpy(y, x, rows * sizeof(float));
453
454 return;
455}
456
457/* **************************************************************** */
458/* *************** I N T E G E R ********************************** */
459/* **************************************************************** */
460
461/*!
462 * \brief Compute the dot product of vector x and y
463 *
464 * \f[ a = {\bf x}^T {\bf y} \f]
465 *
466 * The functions creates its own parallel OpenMP region.
467 * It can be called within a parallel OpenMP region if nested parallelism is
468 * supported by the compiler.
469 *
470 * \param x (int *)
471 * \param y (int *)
472 * \param value (double *) -- the return value
473 * \param rows (int)
474 * \return (void)
475 *
476 * */
477void G_math_i_x_dot_y(int *x, int *y, double *value, int rows)
478{
479 int i;
480
481 double s = 0.0;
482
483#pragma omp parallel for schedule(static) reduction(+ : s)
484 for (i = rows - 1; i >= 0; i--) {
485 s += x[i] * y[i];
486 }
487#pragma omp single
488 {
489 *value = s;
490 }
491 return;
492}
493
494/*!
495 * \brief Compute the euclid norm of vector x
496 *
497 * \f[ a = ||{\bf x}||_2 \f]
498 *
499 * The functions creates its own parallel OpenMP region.
500 * It can be called within a parallel OpenMP region if nested parallelism is
501 * supported by the compiler.
502 *
503 * \param x (int *) -- the vector
504 * \param value (double *) -- the return value
505 * \param rows (int)
506 * \return (void)
507 *
508 * */
509void G_math_i_euclid_norm(int *x, double *value, int rows)
510{
511 int i;
512
513 double s = 0.0;
514
515#pragma omp parallel for schedule(static) reduction(+ : s)
516 for (i = rows - 1; i >= 0; i--) {
517 s += x[i] * x[i];
518 }
519#pragma omp single
520 {
521 *value = sqrt(s);
522 }
523 return;
524}
525
526/*!
527 * \brief Compute the asum norm of vector x
528 *
529 * \f[ a = ||{\bf x}||_1 \f]
530 *
531 * The functions creates its own parallel OpenMP region.
532 * It can be called within a parallel OpenMP region if nested parallelism is
533 * supported by the compiler.
534 *
535 * \param x (int *)-- the vector
536 * \param value (double *) -- the return value
537 * \param rows (int)
538 * \return (void)
539 *
540 * */
541void G_math_i_asum_norm(int *x, double *value, int rows)
542{
543 int i;
544
545 double s = 0.0;
546
547#pragma omp parallel for schedule(static) reduction(+ : s)
548 for (i = rows - 1; i >= 0; i--) {
549 s += (double)abs(x[i]);
550 }
551#pragma omp single
552 {
553 *value = s;
554 }
555 return;
556}
557
558/*!
559 * \brief Compute the maximum norm of vector x
560 *
561 * \f[ a = ||{\bf x}||_\infty \f]
562 *
563 * This function is not multi-threaded
564 *
565 * \param x (int *)-- the vector
566 * \param value (int *) -- the return value
567 * \param rows (int)
568 * \return (void)
569 *
570 * */
571void G_math_i_max_norm(int *x, int *value, int rows)
572{
573 int i;
574
575 int max = 0.0;
576
577 max = abs(x[rows - 1]);
578 for (i = rows - 2; i >= 0; i--) {
579 if (max < abs(x[i]))
580 max = abs(x[i]);
581 }
582
583 *value = max;
584}
585
586/*!
587 * \brief Scales vectors x and y with the scalars a and b and adds them
588 *
589 * \f[ {\bf z} = a{\bf x} + b{\bf y} \f]
590 *
591 * This function is multi-threaded with OpenMP and can be called within a
592 * parallel OpenMP region.
593 *
594 * \param x (int *)
595 * \param y (int *)
596 * \param z (int *)
597 * \param a (int)
598 * \param b (int)
599 * \param rows (int)
600 * \return (void)
601 *
602 * */
603void G_math_i_ax_by(int *x, int *y, int *z, int a, int b, int rows)
604{
605 int i;
606
607 /*find specific cases */
608 if (b == 0.0) {
609#pragma omp for schedule(static)
610 for (i = rows - 1; i >= 0; i--) {
611 z[i] = a * x[i];
612 }
613 }
614 else if ((a == 1.0) && (b == 1.0)) {
615#pragma omp for schedule(static)
616 for (i = rows - 1; i >= 0; i--) {
617 z[i] = x[i] + y[i];
618 }
619 }
620 else if ((a == 1.0) && (b == -1.0)) {
621#pragma omp for schedule(static)
622 for (i = rows - 1; i >= 0; i--) {
623 z[i] = x[i] - y[i];
624 }
625 }
626 else if (a == b) {
627#pragma omp for schedule(static)
628 for (i = rows - 1; i >= 0; i--) {
629 z[i] = a * (x[i] + y[i]);
630 }
631 }
632 else if (b == -1.0) {
633#pragma omp for schedule(static)
634 for (i = rows - 1; i >= 0; i--) {
635 z[i] = a * x[i] - y[i];
636 }
637 }
638 else if (b == 1.0) {
639#pragma omp for schedule(static)
640 for (i = rows - 1; i >= 0; i--) {
641 z[i] = a * x[i] + y[i];
642 }
643 }
644 else {
645#pragma omp for schedule(static)
646 for (i = rows - 1; i >= 0; i--) {
647 z[i] = a * x[i] + b * y[i];
648 }
649 }
650
651 return;
652}
653
654/*!
655 * \brief Copy the vector x to y
656 *
657 * \f[ {\bf y} = {\bf x} \f]
658 *
659 * This function is not multi-threaded
660 *
661 * \param x (int *)
662 * \param y (int *)
663 * \param rows (int)
664 *
665 * */
666void G_math_i_copy(int *x, int *y, int rows)
667{
668 y = memcpy(y, x, rows * sizeof(int));
669
670 return;
671}
void G_math_i_euclid_norm(int *x, double *value, int rows)
Compute the euclid norm of vector x.
void G_math_d_asum_norm(double *x, double *value, int rows)
Compute the asum norm of vector x.
void G_math_f_asum_norm(float *x, float *value, int rows)
Compute the asum norm of vector x.
void G_math_d_max_norm(double *x, double *value, int rows)
Compute the maximum norm of vector x.
void G_math_i_asum_norm(int *x, double *value, int rows)
Compute the asum norm of vector x.
void G_math_f_max_norm(float *x, float *value, int rows)
Compute the maximum norm of vector x.
void G_math_d_x_dot_y(double *x, double *y, double *value, int rows)
Compute the dot product of vector x and y.
void G_math_f_euclid_norm(float *x, float *value, int rows)
Compute the euclid norm of vector x.
void G_math_d_ax_by(double *x, double *y, double *z, double a, double b, int rows)
Scales vectors x and y with the scalars a and b and adds them.
void G_math_f_x_dot_y(float *x, float *y, float *value, int rows)
Compute the dot product of vector x and y.
void G_math_f_ax_by(float *x, float *y, float *z, float a, float b, int rows)
Scales vectors x and y with the scalars a and b and adds them.
void G_math_d_copy(double *x, double *y, int rows)
Copy the vector x to y.
void G_math_i_ax_by(int *x, int *y, int *z, int a, int b, int rows)
Scales vectors x and y with the scalars a and b and adds them.
void G_math_d_euclid_norm(double *x, double *value, int rows)
Compute the euclid norm of vector x.
void G_math_i_max_norm(int *x, int *value, int rows)
Compute the maximum norm of vector x.
void G_math_i_copy(int *x, int *y, int rows)
Copy the vector x to y.
void G_math_i_x_dot_y(int *x, int *y, double *value, int rows)
Compute the dot product of vector x and y.
void G_math_f_copy(float *x, float *y, int rows)
Copy the vector x to y.
#define max(x, y)
Definition draw2.c:30
double b
Definition r_raster.c:37
#define x