00001 #ifndef CCTBX_CRYSTAL_NEIGHBORS_SIMPLE_H
00002 #define CCTBX_CRYSTAL_NEIGHBORS_SIMPLE_H
00003
00004 #include <cctbx/crystal/direct_space_asu.h>
00005
00006 namespace cctbx { namespace crystal {
00007
00009 namespace neighbors {
00010
00012 template <typename FloatType=double, typename IntShiftType=int>
00013 class simple_pair_generator
00014 {
00015 public:
00017 typedef typename
00018 direct_space_asu::asu_mappings<FloatType, IntShiftType>
00019 asu_mappings_t;
00020
00022 simple_pair_generator() {}
00023
00025
00034 simple_pair_generator(
00035 boost::shared_ptr<
00036 direct_space_asu::asu_mappings<
00037 FloatType, IntShiftType> > const& asu_mappings,
00038 FloatType const& distance_cutoff=0,
00039 bool minimal=false)
00040 :
00041 asu_mappings_owner_(asu_mappings),
00042 asu_mappings_(asu_mappings.get()),
00043 distance_cutoff_sq_(distance_cutoff*distance_cutoff),
00044 minimal_(minimal)
00045 {
00046 CCTBX_ASSERT(distance_cutoff >= 0);
00047 restart();
00048 }
00049
00051 boost::shared_ptr<
00052 direct_space_asu::asu_mappings<
00053 FloatType, IntShiftType> >
00054 asu_mappings() const { return asu_mappings_owner_; }
00055
00057 FloatType
00058 distance_cutoff_sq() const { return distance_cutoff_sq_; }
00059
00061 bool
00062 minimal() const { return minimal_; }
00063
00067 bool
00068 at_end() const { return at_end_; }
00069
00071
00073 direct_space_asu::asu_mapping_index_pair_and_diff<FloatType>
00074 next()
00075 {
00076 CCTBX_ASSERT(!at_end_);
00077 direct_space_asu::asu_mapping_index_pair_and_diff<FloatType>
00078 result = pair_;
00079 incr(false);
00080 while (!at_end_ && pair_.dist_sq > distance_cutoff_sq_) {
00081 incr(false);
00082 }
00083 return result;
00084 }
00085
00087 void
00088 restart()
00089 {
00090 at_end_ = false;
00091 is_swapped_ = false;
00092 incr(true);
00093 while (!at_end_ && pair_.dist_sq > distance_cutoff_sq_) {
00094 incr(false);
00095 }
00096 }
00097
00099 std::size_t
00100 count_pairs()
00101 {
00102 std::size_t result = 0;
00103 while (!at_end_) {
00104 next();
00105 result++;
00106 }
00107 return result;
00108 }
00109
00111 FloatType
00112 max_distance_sq()
00113 {
00114 FloatType result = -1;
00115 while (!this->at_end_) {
00116 result = std::max(result, next().dist_sq);
00117 }
00118 return result;
00119 }
00120
00126 af::shared<bool>
00127 neighbors_of(af::const_ref<bool> const& primary_selection)
00128 {
00129 CCTBX_ASSERT(primary_selection.size()
00130 == asu_mappings_->mappings_const_ref().size());
00131 af::shared<bool> result(
00132 primary_selection.begin(),
00133 primary_selection.end());
00134 af::ref<bool> result_ = result.ref();
00135 while (!at_end_) {
00136 direct_space_asu::asu_mapping_index_pair_and_diff<FloatType>
00137 pair = next();
00138 if (primary_selection[pair.i_seq]) result_[pair.j_seq] = true;
00139 else if (primary_selection[pair.j_seq]) result_[pair.i_seq] = true;
00140 }
00141 return result;
00142 }
00143
00145 bool
00146 is_simple_interaction(
00147 direct_space_asu::asu_mapping_index_pair const& pair) const
00148 {
00149 return asu_mappings_->is_simple_interaction(pair);
00150 }
00151
00152 protected:
00153 boost::shared_ptr<asu_mappings_t> asu_mappings_owner_;
00154 const asu_mappings_t* asu_mappings_;
00155 unsigned mappings_size_;
00156 FloatType distance_cutoff_sq_;
00157 bool minimal_;
00158 bool at_end_;
00159 bool is_swapped_;
00160 direct_space_asu::asu_mapping_index_pair_and_diff<FloatType> pair_;
00161
00162 void
00163 incr(bool start);
00164 };
00165
00166 template <typename FloatType, typename IntShiftType>
00167 void
00168 simple_pair_generator<FloatType, IntShiftType>::
00169 incr(bool start)
00170 {
00171 af::const_ref<typename asu_mappings_t::array_of_mappings_for_one_site>
00172 const& mappings = asu_mappings_->mappings_const_ref();
00173 if (!start) {
00174 if (!is_swapped_) goto continue_after_return;
00175 goto continue_after_return_swapped;
00176 }
00177 mappings_size_ = static_cast<unsigned>(mappings.size());
00178 pair_.dist_sq = -1;
00179 pair_.diff_vec = cartesian<FloatType>(0,0,0);
00180 for(pair_.i_seq=0;
00181 pair_.i_seq<mappings_size_;
00182 pair_.i_seq++) {
00183 for(pair_.j_seq=pair_.i_seq;
00184 pair_.j_seq<mappings_size_;
00185 pair_.j_seq++) {
00186 for(pair_.j_sym=(pair_.i_seq == pair_.j_seq ? 1 : 0);
00187 pair_.j_sym<mappings[pair_.j_seq].size();
00188 pair_.j_sym++) {
00189 if (distance_cutoff_sq_ != 0) {
00190 pair_.diff_vec =
00191 mappings[pair_.j_seq][pair_.j_sym].mapped_site()
00192 - mappings[pair_.i_seq][0].mapped_site();
00193 pair_.dist_sq = pair_.diff_vec.length_sq();
00194 }
00195 return;
00196 continue_after_return:;
00197 }
00198 if (!minimal_ && pair_.j_seq != pair_.i_seq) {
00199 std::swap(pair_.i_seq, pair_.j_seq);
00200 is_swapped_ = true;
00201 for(pair_.j_sym=1;
00202 pair_.j_sym<mappings[pair_.j_seq].size();
00203 pair_.j_sym++) {
00204 if (distance_cutoff_sq_ != 0) {
00205 pair_.diff_vec =
00206 mappings[pair_.j_seq][pair_.j_sym].mapped_site()
00207 - mappings[pair_.i_seq][0].mapped_site();
00208 pair_.dist_sq = pair_.diff_vec.length_sq();
00209 }
00210 return;
00211 continue_after_return_swapped:;
00212 }
00213 std::swap(pair_.i_seq, pair_.j_seq);
00214 is_swapped_ = false;
00215 }
00216 }
00217 }
00218 at_end_ = true;
00219 }
00220
00221 }}}
00222
00223 #endif // CCTBX_CRYSTAL_NEIGHBORS_SIMPLE_H