//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RivCrossSectionPartMgr::RivCrossSectionPartMgr(const RimCrossSection* rimCrossSection) : m_rimCrossSection(rimCrossSection), m_defaultColor(cvf::Color3::WHITE) { CVF_ASSERT(m_rimCrossSection); m_crossSectionFacesTextureCoords = new cvf::Vec2fArray; computeData(); }
void MtlSaInverseBWTransform::doTransform(byte* bwt, uint32 bwt_size, const std::vector<uint32> &LFpowers) { PROFILE("MtlSaInverseBWTransform::doTransform"); assert(bwt_size >= 2); assert(LFpowers.size() > 0); uint32 eob_position = LFpowers[0]; // We use 'data' to store: // a) LF^2[i] (4 bytes), // b) a pair (bwt[LF[i]], bwt[i]) (2 bytes) // for each position i = 0, .., bwt_size - 1. In total the array takes roughly // 6 * bwt_size bytes. Having this array enables restoring the original string // two characters at a time. // Information a) and b) for position i is always accessed together. To reduce // the number of cache misses the following layout is used: // // layout | - - - - | - - | - - | - - - - | - - - - | - - | - - | - - - -| // bytes 4 2 2 4 4 2 2 4 // meaning LF^2[0] P[0] P[1] LF^2[1] LF^2[2] P[2] P[3] LF^2[3] // // Where P[i] is a pair (bwt[LF[i]], bwt[i]). uint32 *data = new uint32[3 * ((bwt_size + 1) / 2)]; computeData(bwt, bwt_size, data, eob_position); uint32 *data_ptr = &data[0]; byte *result_ptr = bwt; uint32 starting_positions = LFpowers.size(); uint32 block_size = bwt_size / starting_positions; uint32 to_restore = bwt_size - 1; // Stores the set of current LF powers (one per block). uint32 positions[starting_positions]; std::copy(LFpowers.begin(), LFpowers.end(), positions); // If the block size is small, don't deploy parallel inversion. if (block_size <= 1) { starting_positions = 1; block_size = bwt_size; } // Stores pointers to positions in text that are about to be restored. uint16 *dest_ptr[starting_positions]; for (uint32 i = 0; i < starting_positions; ++i) { dest_ptr[i] = (uint16 *)(result_ptr + i * block_size - 1); } // Restore the first pair from each block. for (uint32 block_id = 0; block_id < starting_positions; ++block_id) { uint32 position = positions[block_id]; uint32 base = 3 * (position / 2); uint32 offset = position & 1; uint32 next_position = data_ptr[base + (offset << 1)]; uint16 char_pair = ((uint16 *)(data_ptr + base + 1))[offset]; positions[block_id] = next_position; if (block_id == 0) { // Skip the EOB symbol. ++dest_ptr[block_id]; result_ptr[0] = ((unsigned char *)&char_pair)[1]; } else { // Not the first pair, decode as normal. *dest_ptr[block_id]++ = char_pair; } } // Restore the main part of each block, two characters at a time, // simultaneously from multiple starting positions. for (uint32 filled = 1; filled < block_size / 2; ++filled) { for (uint32 block_id = 0; block_id < starting_positions; ++block_id) { uint32 position = positions[block_id]; uint32 base = 3 * (position / 2); uint32 offset = position & 1; uint32 next_position = data_ptr[base + (offset << 1)]; uint16 char_pair = ((uint16 *)(data_ptr + base + 1))[offset]; positions[block_id] = next_position; *dest_ptr[block_id]++ = char_pair; } } // If the block size is odd then there is one remaining character in each // block. This loop takes case of that. The last block is handled separately // because it might contain more than one remaining character. if (block_size & 1) { for (uint32 block_id = 0; block_id + 1 < starting_positions; ++block_id) { uint32 position = positions[block_id]; uint32 base = 3 * (position / 2); uint32 offset = position & 1; uint16 char_pair = ((uint16 *)(data_ptr + base + 1))[offset]; result_ptr[(block_id + 1) * block_size - 2] = ((unsigned char *)&char_pair)[0]; } } // Restore the remaining characters from the last (longest) block, // possibly except the last character, if the last block has odd length. uint32 index = (starting_positions - 1) * block_size - 1 + 2 * (block_size / 2); while (index + 1 < to_restore) { uint32 position = positions[starting_positions - 1]; uint32 base = 3 * (position / 2); uint32 offset = position & 1; uint32 next_position = data_ptr[base + (offset << 1)]; uint16 char_pair = ((uint16 *)(data_ptr + base + 1))[offset]; positions[starting_positions - 1] = next_position; *dest_ptr[starting_positions - 1]++ = char_pair; index += 2; } // Single character left in the last block. if (index != to_restore) { uint32 position = positions[starting_positions - 1]; uint32 base = 3 * (position / 2); uint32 offset = position & 1; uint16 char_pair = ((uint16 *)(data_ptr + base + 1))[offset]; result_ptr[to_restore - 1] = ((unsigned char *)&char_pair)[0]; } delete[] data; }