n_arrays_calc.c 25 KB

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