GRASS 8 Programmer's Manual 8.6.0dev(2026)-1878fdfec5
Loading...
Searching...
No Matches
n_arrays_calc.c
Go to the documentation of this file.
1/*****************************************************************************
2 *
3 * MODULE: Grass PDE Numerical Library
4 * AUTHOR(S): Soeren Gebbert, Berlin (GER) Dec 2006
5 * soerengebbert <at> gmx <dot> de
6 *
7 * PURPOSE: Higher level array management functions
8 * part of the gpde library
9 *
10 * SPDX-FileCopyrightText: 2000 GRASS Development Team
11 * SPDX-License-Identifier: GPL-2.0-or-later
12 *
13 *****************************************************************************/
14
15#include <math.h>
16
17#include <grass/N_pde.h>
18#include <grass/raster.h>
19#include <grass/glocale.h>
20
21/* ******************** 2D ARRAY FUNCTIONS *********************** */
22
23/*!
24 * \brief Copy the source N_array_2d struct to the target N_array_2d struct
25 *
26 * The arrays must have the same size and the same offset.
27 *
28 * The array types can be mixed, the values are automatically casted
29 * and the null values are set accordingly.
30 * <br><br>
31 * If you copy a cell array into a dcell array, the values are casted to dcell
32 * and the null values are converted from cell-null to dcell-null <br><br> This
33 * function can be called in a parallel region defined with OpenMP. The copy
34 * loop is parallelize with a openmp for pragma.
35 *
36 * \param source N_array_2d *
37 * \param target N_array_2d *
38 * \return void
39 * */
41{
42 int i;
43 int null = 0;
44
45#pragma omp single
46 {
47 if (source->cols_intern != target->cols_intern)
48 G_fatal_error("N_copy_array_2d: the arrays are not of equal size");
49
50 if (source->rows_intern != target->rows_intern)
51 G_fatal_error("N_copy_array_2d: the arrays are not of equal size");
52
53 G_debug(3, "N_copy_array_2d: copy source array to target array size %i",
54 source->cols_intern * source->rows_intern);
55 }
56
57#pragma omp for
58 for (i = 0; i < source->cols_intern * source->rows_intern; i++) {
59 null = 0;
60 if (source->type == CELL_TYPE) {
61 if (Rast_is_c_null_value((void *)&source->cell_array[i]))
62 null = 1;
63
64 if (target->type == CELL_TYPE) {
65 target->cell_array[i] = source->cell_array[i];
66 }
67 if (target->type == FCELL_TYPE) {
68 if (null)
69 Rast_set_f_null_value((void *)&(target->fcell_array[i]), 1);
70 else
71 target->fcell_array[i] = (FCELL)source->cell_array[i];
72 }
73 if (target->type == DCELL_TYPE) {
74 if (null)
75 Rast_set_d_null_value((void *)&(target->dcell_array[i]), 1);
76 else
77 target->dcell_array[i] = (DCELL)source->cell_array[i];
78 }
79 }
80 if (source->type == FCELL_TYPE) {
81 if (Rast_is_f_null_value((void *)&source->fcell_array[i]))
82 null = 1;
83
84 if (target->type == CELL_TYPE) {
85 if (null)
86 Rast_set_c_null_value((void *)&(target->cell_array[i]), 1);
87 else
88 target->cell_array[i] = (CELL)source->fcell_array[i];
89 }
90 if (target->type == FCELL_TYPE) {
91 target->fcell_array[i] = source->fcell_array[i];
92 }
93 if (target->type == DCELL_TYPE) {
94 if (null)
95 Rast_set_d_null_value((void *)&(target->dcell_array[i]), 1);
96 else
97 target->dcell_array[i] = (DCELL)source->fcell_array[i];
98 }
99 }
100 if (source->type == DCELL_TYPE) {
101 if (Rast_is_d_null_value((void *)&source->dcell_array[i]))
102 null = 1;
103
104 if (target->type == CELL_TYPE) {
105 if (null)
106 Rast_set_c_null_value((void *)&(target->cell_array[i]), 1);
107 else
108 target->cell_array[i] = (CELL)source->dcell_array[i];
109 }
110 if (target->type == FCELL_TYPE) {
111 if (null)
112 Rast_set_f_null_value((void *)&(target->fcell_array[i]), 1);
113 else
114 target->fcell_array[i] = (FCELL)source->dcell_array[i];
115 }
116 if (target->type == DCELL_TYPE) {
117 target->dcell_array[i] = source->dcell_array[i];
118 }
119 }
120 }
121
122 return;
123}
124
125/*!
126 * \brief Calculate the norm of the two input arrays
127 *
128 * The norm can be of type N_MAXIMUM_NORM or N_EUKLID_NORM.
129 * All arrays must have equal sizes and offsets.
130 * The complete data array inclusively offsets is used for norm calculation.
131 * Only non-null values are used to calculate the norm.
132 *
133
134 * \param a N_array_2d *
135 * \param b N_array_2d *
136 * \param type the type of the norm -> N_MAXIMUM_NORM, N_EUKLID_NORM
137 * \return double the calculated norm
138 * */
140{
141 int i = 0;
142 double norm = 0.0, tmp = 0.0;
143 double v1 = 0.0, v2 = 0.0;
144
145 if (a->cols_intern != b->cols_intern)
146 G_fatal_error("N_norm_array_2d: the arrays are not of equal size");
147
148 if (a->rows_intern != b->rows_intern)
149 G_fatal_error("N_norm_array_2d: the arrays are not of equal size");
150
151 G_debug(3, "N_norm_array_2d: norm of a and b size %i",
152 a->cols_intern * a->rows_intern);
153
154 for (i = 0; i < a->cols_intern * a->rows_intern; i++) {
155 v1 = 0.0;
156 v2 = 0.0;
157
158 if (a->type == CELL_TYPE) {
159 if (!Rast_is_f_null_value((void *)&(a->cell_array[i])))
160 v1 = (double)a->cell_array[i];
161 }
162 if (a->type == FCELL_TYPE) {
163 if (!Rast_is_f_null_value((void *)&(a->fcell_array[i])))
164 v1 = (double)a->fcell_array[i];
165 }
166 if (a->type == DCELL_TYPE) {
167 if (!Rast_is_f_null_value((void *)&(a->dcell_array[i])))
168 v1 = (double)a->dcell_array[i];
169 }
170 if (b->type == CELL_TYPE) {
171 if (!Rast_is_f_null_value((void *)&(b->cell_array[i])))
172 v2 = (double)b->cell_array[i];
173 }
174 if (b->type == FCELL_TYPE) {
175 if (!Rast_is_f_null_value((void *)&(b->fcell_array[i])))
176 v2 = (double)b->fcell_array[i];
177 }
178 if (b->type == DCELL_TYPE) {
179 if (!Rast_is_f_null_value((void *)&(b->dcell_array[i])))
180 v2 = (double)b->dcell_array[i];
181 }
182
183 if (type == N_MAXIMUM_NORM) {
184 tmp = fabs(v2 - v1);
185 if ((tmp > norm))
186 norm = tmp;
187 }
188 if (type == N_EUKLID_NORM) {
189 norm += fabs(v2 - v1);
190 }
191 }
192
193 return norm;
194}
195
196/*!
197 * \brief Calculate basic statistics of the N_array_2d struct
198 *
199 * Calculates the minimum, maximum, sum and the number of
200 * non null values. The array offset can be included in the calculation.
201 *
202 * \param a N_array_2d * - input array
203 * \param min double* - variable to store the computed minimum
204 * \param max double* - variable to store the computed maximum
205 * \param sum double* - variable to store the computed sum
206 * \param nonull int* - variable to store the number of non null values
207 * \param withoffset - if 1 include offset values in statistic calculation, 0
208 * otherwise \return void
209 * */
210void N_calc_array_2d_stats(N_array_2d *a, double *min, double *max, double *sum,
211 int *nonull, int withoffset)
212{
213 int i, j;
214 double val;
215
216 *sum = 0.0;
217 *nonull = 0;
218
219 if (withoffset == 1) {
220
221 *min = (double)N_get_array_2d_d_value(a, 0 - a->offset, 0 - a->offset);
222 *max = (double)N_get_array_2d_d_value(a, 0 - a->offset, 0 - a->offset);
223
224 for (j = 0 - a->offset; j < a->rows + a->offset; j++) {
225 for (i = 0 - a->offset; i < a->cols + a->offset; i++) {
226 if (!N_is_array_2d_value_null(a, i, j)) {
227 val = (double)N_get_array_2d_d_value(a, i, j);
228 if (*min > val)
229 *min = val;
230 if (*max < val)
231 *max = val;
232 *sum += val;
233 (*nonull)++;
234 }
235 }
236 }
237 }
238 else {
239
240 *min = (double)N_get_array_2d_d_value(a, 0, 0);
241 *max = (double)N_get_array_2d_d_value(a, 0, 0);
242
243 for (j = 0; j < a->rows; j++) {
244 for (i = 0; i < a->cols; i++) {
245 if (!N_is_array_2d_value_null(a, i, j)) {
246 val = (double)N_get_array_2d_d_value(a, i, j);
247 if (*min > val)
248 *min = val;
249 if (*max < val)
250 *max = val;
251 *sum += val;
252 (*nonull)++;
253 }
254 }
255 }
256 }
257
258 G_debug(3,
259 "N_calc_array_2d_stats: compute array stats, min %g, max %g, sum "
260 "%g, nonull %i",
261 *min, *max, *sum, *nonull);
262 return;
263}
264
265/*!
266 * \brief Perform calculations with two input arrays,
267 * the result is written to a third array.
268 *
269 * All arrays must have equal sizes and offsets.
270 * The complete data array inclusively offsets is used for calculations.
271 * Only non-null values are computed. If one array value is null,
272 * the result array value will be null too.
273 * <br><br>
274 * If a division with zero is detected, the resulting arrays
275 * value will set to null and not to NaN.
276 * <br><br>
277 * The result array is optional, if the result arrays points to NULL,
278 * a new array will be allocated with the largest arrays data type
279 * (CELL, FCELL or DCELL) used by the input arrays.
280 * <br><br>
281 * the array computations can be of the following forms:
282 *
283 * <ul>
284 * <li>result = a + b -> N_ARRAY_SUM</li>
285 * <li>result = a - b -> N_ARRAY_DIF</li>
286 * <li>result = a * b -> N_ARRAY_MUL</li>
287 * <li>result = a / b -> N_ARRAY_DIV</li>
288 * </ul>
289 *
290 * \param a N_array_2d * - first input array
291 * \param b N_array_2d * - second input array
292 * \param result N_array_2d * - the optional result array
293 * \param type - the type of calculation
294 * \return N_array_2d * - the pointer to the result array
295 * */
297 int type)
298{
299 N_array_2d *c;
300 int i, j, setnull = 0;
301 double va = 0.0, vb = 0.0, vc = 0.0; /*variables used for calculation */
302
303 /*Set the pointer */
304 c = result;
305
306#pragma omp single
307 {
308 /*Check the array sizes */
309 if (a->cols_intern != b->cols_intern)
310 G_fatal_error("N_math_array_2d: the arrays are not of equal size");
311 if (a->rows_intern != b->rows_intern)
312 G_fatal_error("N_math_array_2d: the arrays are not of equal size");
313 if (a->offset != b->offset)
314 G_fatal_error("N_math_array_2d: the arrays have different offsets");
315
316 G_debug(3, "N_math_array_2d: mathematical calculations, size: %i",
317 a->cols_intern * a->rows_intern);
318
319 /*if the result array is null, allocate a new one, use the
320 * largest data type of the input arrays*/
321 if (c == NULL) {
322 if (a->type == DCELL_TYPE || b->type == DCELL_TYPE) {
323 c = N_alloc_array_2d(a->cols, a->rows, a->offset, DCELL_TYPE);
324 G_debug(3, "N_math_array_2d: array of type DCELL_TYPE created");
325 }
326 else if (a->type == FCELL_TYPE || b->type == FCELL_TYPE) {
327 c = N_alloc_array_2d(a->cols, a->rows, a->offset, FCELL_TYPE);
328 G_debug(3, "N_math_array_2d: array of type FCELL_TYPE created");
329 }
330 else {
331 c = N_alloc_array_2d(a->cols, a->rows, a->offset, CELL_TYPE);
332 G_debug(3, "N_math_array_2d: array of type CELL_TYPE created");
333 }
334 }
335 else {
336 /*Check the array sizes */
337 if (a->cols_intern != c->cols_intern)
339 "N_math_array_2d: the arrays are not of equal size");
340 if (a->rows_intern != c->rows_intern)
342 "N_math_array_2d: the arrays are not of equal size");
343 if (a->offset != c->offset)
345 "N_math_array_2d: the arrays have different offsets");
346 }
347 }
348
349#pragma omp for private(va, vb, vc, setnull)
350 for (j = 0 - a->offset; j < a->rows + a->offset; j++) {
351 for (i = 0 - a->offset; i < a->cols + a->offset; i++) {
352 if (!N_is_array_2d_value_null(a, i, j) &&
354 /*we always calculate internally with double values */
357 vc = 0;
358 setnull = 0;
359
360 switch (type) {
361 case N_ARRAY_SUM:
362 vc = va + vb;
363 break;
364 case N_ARRAY_DIF:
365 vc = va - vb;
366 break;
367 case N_ARRAY_MUL:
368 vc = va * vb;
369 break;
370 case N_ARRAY_DIV:
371 if (vb != 0)
372 vc = va / vb;
373 else
374 setnull = 1;
375 break;
376 }
377
378 if (c->type == CELL_TYPE) {
379 if (setnull)
381 else
383 }
384 if (c->type == FCELL_TYPE) {
385 if (setnull)
387 else
389 }
390 if (c->type == DCELL_TYPE) {
391 if (setnull)
393 else
395 }
396 }
397 else {
399 }
400 }
401 }
402
403 return c;
404}
405
406/*!
407 * \brief Convert all null values to zero values
408 *
409 * The complete data array inclusively offsets is used.
410 * The array data types are automatically recognized.
411 *
412 * \param a N_array_2d *
413 * \return int - number of replaced values
414 * */
416{
417 int i = 0, count = 0;
418
419 G_debug(3, "N_convert_array_2d_null_to_zero: convert array of size %i",
420 a->cols_intern * a->rows_intern);
421
422 if (a->type == CELL_TYPE)
423 for (i = 0; i < a->cols_intern * a->rows_intern; i++) {
424 if (Rast_is_c_null_value((void *)&(a->cell_array[i]))) {
425 a->cell_array[i] = 0;
426 count++;
427 }
428 }
429
430 if (a->type == FCELL_TYPE)
431 for (i = 0; i < a->cols_intern * a->rows_intern; i++) {
432 if (Rast_is_f_null_value((void *)&(a->fcell_array[i]))) {
433 a->fcell_array[i] = 0.0;
434 count++;
435 }
436 }
437
438 if (a->type == DCELL_TYPE)
439 for (i = 0; i < a->cols_intern * a->rows_intern; i++) {
440 if (Rast_is_d_null_value((void *)&(a->dcell_array[i]))) {
441 a->dcell_array[i] = 0.0;
442 count++;
443 }
444 }
445
446 if (a->type == CELL_TYPE)
447 G_debug(2,
448 "N_convert_array_2d_null_to_zero: %i values of type CELL_TYPE "
449 "are converted",
450 count);
451 if (a->type == FCELL_TYPE)
452 G_debug(2,
453 "N_convert_array_2d_null_to_zero: %i values of type "
454 "FCELL_TYPE are converted",
455 count);
456 if (a->type == DCELL_TYPE)
457 G_debug(2,
458 "N_convert_array_2d_null_to_zero: %i values of type "
459 "DCELL_TYPE are converted",
460 count);
461
462 return count;
463}
464
465/* ******************** 3D ARRAY FUNCTIONS *********************** */
466
467/*!
468 * \brief Copy the source N_array_3d struct to the target N_array_3d struct
469 *
470 * The arrays must have the same size and the same offset.
471 *
472 * The array data types can be mixed, the values are automatically casted
473 * and the null values are set accordingly.
474 *
475 * If you copy a float array to a double array, the values are casted to DCELL
476 * and the null values are converted from FCELL-null to DCELL-null
477 *
478 * \param source N_array_3d *
479 * \param target N_array_3d *
480 * \return void
481 * */
483{
484 int i;
485 int null;
486
487 if (source->cols_intern != target->cols_intern)
488 G_fatal_error("N_copy_array_3d: the arrays are not of equal size");
489
490 if (source->rows_intern != target->rows_intern)
491 G_fatal_error("N_copy_array_3d: the arrays are not of equal size");
492
493 if (source->depths_intern != target->depths_intern)
494 G_fatal_error("N_copy_array_3d: the arrays are not of equal size");
495
496 G_debug(3, "N_copy_array_3d: copy source array to target array size %i",
497 source->cols_intern * source->rows_intern * source->depths_intern);
498
499 for (i = 0;
500 i < source->cols_intern * source->rows_intern * source->depths_intern;
501 i++) {
502 null = 0;
503 if (source->type == FCELL_TYPE) {
504 if (Rast3d_is_null_value_num((void *)&(source->fcell_array[i]),
505 FCELL_TYPE))
506 null = 1;
507
508 if (target->type == FCELL_TYPE) {
509 target->fcell_array[i] = source->fcell_array[i];
510 }
511 if (target->type == DCELL_TYPE) {
512 if (null)
513 Rast3d_set_null_value((void *)&(target->dcell_array[i]), 1,
514 DCELL_TYPE);
515 else
516 target->dcell_array[i] = (double)source->fcell_array[i];
517 }
518 }
519 if (source->type == DCELL_TYPE) {
520 if (Rast3d_is_null_value_num((void *)&(source->dcell_array[i]),
521 DCELL_TYPE))
522 null = 1;
523
524 if (target->type == FCELL_TYPE) {
525 if (null)
526 Rast3d_set_null_value((void *)&(target->fcell_array[i]), 1,
527 FCELL_TYPE);
528 else
529 target->fcell_array[i] = (float)source->dcell_array[i];
530 }
531 if (target->type == DCELL_TYPE) {
532 target->dcell_array[i] = source->dcell_array[i];
533 }
534 }
535 }
536
537 return;
538}
539
540/*!
541 * \brief Calculate the norm of the two input arrays
542 *
543 * The norm can be of type N_MAXIMUM_NORM or N_EUKLID_NORM.
544 * All arrays must have equal sizes and offsets.
545 * The complete data array inclusively offsets is used for norm calculation.
546 * Only non-null values are used to calculate the norm.
547 *
548 * \param a N_array_3d *
549 * \param b N_array_3d *
550 * \param type the type of the norm -> N_MAXIMUM_NORM, N_EUKLID_NORM
551 * \return double the calculated norm
552 * */
554{
555 int i = 0;
556 double norm = 0.0, tmp = 0.0;
557 double v1 = 0.0, v2 = 0.0;
558
559 if (a->cols_intern != b->cols_intern)
560 G_fatal_error("N_norm_array_3d: the arrays are not of equal size");
561
562 if (a->rows_intern != b->rows_intern)
563 G_fatal_error("N_norm_array_3d: the arrays are not of equal size");
564
565 if (a->depths_intern != b->depths_intern)
566 G_fatal_error("N_norm_array_3d: the arrays are not of equal size");
567
568 G_debug(3, "N_norm_array_3d: norm of a and b size %i",
570
571 for (i = 0; i < a->cols_intern * a->rows_intern * a->depths_intern; i++) {
572 v1 = 0.0;
573 v2 = 0.0;
574
575 if (a->type == FCELL_TYPE) {
576 if (!Rast3d_is_null_value_num((void *)&(a->fcell_array[i]),
577 FCELL_TYPE))
578 v1 = (double)a->fcell_array[i];
579 }
580 if (a->type == DCELL_TYPE) {
581 if (!Rast3d_is_null_value_num((void *)&(a->dcell_array[i]),
582 DCELL_TYPE))
583 v1 = (double)a->dcell_array[i];
584 }
585 if (b->type == FCELL_TYPE) {
586 if (!Rast3d_is_null_value_num((void *)&(b->fcell_array[i]),
587 FCELL_TYPE))
588 v2 = (double)b->fcell_array[i];
589 }
590 if (b->type == DCELL_TYPE) {
591 if (!Rast3d_is_null_value_num((void *)&(b->dcell_array[i]),
592 DCELL_TYPE))
593 v2 = (double)b->dcell_array[i];
594 }
595
596 if (type == N_MAXIMUM_NORM) {
597 tmp = fabs(v2 - v1);
598 if ((tmp > norm))
599 norm = tmp;
600 }
601 if (type == N_EUKLID_NORM) {
602 norm += fabs(v2 - v1);
603 }
604 }
605
606 return norm;
607}
608
609/*!
610 * \brief Calculate basic statistics of the N_array_3d struct
611 *
612 * Calculates the minimum, maximum, sum and the number of
613 * non null values. The array offset can be included in the statistical
614 * calculation.
615 *
616 * \param a N_array_3d * - input array
617 * \param min double* - variable to store the computed minimum
618 * \param max double* - variable to store the computed maximum
619 * \param sum double* - variable to store the computed sum
620 * \param nonull int* - variable to store the number of non null values
621 * \param withoffset - if 1 include offset values in statistic calculation, 0
622 * otherwise \return void
623 * */
624void N_calc_array_3d_stats(N_array_3d *a, double *min, double *max, double *sum,
625 int *nonull, int withoffset)
626{
627 int i, j, k;
628 double val;
629
630 *sum = 0.0;
631 *nonull = 0;
632
633 if (withoffset == 1) {
634
635 *min = (double)N_get_array_3d_d_value(a, 0 - a->offset, 0 - a->offset,
636 0 - a->offset);
637 *max = (double)N_get_array_3d_d_value(a, 0 - a->offset, 0 - a->offset,
638 0 - a->offset);
639
640 for (k = 0 - a->offset; k < a->depths + a->offset; k++) {
641 for (j = 0 - a->offset; j < a->rows + a->offset; j++) {
642 for (i = 0 - a->offset; i < a->cols + a->offset; i++) {
643 if (!N_is_array_3d_value_null(a, i, j, k)) {
644 val = (double)N_get_array_3d_d_value(a, i, j, k);
645 if (*min > val)
646 *min = val;
647 if (*max < val)
648 *max = val;
649 *sum += val;
650 (*nonull)++;
651 }
652 }
653 }
654 }
655 }
656 else {
657
658 *min = (double)N_get_array_3d_d_value(a, 0, 0, 0);
659 *max = (double)N_get_array_3d_d_value(a, 0, 0, 0);
660
661 for (k = 0; k < a->depths; k++) {
662 for (j = 0; j < a->rows; j++) {
663 for (i = 0; i < a->cols; i++) {
664 if (!N_is_array_3d_value_null(a, i, j, k)) {
665 val = (double)N_get_array_3d_d_value(a, i, j, k);
666 if (*min > val)
667 *min = val;
668 if (*max < val)
669 *max = val;
670 *sum += val;
671 (*nonull)++;
672 }
673 }
674 }
675 }
676 }
677
678 G_debug(3,
679 "N_calc_array_3d_stats: compute array stats, min %g, max %g, sum "
680 "%g, nonull %i",
681 *min, *max, *sum, *nonull);
682
683 return;
684}
685
686/*!
687 * \brief Perform calculations with two input arrays,
688 * the result is written to a third array.
689 *
690 * All arrays must have equal sizes and offsets.
691 * The complete data array inclusively offsets is used for calculations.
692 * Only non-null values are used. If one array value is null,
693 * the result array value will be null too.
694 * <br><br>
695 *
696 * If a division with zero is detected, the resulting arrays
697 * value will set to null and not to NaN.
698 * <br><br>
699 *
700 * The result array is optional, if the result arrays points to NULL,
701 * a new array will be allocated with the largest arrays data type
702 * (FCELL_TYPE or DCELL_TYPE) used by the input arrays.
703 * <br><br>
704 *
705 * the calculations are of the following form:
706 *
707 * <ul>
708 * <li>result = a + b -> N_ARRAY_SUM</li>
709 * <li>result = a - b -> N_ARRAY_DIF</li>
710 * <li>result = a * b -> N_ARRAY_MUL</li>
711 * <li>result = a / b -> N_ARRAY_DIV</li>
712 * </ul>
713 *
714 * \param a N_array_3d * - first input array
715 * \param b N_array_3d * - second input array
716 * \param result N_array_3d * - the optional result array
717 * \param type - the type of calculation
718 * \return N_array_3d * - the pointer to the result array
719 * */
721 int type)
722{
723 N_array_3d *c;
724 int i, j, k, setnull = 0;
725 double va = 0.0, vb = 0.0, vc = 0.0; /*variables used for calculation */
726
727 /*Set the pointer */
728 c = result;
729
730 /*Check the array sizes */
731 if (a->cols_intern != b->cols_intern)
732 G_fatal_error("N_math_array_3d: the arrays are not of equal size");
733 if (a->rows_intern != b->rows_intern)
734 G_fatal_error("N_math_array_3d: the arrays are not of equal size");
735 if (a->depths_intern != b->depths_intern)
736 G_fatal_error("N_math_array_3d: the arrays are not of equal size");
737 if (a->offset != b->offset)
738 G_fatal_error("N_math_array_3d: the arrays have different offsets");
739
740 G_debug(3, "N_math_array_3d: mathematical calculations, size: %i",
742
743 /*if the result array is null, allocate a new one, use the
744 * largest data type of the input arrays*/
745 if (c == NULL) {
746 if (a->type == DCELL_TYPE || b->type == DCELL_TYPE) {
747 c = N_alloc_array_3d(a->cols, a->rows, a->depths, a->offset,
748 DCELL_TYPE);
749 G_debug(3, "N_math_array_3d: array of type DCELL_TYPE created");
750 }
751 else {
752 c = N_alloc_array_3d(a->cols, a->rows, a->depths, a->offset,
753 FCELL_TYPE);
754 G_debug(3, "N_math_array_3d: array of type FCELL_TYPE created");
755 }
756 }
757 else {
758 /*Check the array sizes */
759 if (a->cols_intern != c->cols_intern)
760 G_fatal_error("N_math_array_3d: the arrays are not of equal size");
761 if (a->rows_intern != c->rows_intern)
762 G_fatal_error("N_math_array_3d: the arrays are not of equal size");
763 if (a->depths_intern != c->depths_intern)
764 G_fatal_error("N_math_array_3d: the arrays are not of equal size");
765 if (a->offset != c->offset)
766 G_fatal_error("N_math_array_3d: the arrays have different offsets");
767 }
768
769 for (k = 0 - a->offset; k < a->depths + a->offset; k++) {
770 for (j = 0 - a->offset; j < a->rows + a->offset; j++) {
771 for (i = 0 - a->offset; i < a->cols + a->offset; i++) {
772 if (!N_is_array_3d_value_null(a, i, j, k) &&
773 !N_is_array_3d_value_null(a, i, j, k)) {
774 /*we always calculate internally with double values */
775 va = (double)N_get_array_3d_d_value(a, i, j, k);
777 vc = 0;
778 setnull = 0;
779
780 switch (type) {
781 case N_ARRAY_SUM:
782 vc = va + vb;
783 break;
784 case N_ARRAY_DIF:
785 vc = va - vb;
786 break;
787 case N_ARRAY_MUL:
788 vc = va * vb;
789 break;
790 case N_ARRAY_DIV:
791 if (vb != 0)
792 vc = va / vb;
793 else
794 setnull = 1;
795 break;
796 }
797
798 if (c->type == FCELL_TYPE) {
799 if (setnull)
801 else
802 N_put_array_3d_f_value(c, i, j, k, (float)vc);
803 }
804 if (c->type == DCELL_TYPE) {
805 if (setnull)
807 else
808 N_put_array_3d_d_value(c, i, j, k, vc);
809 }
810 }
811 else {
813 }
814 }
815 }
816 }
817
818 return c;
819}
820
821/*!
822 * \brief Convert all null values to zero values
823 *
824 * The complete data array inclusively offsets is used.
825 *
826 * \param a N_array_3d *
827 * \return int - number of replaced null values
828 * */
830{
831 int i = 0, count = 0;
832
833 G_debug(3, "N_convert_array_3d_null_to_zero: convert array of size %i",
835
836 if (a->type == FCELL_TYPE)
837 for (i = 0; i < a->cols_intern * a->rows_intern * a->depths_intern;
838 i++) {
839 if (Rast3d_is_null_value_num((void *)&(a->fcell_array[i]),
840 FCELL_TYPE)) {
841 a->fcell_array[i] = 0.0;
842 count++;
843 }
844 }
845
846 if (a->type == DCELL_TYPE)
847 for (i = 0; i < a->cols_intern * a->rows_intern * a->depths_intern;
848 i++) {
849 if (Rast3d_is_null_value_num((void *)&(a->dcell_array[i]),
850 DCELL_TYPE)) {
851 a->dcell_array[i] = 0.0;
852 count++;
853 }
854 }
855
856 if (a->type == FCELL_TYPE)
857 G_debug(3,
858 "N_convert_array_3d_null_to_zero: %i values of type FCELL_TYPE "
859 "are converted",
860 count);
861
862 if (a->type == DCELL_TYPE)
863 G_debug(3,
864 "N_convert_array_3d_null_to_zero: %i values of type DCELL_TYPE "
865 "are converted",
866 count);
867
868 return count;
869}
#define N_EUKLID_NORM
Definition N_pde.h:43
#define N_ARRAY_MUL
Definition N_pde.h:47
#define N_MAXIMUM_NORM
Definition N_pde.h:42
#define N_ARRAY_DIF
Definition N_pde.h:46
#define N_ARRAY_SUM
Definition N_pde.h:45
#define N_ARRAY_DIV
Definition N_pde.h:48
#define NULL
Definition ccmath.h:32
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
void Rast3d_set_null_value(void *, int, int)
Fills the vector pointed to by c with nofElts NULL-values of type.
Definition null.c:33
int Rast3d_is_null_value_num(const void *, int)
Definition null.c:12
#define Rast_is_f_null_value(fcellVal)
void Rast_set_d_null_value(DCELL *, int)
To set a number of DCELL raster values to NULL.
Definition null_val.c:151
void Rast_set_f_null_value(FCELL *, int)
To set a number of FCELL raster values to NULL.
Definition null_val.c:136
void Rast_set_c_null_value(CELL *, int)
To set a number of CELL raster values to NULL.
Definition null_val.c:122
#define Rast_is_d_null_value(dcellVal)
#define Rast_is_c_null_value(cellVal)
#define min(x, y)
Definition draw2.c:29
#define max(x, y)
Definition draw2.c:30
float FCELL
Definition gis.h:633
double DCELL
Definition gis.h:632
int CELL
Definition gis.h:631
int count
void N_put_array_3d_value_null(N_array_3d *data, int col, int row, int depth)
This function writes a null value to the N_array_3d data at position col, row, depth.
Definition n_arrays.c:1057
N_array_3d * N_alloc_array_3d(int cols, int rows, int depths, int offset, int type)
Allocate memory for a N_array_3d data structure.
Definition n_arrays.c:716
void N_put_array_2d_f_value(N_array_2d *data, int col, int row, FCELL value)
Writes a FCELL value to the N_array_2d struct at position col, row.
Definition n_arrays.c:543
void N_put_array_3d_f_value(N_array_3d *data, int col, int row, int depth, float value)
This function writes a float value to the N_array_3d data at position col, row, depth.
Definition n_arrays.c:1118
DCELL N_get_array_2d_d_value(N_array_2d *data, int col, int row)
Returns the value of type DCELL at position col, row.
Definition n_arrays.c:377
int N_is_array_3d_value_null(N_array_3d *data, int col, int row, int depth)
This function returns 1 if value of N_array_3d data at position col, row, depth is of type null,...
Definition n_arrays.c:870
int N_is_array_2d_value_null(N_array_2d *data, int col, int row)
Returns 1 if the value of N_array_2d struct at position col, row is of type null, otherwise 0.
Definition n_arrays.c:228
void N_put_array_3d_d_value(N_array_3d *data, int col, int row, int depth, double value)
Writes a double value to the N_array_3d struct at position col, row, depth.
Definition n_arrays.c:1145
N_array_2d * N_alloc_array_2d(int cols, int rows, int offset, int type)
Allocate memory for a N_array_2d data structure.
Definition n_arrays.c:72
double N_get_array_3d_d_value(N_array_3d *data, int col, int row, int depth)
This function returns the value of type float at position col, row, depth.
Definition n_arrays.c:976
void N_put_array_2d_value_null(N_array_2d *data, int col, int row)
Writes the null value to the N_array_2d struct at position col, row.
Definition n_arrays.c:456
void N_put_array_2d_c_value(N_array_2d *data, int col, int row, CELL value)
Writes a CELL value to the N_array_2d struct at position col, row.
Definition n_arrays.c:513
void N_put_array_2d_d_value(N_array_2d *data, int col, int row, DCELL value)
Writes a DCELL value to the N_array_2d struct at position col, row.
Definition n_arrays.c:573
int N_convert_array_3d_null_to_zero(N_array_3d *a)
Convert all null values to zero values.
int N_convert_array_2d_null_to_zero(N_array_2d *a)
Convert all null values to zero values.
double N_norm_array_3d(N_array_3d *a, N_array_3d *b, int type)
Calculate the norm of the two input arrays.
void N_calc_array_3d_stats(N_array_3d *a, double *min, double *max, double *sum, int *nonull, int withoffset)
Calculate basic statistics of the N_array_3d struct.
void N_calc_array_2d_stats(N_array_2d *a, double *min, double *max, double *sum, int *nonull, int withoffset)
Calculate basic statistics of the N_array_2d struct.
void N_copy_array_3d(N_array_3d *source, N_array_3d *target)
Copy the source N_array_3d struct to the target N_array_3d struct.
void N_copy_array_2d(N_array_2d *source, N_array_2d *target)
Copy the source N_array_2d struct to the target N_array_2d struct.
double N_norm_array_2d(N_array_2d *a, N_array_2d *b, int type)
Calculate the norm of the two input arrays.
N_array_3d * N_math_array_3d(N_array_3d *a, N_array_3d *b, N_array_3d *result, int type)
Perform calculations with two input arrays, the result is written to a third array.
N_array_2d * N_math_array_2d(N_array_2d *a, N_array_2d *b, N_array_2d *result, int type)
Perform calculations with two input arrays, the result is written to a third array.
double b
Definition r_raster.c:37
#define FCELL_TYPE
Definition raster.h:12
#define DCELL_TYPE
Definition raster.h:13
#define CELL_TYPE
Definition raster.h:11
int type
Definition N_pde.h:130
DCELL * dcell_array
Definition N_pde.h:138
FCELL * fcell_array
Definition N_pde.h:136
CELL * cell_array
Definition N_pde.h:134
int cols
Definition N_pde.h:131
int rows_intern
Definition N_pde.h:132
int rows
Definition N_pde.h:131
int offset
Definition N_pde.h:133
int cols_intern
Definition N_pde.h:132
int cols_intern
Definition N_pde.h:175
int type
Definition N_pde.h:173
int offset
Definition N_pde.h:176
int rows
Definition N_pde.h:174
double * dcell_array
Definition N_pde.h:179
float * fcell_array
Definition N_pde.h:177
int depths_intern
Definition N_pde.h:175
int rows_intern
Definition N_pde.h:175
int depths
Definition N_pde.h:174
int cols
Definition N_pde.h:174