| 120 | } // namespace |
| 121 | |
| 122 | ParameterBlock* ProblemImpl::InternalAddParameterBlock(double* values, |
| 123 | int size) { |
| 124 | CHECK(values != nullptr) << "Null pointer passed to AddParameterBlock " |
| 125 | << "for a parameter with size " << size; |
| 126 | |
| 127 | // Ignore the request if there is a block for the given pointer already. |
| 128 | auto it = parameter_block_map_.find(values); |
| 129 | if (it != parameter_block_map_.end()) { |
| 130 | if (!options_.disable_all_safety_checks) { |
| 131 | int existing_size = it->second->Size(); |
| 132 | CHECK(size == existing_size) |
| 133 | << "Tried adding a parameter block with the same double pointer, " |
| 134 | << values << ", twice, but with different block sizes. Original " |
| 135 | << "size was " << existing_size << " but new size is " << size; |
| 136 | } |
| 137 | return it->second; |
| 138 | } |
| 139 | |
| 140 | if (!options_.disable_all_safety_checks) { |
| 141 | // Before adding the parameter block, also check that it doesn't alias any |
| 142 | // other parameter blocks. |
| 143 | if (!parameter_block_map_.empty()) { |
| 144 | auto lb = parameter_block_map_.lower_bound(values); |
| 145 | |
| 146 | // If lb is not the first block, check the previous block for aliasing. |
| 147 | if (lb != parameter_block_map_.begin()) { |
| 148 | auto previous = lb; |
| 149 | --previous; |
| 150 | CheckForNoAliasing( |
| 151 | previous->first, previous->second->Size(), values, size); |
| 152 | } |
| 153 | |
| 154 | // If lb is not off the end, check lb for aliasing. |
| 155 | if (lb != parameter_block_map_.end()) { |
| 156 | CheckForNoAliasing(lb->first, lb->second->Size(), values, size); |
| 157 | } |
| 158 | } |
| 159 | } |
| 160 | |
| 161 | // Pass the index of the new parameter block as well to keep the index in |
| 162 | // sync with the position of the parameter in the program's parameter vector. |
| 163 | auto* new_parameter_block = |
| 164 | new ParameterBlock(values, size, program_->parameter_blocks_.size()); |
| 165 | |
| 166 | // For dynamic problems, add the list of dependent residual blocks, which is |
| 167 | // empty to start. |
| 168 | if (options_.enable_fast_removal) { |
| 169 | new_parameter_block->EnableResidualBlockDependencies(); |
| 170 | } |
| 171 | parameter_block_map_[values] = new_parameter_block; |
| 172 | program_->parameter_blocks_.push_back(new_parameter_block); |
| 173 | return new_parameter_block; |
| 174 | } |
| 175 | |
| 176 | void ProblemImpl::InternalRemoveResidualBlock(ResidualBlock* residual_block) { |
| 177 | CHECK(residual_block != nullptr); |