xround.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #include <limits.h>
  2. #include <math.h>
  3. #include <grass/gis.h>
  4. #include <grass/raster.h>
  5. #include <grass/calc.h>
  6. /**********************************************************************
  7. round(x, step, start)
  8. rounds x to nearest value in the sequence
  9. y[i] = i * step + start
  10. **********************************************************************/
  11. /* i_round(x) rounds x to nearest value, handles negative correctly */
  12. static double i_round(double x, double step, double start)
  13. {
  14. x -= start;
  15. x /= step;
  16. x = floor(x + 0.5);
  17. x *= step;
  18. x += start;
  19. return x;
  20. }
  21. /**********************************************************************/
  22. int f_round(int argc, const int *argt, void **args)
  23. {
  24. const DCELL *arg1 = args[1];
  25. int i;
  26. if (argc < 1)
  27. return E_ARG_LO;
  28. if (argc > 3)
  29. return E_ARG_HI;
  30. if (argc == 1 && argt[0] != CELL_TYPE)
  31. return E_RES_TYPE;
  32. if (argt[1] != DCELL_TYPE)
  33. return E_ARG_TYPE;
  34. if (argc > 1 && argt[2] != DCELL_TYPE)
  35. return E_ARG_TYPE;
  36. if (argc > 2 && argt[3] != DCELL_TYPE)
  37. return E_ARG_TYPE;
  38. if (argc == 1) {
  39. CELL *res = args[0];
  40. for (i = 0; i < columns; i++) {
  41. if (IS_NULL_D(&arg1[i]))
  42. SET_NULL_C(&res[i]);
  43. else {
  44. DCELL x = i_round(arg1[i], 1.0, 0.0);
  45. if (x > 2147483647.0 || x < -2147483647.0)
  46. SET_NULL_C(&res[i]);
  47. else
  48. res[i] = (CELL) x;
  49. }
  50. }
  51. return 0;
  52. }
  53. else if (argc == 2) {
  54. const DCELL *arg2 = args[2];
  55. switch (argt[0]) {
  56. case CELL_TYPE:
  57. {
  58. CELL *res = args[0];
  59. for (i = 0; i < columns; i++) {
  60. if (IS_NULL_D(&arg1[i]))
  61. SET_NULL_C(&res[i]);
  62. else if (IS_NULL_D(&arg2[i]))
  63. SET_NULL_C(&res[i]);
  64. else {
  65. DCELL x = i_round(arg1[i], arg2[i], 0.0);
  66. if (x > 2147483647.0 || x < -2147483647.0)
  67. SET_NULL_C(&res[i]);
  68. else
  69. res[i] = (CELL) x;
  70. }
  71. }
  72. return 0;
  73. }
  74. case FCELL_TYPE:
  75. {
  76. FCELL *res = args[0];
  77. for (i = 0; i < columns; i++)
  78. if (IS_NULL_D(&arg1[i]))
  79. SET_NULL_F(&res[i]);
  80. else if (IS_NULL_D(&arg2[i]))
  81. SET_NULL_F(&res[i]);
  82. else
  83. res[i] = (FCELL) i_round(arg1[i], arg2[i], 0.0);
  84. return 0;
  85. }
  86. case DCELL_TYPE:
  87. {
  88. DCELL *res = args[0];
  89. for (i = 0; i < columns; i++)
  90. if (IS_NULL_D(&arg1[i]))
  91. SET_NULL_D(&res[i]);
  92. else if (IS_NULL_D(&arg2[i]))
  93. SET_NULL_D(&res[i]);
  94. else
  95. res[i] = (DCELL) i_round(arg1[i], arg2[i], 0.0);
  96. return 0;
  97. }
  98. default:
  99. return E_INV_TYPE;
  100. }
  101. }
  102. else if (argc == 3) {
  103. const DCELL *arg2 = args[2];
  104. const DCELL *arg3 = args[3];
  105. switch (argt[0]) {
  106. case CELL_TYPE:
  107. {
  108. CELL *res = args[0];
  109. for (i = 0; i < columns; i++) {
  110. if (IS_NULL_D(&arg1[i]))
  111. SET_NULL_C(&res[i]);
  112. else if (IS_NULL_D(&arg2[i]))
  113. SET_NULL_C(&res[i]);
  114. else if (IS_NULL_D(&arg3[i]))
  115. SET_NULL_C(&res[i]);
  116. else {
  117. DCELL x = i_round(arg1[i], arg2[i], arg3[i]);
  118. if (x > 2147483647.0 || x < -2147483647.0)
  119. SET_NULL_C(&res[i]);
  120. else
  121. res[i] = (CELL) x;
  122. }
  123. }
  124. return 0;
  125. }
  126. case FCELL_TYPE:
  127. {
  128. FCELL *res = args[0];
  129. for (i = 0; i < columns; i++)
  130. if (IS_NULL_D(&arg1[i]))
  131. SET_NULL_F(&res[i]);
  132. else if (IS_NULL_D(&arg2[i]))
  133. SET_NULL_F(&res[i]);
  134. else if (IS_NULL_D(&arg3[i]))
  135. SET_NULL_F(&res[i]);
  136. else
  137. res[i] = (FCELL) i_round(arg1[i], arg2[i], arg3[i]);
  138. return 0;
  139. }
  140. case DCELL_TYPE:
  141. {
  142. DCELL *res = args[0];
  143. for (i = 0; i < columns; i++)
  144. if (IS_NULL_D(&arg1[i]))
  145. SET_NULL_D(&res[i]);
  146. else if (IS_NULL_D(&arg2[i]))
  147. SET_NULL_D(&res[i]);
  148. else if (IS_NULL_D(&arg3[i]))
  149. SET_NULL_D(&res[i]);
  150. else
  151. res[i] = (DCELL) i_round(arg1[i], arg2[i], arg3[i]);
  152. return 0;
  153. }
  154. default:
  155. return E_INV_TYPE;
  156. }
  157. }
  158. else
  159. return E_WTF;
  160. }
  161. int c_round(int argc, int *argt)
  162. {
  163. if (argc < 1)
  164. return E_ARG_LO;
  165. if (argc > 3)
  166. return E_ARG_HI;
  167. argt[0] = CELL_TYPE;
  168. if (argc > 1 && argt[0] < argt[2])
  169. argt[0] = argt[2];
  170. if (argc > 2 && argt[0] < argt[3])
  171. argt[0] = argt[3];
  172. argt[1] = DCELL_TYPE;
  173. if (argc > 1)
  174. argt[2] = DCELL_TYPE;
  175. if (argc > 2)
  176. argt[3] = DCELL_TYPE;
  177. return 0;
  178. }