address.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /**
  2. * \file address.c
  3. *
  4. * \brief Address routines.
  5. *
  6. * This program is free software under the GNU General Public License
  7. * (>=v2). Read the file COPYING that comes with GRASS for details.
  8. *
  9. * \author GRASS GIS Development Team
  10. *
  11. * \date 2005-2009
  12. */
  13. #include "local_proto.h"
  14. #define SEG_N_ROW_NONZERO(SEG, row, col) \
  15. (((row) >> (SEG)->srowbits) * (SEG)->spr + ((col) >> (SEG)->scolbits))
  16. #define SEG_INDEX_ROW_NONZERO(SEG, row, col) \
  17. ((((row) & ((SEG)->srows - 1)) << (SEG)->scolbits) + ((col) & ((SEG)->scols - 1)))
  18. #define SEG_N_ROW_ZERO(SEG, col) ((col) >> (SEG)->scolbits)
  19. #define SEG_INDEX_ROW_ZERO(SEG, col) ((col) & ((SEG)->scols - 1))
  20. #define INDEX_ADJ(SEG, i) \
  21. ((SEG)->fast_seek ? ((i) << (SEG)->lenbits) : ((i) * (SEG)->len))
  22. int seg_address_fast(const SEGMENT * SEG, off_t row, off_t col, int *n,
  23. int *index)
  24. {
  25. #if 1
  26. if (row) {
  27. *n = SEG_N_ROW_NONZERO(SEG, row, col);
  28. *index = INDEX_ADJ(SEG, SEG_INDEX_ROW_NONZERO(SEG, row, col));
  29. }
  30. /* for simple arrays */
  31. else {
  32. *n = SEG_N_ROW_ZERO(SEG, col);
  33. *index = INDEX_ADJ(SEG, SEG_INDEX_ROW_ZERO(SEG, col));
  34. }
  35. #else
  36. if (row) {
  37. *n = (row >> SEG->srowbits) * SEG->spr + (col >> SEG->scolbits);
  38. *index = ((row & (SEG->srows - 1)) << SEG->scolbits) + (col & (SEG->scols - 1));
  39. /* slower version for testing */
  40. /*
  41. off_t seg_r = row >> SEG->srowbits;
  42. off_t seg_c = col >> SEG->scolbits;
  43. *n = seg_r * SEG->spr + seg_c;
  44. *index = ((row - (seg_r << SEG->srowbits)) << SEG->scolbits) +
  45. col - (seg_c << SEG->scolbits);
  46. */
  47. }
  48. /* for simple arrays */
  49. else {
  50. *n = col >> SEG->scolbits;
  51. *index = col - ((*n) << SEG->scolbits);
  52. }
  53. *index = SEG->fast_seek ? (*index << SEG->lenbits) : (*index * SEG->len);
  54. #endif
  55. return 0;
  56. }
  57. int seg_address_slow(const SEGMENT * SEG, off_t row, off_t col, int *n,
  58. int *index)
  59. {
  60. if (row) {
  61. off_t seg_r = row / SEG->srows;
  62. off_t seg_c = col / SEG->scols;
  63. *n = seg_r * SEG->spr + seg_c;
  64. *index = (row - seg_r * SEG->srows) * SEG->scols + col -
  65. seg_c * SEG->scols;
  66. }
  67. /* for simple arrays */
  68. else {
  69. *n = col / SEG->scols;
  70. *index = col - *n * SEG->scols;
  71. }
  72. *index *= SEG->len;
  73. return 0;
  74. }
  75. /**
  76. * \brief Internal use only
  77. *
  78. * Gets segment address and sets<b>n</b> and <b>index</b>.
  79. *
  80. * \param[in] SEG segment
  81. * \param[in] row
  82. * \param[in] col
  83. * \param[in,out] n
  84. * \param[in,out] index
  85. * \return always returns 0
  86. */
  87. int seg_address(const SEGMENT * SEG, off_t row, off_t col, int *n, int *index)
  88. {
  89. /* old code
  90. *n = row / SEG->srows * SEG->spr + col / SEG->scols;
  91. *index = (row % SEG->srows * SEG->scols + col % SEG->scols) * SEG->len;
  92. */
  93. /* this function is called at least once every time data are accessed in SEG
  94. * avoid very slow modulus and divisions, modulus was the main time killer */
  95. return SEG->address(SEG, row, col, n, index);
  96. }