Skip to main content
Rollback to Revision 5 - This should be in a seperate question: https://codereview.meta.stackexchange.com/questions/10901/can-another-code-review-question-count-as-review-context?noredirect=1#comment21627_10901
Source Link
CPlus
  • 948
  • 5
  • 26

Update:

It turns out there are are 2 ways to obtain the correct bounds for the second memmove(). One is to find the start of the sets to delete as the destination and add state.level for the source (the start of the sets to delete is the last set to be all the same type, or the one encountered before the first set with not all nodes of the same type).

The other is to find the start of the next sets after the deleted region as the source, and subtract state.level to get the destination. The latter means no previous set needs to be recorded in the first loop in the delete branch, but also means that the 'first index that needs to be updated' needs to be found via the loop that updates the indices.

As such, the duplication can be resolved by creating this function:

static unsigned octree_offset(Octree *const octree, const State *const state, const int delta, const unsigned size) {
    unsigned set = 0, level = state->level;
    do {
        unsigned offset = state->offset[level];
        while (++offset&7) {
            uint16_t *const node_ptr = (uint16_t *)octree->set+offset;
            if (*node_ptr&0x8000) {
                if (!set)
                    set = (offset>>3)+(*node_ptr&0x7FFF);
                *node_ptr += delta;
            }
        }
    } while (++level != 5);
    if (set) {
        Node8 *const set_ptr = octree->set+set;
        memmove(set_ptr+delta, set_ptr, (size-set)*sizeof(Node8));
        return set;
    }
    return size;
}

The function would be used as octree_offset(octree, &state, -state.level, prev_size); in the delete branch and octree_offset(octree, &state, state.level, prev_size); in the insert branch. I have also decided to move prev_size to outside the main if (state.level) block, and the do while() loops in each branch and the memmove() calls can be replaced with the corresponding calls to this function.

Update:

It turns out there are are 2 ways to obtain the correct bounds for the second memmove(). One is to find the start of the sets to delete as the destination and add state.level for the source (the start of the sets to delete is the last set to be all the same type, or the one encountered before the first set with not all nodes of the same type).

The other is to find the start of the next sets after the deleted region as the source, and subtract state.level to get the destination. The latter means no previous set needs to be recorded in the first loop in the delete branch, but also means that the 'first index that needs to be updated' needs to be found via the loop that updates the indices.

As such, the duplication can be resolved by creating this function:

static unsigned octree_offset(Octree *const octree, const State *const state, const int delta, const unsigned size) {
    unsigned set = 0, level = state->level;
    do {
        unsigned offset = state->offset[level];
        while (++offset&7) {
            uint16_t *const node_ptr = (uint16_t *)octree->set+offset;
            if (*node_ptr&0x8000) {
                if (!set)
                    set = (offset>>3)+(*node_ptr&0x7FFF);
                *node_ptr += delta;
            }
        }
    } while (++level != 5);
    if (set) {
        Node8 *const set_ptr = octree->set+set;
        memmove(set_ptr+delta, set_ptr, (size-set)*sizeof(Node8));
        return set;
    }
    return size;
}

The function would be used as octree_offset(octree, &state, -state.level, prev_size); in the delete branch and octree_offset(octree, &state, state.level, prev_size); in the insert branch. I have also decided to move prev_size to outside the main if (state.level) block, and the do while() loops in each branch and the memmove() calls can be replaced with the corresponding calls to this function.

added 1820 characters in body
Source Link
CPlus
  • 948
  • 5
  • 26

Update:

It turns out there are are 2 ways to obtain the correct bounds for the second memmove(). One is to find the start of the sets to delete as the destination and add state.level for the source (the start of the sets to delete is the last set to be all the same type, or the one encountered before the first set with not all nodes of the same type).

The other is to find the start of the next sets after the deleted region as the source, and subtract state.level to get the destination. The latter means no previous set needs to be recorded in the first loop in the delete branch, but also means that the 'first index that needs to be updated' needs to be found via the loop that updates the indices.

As such, the duplication can be resolved by creating this function:

static unsigned octree_offset(Octree *const octree, const State *const state, const int delta, const unsigned size) {
    unsigned set = 0, level = state->level;
    do {
        unsigned offset = state->offset[level];
        while (++offset&7) {
            uint16_t *const node_ptr = (uint16_t *)octree->set+offset;
            if (*node_ptr&0x8000) {
                if (!set)
                    set = (offset>>3)+(*node_ptr&0x7FFF);
                *node_ptr += delta;
            }
        }
    } while (++level != 5);
    if (set) {
        Node8 *const set_ptr = octree->set+set;
        memmove(set_ptr+delta, set_ptr, (size-set)*sizeof(Node8));
        return set;
    }
    return size;
}

The function would be used as octree_offset(octree, &state, -state.level, prev_size); in the delete branch and octree_offset(octree, &state, state.level, prev_size); in the insert branch. I have also decided to move prev_size to outside the main if (state.level) block, and the do while() loops in each branch and the memmove() calls can be replaced with the corresponding calls to this function.

Update:

It turns out there are are 2 ways to obtain the correct bounds for the second memmove(). One is to find the start of the sets to delete as the destination and add state.level for the source (the start of the sets to delete is the last set to be all the same type, or the one encountered before the first set with not all nodes of the same type).

The other is to find the start of the next sets after the deleted region as the source, and subtract state.level to get the destination. The latter means no previous set needs to be recorded in the first loop in the delete branch, but also means that the 'first index that needs to be updated' needs to be found via the loop that updates the indices.

As such, the duplication can be resolved by creating this function:

static unsigned octree_offset(Octree *const octree, const State *const state, const int delta, const unsigned size) {
    unsigned set = 0, level = state->level;
    do {
        unsigned offset = state->offset[level];
        while (++offset&7) {
            uint16_t *const node_ptr = (uint16_t *)octree->set+offset;
            if (*node_ptr&0x8000) {
                if (!set)
                    set = (offset>>3)+(*node_ptr&0x7FFF);
                *node_ptr += delta;
            }
        }
    } while (++level != 5);
    if (set) {
        Node8 *const set_ptr = octree->set+set;
        memmove(set_ptr+delta, set_ptr, (size-set)*sizeof(Node8));
        return set;
    }
    return size;
}

The function would be used as octree_offset(octree, &state, -state.level, prev_size); in the delete branch and octree_offset(octree, &state, state.level, prev_size); in the insert branch. I have also decided to move prev_size to outside the main if (state.level) block, and the do while() loops in each branch and the memmove() calls can be replaced with the corresponding calls to this function.

edited tags
Link
G. Sliepen
  • 61.7k
  • 3
  • 61
  • 152
edited tags
Link
G. Sliepen
  • 61.7k
  • 3
  • 61
  • 152
Loading
Added example output data
Source Link
CPlus
  • 948
  • 5
  • 26
Loading
Added related network question and fixed a subtle bug when inserting nodes with a large value
Source Link
CPlus
  • 948
  • 5
  • 26
Loading
added 4 characters in body
Source Link
CPlus
  • 948
  • 5
  • 26
Loading
added 4 characters in body
Source Link
CPlus
  • 948
  • 5
  • 26
Loading
Source Link
CPlus
  • 948
  • 5
  • 26
Loading