1 //
2 //  Copyright (C) 2002-2017 Greg Landrum and Rational Discovery LLC
3 //
4 //   @@ All Rights Reserved @@
5 //  This file is part of the RDKit.
6 //  The contents are covered by the terms of the BSD license
7 //  which is included in the file license.txt, found at the root
8 //  of the RDKit source tree.
9 //
10 #include "AtomIterators.h"
11 #include "RDKitBase.h"
12 #include "RDKitQueries.h"
13 
14 namespace RDKit {
15 template <class Atom_, class Mol_>
AtomIterator_(Mol_ * mol)16 AtomIterator_<Atom_, Mol_>::AtomIterator_(Mol_ *mol) {
17   _mol = mol;
18   _pos = 0;
19   _max = mol->getNumAtoms();
20 };
21 template <class Atom_, class Mol_>
AtomIterator_(Mol_ * mol,int pos)22 AtomIterator_<Atom_, Mol_>::AtomIterator_(Mol_ *mol, int pos) {
23   _mol = mol;
24   _pos = pos;
25   _max = mol->getNumAtoms();
26 };
27 template <class Atom_, class Mol_>
AtomIterator_(const AtomIterator_<Atom_,Mol_> & other)28 AtomIterator_<Atom_, Mol_>::AtomIterator_(
29     const AtomIterator_<Atom_, Mol_> &other) {
30   _mol = other._mol;
31   _pos = other._pos;
32   _max = other._max;
33 }
34 template <class Atom_, class Mol_>
operator =(const AtomIterator_<Atom_,Mol_> & other)35 AtomIterator_<Atom_, Mol_> &AtomIterator_<Atom_, Mol_>::operator=(
36     const AtomIterator_<Atom_, Mol_> &other) {
37   _mol = other._mol;
38   _pos = other._pos;
39   _max = other._max;
40   return *this;
41 }
42 
43 template <class Atom_, class Mol_>
operator +=(int val)44 AtomIterator_<Atom_, Mol_> &AtomIterator_<Atom_, Mol_>::operator+=(int val) {
45   _pos += val;
46   if (_pos < 0 || _pos > _max) {
47     _pos = _max;
48   }
49   return *this;
50 }
51 template <class Atom_, class Mol_>
operator -=(int val)52 AtomIterator_<Atom_, Mol_> &AtomIterator_<Atom_, Mol_>::operator-=(int val) {
53   _pos -= val;
54   if (_pos < 0 || _pos > _max) {
55     _pos = _max;
56   }
57   return *this;
58 }
59 template <class Atom_, class Mol_>
operator +(int val) const60 AtomIterator_<Atom_, Mol_> AtomIterator_<Atom_, Mol_>::operator+(
61     int val) const {
62   AtomIterator_<Atom_, Mol_> res(*this);
63   res += val;
64   // += takes care of the pre/post conditions for us, so we're safe to return
65   return res;
66 }
67 template <class Atom_, class Mol_>
operator -(int val) const68 AtomIterator_<Atom_, Mol_> AtomIterator_<Atom_, Mol_>::operator-(
69     int val) const {
70   AtomIterator_<Atom_, Mol_> res(*this);
71   // -= takes care of the pre/post conditions for us, so we're safe to return
72   res -= val;
73   return res;
74 }
75 
76 // iterator subtraction
77 template <class Atom_, class Mol_>
operator -(AtomIterator_<Atom_,Mol_> & other) const78 int AtomIterator_<Atom_, Mol_>::operator-(
79     AtomIterator_<Atom_, Mol_> &other) const {
80   PRECONDITION(_mol == other._mol, "bad operator- call");
81   return _pos - other._pos;
82 }
83 
84 // dereference
85 template <class Atom_, class Mol_>
86 Atom_ *AtomIterator_<Atom_, Mol_>::operator*() const {
87   PRECONDITION(_mol != nullptr, "no molecule");
88   RANGE_CHECK(0, _pos, _max - 1);
89   return (*_mol)[_pos];
90 }
91 // random access
92 template <class Atom_, class Mol_>
93 Atom_ *AtomIterator_<Atom_, Mol_>::operator[](const int which) const {
94   PRECONDITION(_mol != nullptr, "no molecule");
95   RANGE_CHECK(0, which, _max - 1);
96   return (*_mol)[which];
97 }
98 
99 template <class Atom_, class Mol_>
operator ==(const AtomIterator_<Atom_,Mol_> & other) const100 bool AtomIterator_<Atom_, Mol_>::operator==(
101     const AtomIterator_<Atom_, Mol_> &other) const {
102   return _mol == other._mol && _pos == other._pos;
103 }
104 template <class Atom_, class Mol_>
operator !=(const AtomIterator_<Atom_,Mol_> & other) const105 bool AtomIterator_<Atom_, Mol_>::operator!=(
106     const AtomIterator_<Atom_, Mol_> &other) const {
107   return _mol != other._mol || _pos != other._pos;
108 }
109 template <class Atom_, class Mol_>
operator <(const AtomIterator_<Atom_,Mol_> & other) const110 bool AtomIterator_<Atom_, Mol_>::operator<(
111     const AtomIterator_<Atom_, Mol_> &other) const {
112   return _mol == other._mol && _pos < other._pos;
113 }
114 template <class Atom_, class Mol_>
operator <=(const AtomIterator_<Atom_,Mol_> & other) const115 bool AtomIterator_<Atom_, Mol_>::operator<=(
116     const AtomIterator_<Atom_, Mol_> &other) const {
117   return _mol == other._mol && _pos <= other._pos;
118 }
119 template <class Atom_, class Mol_>
operator >(const AtomIterator_<Atom_,Mol_> & other) const120 bool AtomIterator_<Atom_, Mol_>::operator>(
121     const AtomIterator_<Atom_, Mol_> &other) const {
122   return _mol == other._mol && _pos > other._pos;
123 }
124 template <class Atom_, class Mol_>
operator >=(const AtomIterator_<Atom_,Mol_> & other) const125 bool AtomIterator_<Atom_, Mol_>::operator>=(
126     const AtomIterator_<Atom_, Mol_> &other) const {
127   return _mol == other._mol && _pos >= other._pos;
128 }
129 
130 // pre-increment
131 template <class Atom_, class Mol_>
operator ++()132 AtomIterator_<Atom_, Mol_> &AtomIterator_<Atom_, Mol_>::operator++() {
133   _pos++;
134   return *this;
135 }
136 template <class Atom_, class Mol_>
operator ++(int)137 AtomIterator_<Atom_, Mol_> AtomIterator_<Atom_, Mol_>::operator++(int) {
138   AtomIterator_<Atom_, Mol_> res(*this);
139   _pos++;
140   return res;
141 }
142 // pre-decrement
143 template <class Atom_, class Mol_>
operator --()144 AtomIterator_<Atom_, Mol_> &AtomIterator_<Atom_, Mol_>::operator--() {
145   _pos--;
146   return *this;
147 }
148 template <class Atom_, class Mol_>
operator --(int)149 AtomIterator_<Atom_, Mol_> AtomIterator_<Atom_, Mol_>::operator--(int) {
150   AtomIterator_<Atom_, Mol_> res(*this);
151   if (_pos - 1 < 0) {
152     _pos = _max;
153   } else {
154     _pos--;
155   }
156   return res;
157 }
158 
159 //-----------------------------------------
160 //
161 //  HeteroatomIterator
162 //
163 //-----------------------------------------
164 template <class Atom_, class Mol_>
HeteroatomIterator_(Mol_ * mol)165 HeteroatomIterator_<Atom_, Mol_>::HeteroatomIterator_(Mol_ *mol) {
166   _mol = mol;
167   _qA = new QueryAtom(6);
168   _qA->getQuery()->setNegation(true);
169   _end = mol->getNumAtoms();
170   _pos = _findNext(0);
171 };
172 template <class Atom_, class Mol_>
HeteroatomIterator_(Mol_ * mol,int pos)173 HeteroatomIterator_<Atom_, Mol_>::HeteroatomIterator_(Mol_ *mol, int pos) {
174   _mol = mol;
175   _qA = new QueryAtom(6);
176   _end = mol->getNumAtoms();
177   _pos = pos;
178 };
179 
180 template <class Atom_, class Mol_>
~HeteroatomIterator_()181 HeteroatomIterator_<Atom_, Mol_>::~HeteroatomIterator_() {
182   delete _qA;
183   _qA = nullptr;
184 }
185 
186 template <class Atom_, class Mol_>
HeteroatomIterator_(const ThisType & other)187 HeteroatomIterator_<Atom_, Mol_>::HeteroatomIterator_(const ThisType &other) {
188   _mol = other._mol;
189   _end = other._end;
190   _pos = other._pos;
191   _qA = static_cast<QueryAtom *>(other._qA->copy());
192 }
193 
194 template <class Atom_, class Mol_>
operator =(const ThisType & other)195 HeteroatomIterator_<Atom_, Mol_> &HeteroatomIterator_<Atom_, Mol_>::operator=(
196     const ThisType &other) {
197   _mol = other._mol;
198   _end = other._end;
199   _pos = other._pos;
200   _qA = static_cast<QueryAtom *>(other._qA->copy());
201   return *this;
202 }
203 
204 template <class Atom_, class Mol_>
operator ==(const ThisType & other) const205 bool HeteroatomIterator_<Atom_, Mol_>::operator==(const ThisType &other) const {
206   return _mol == other._mol && _pos == other._pos;
207 }
208 template <class Atom_, class Mol_>
operator !=(const ThisType & other) const209 bool HeteroatomIterator_<Atom_, Mol_>::operator!=(const ThisType &other) const {
210   return _mol != other._mol || _pos != other._pos;
211 }
212 
213 template <class Atom_, class Mol_>
214 Atom_ *HeteroatomIterator_<Atom_, Mol_>::operator*() const {
215   PRECONDITION(_mol != nullptr, "no molecule");
216   return (*_mol)[_pos];
217 }
218 // pre-increment
219 template <class Atom_, class Mol_>
220 HeteroatomIterator_<Atom_, Mol_>
operator ++()221     &HeteroatomIterator_<Atom_, Mol_>::operator++() {
222   _pos = _findNext(_pos + 1);
223   return *this;
224 }
225 template <class Atom_, class Mol_>
operator ++(int)226 HeteroatomIterator_<Atom_, Mol_> HeteroatomIterator_<Atom_, Mol_>::operator++(
227     int) {
228   HeteroatomIterator_<Atom_, Mol_> res(*this);
229   _pos = _findNext(_pos + 1);
230   return res;
231 }
232 // pre-decrement
233 template <class Atom_, class Mol_>
234 HeteroatomIterator_<Atom_, Mol_>
operator --()235     &HeteroatomIterator_<Atom_, Mol_>::operator--() {
236   _pos = _findPrev(_pos - 1);
237   return *this;
238 }
239 template <class Atom_, class Mol_>
operator --(int)240 HeteroatomIterator_<Atom_, Mol_> HeteroatomIterator_<Atom_, Mol_>::operator--(
241     int) {
242   HeteroatomIterator_<Atom_, Mol_> res(*this);
243   _pos = _findPrev(_pos - 1);
244   return res;
245 }
246 template <class Atom_, class Mol_>
_findNext(int from)247 int HeteroatomIterator_<Atom_, Mol_>::_findNext(int from) {
248   while (from < _end) {
249     if (_qA->Match((*_mol)[from])) {
250       break;
251     } else {
252       from++;
253     }
254   }
255   return from;
256 }
257 
258 template <class Atom_, class Mol_>
_findPrev(int from)259 int HeteroatomIterator_<Atom_, Mol_>::_findPrev(int from) {
260   while (from > 0) {
261     if (_qA->Match((*_mol)[from])) {
262       break;
263     } else {
264       from--;
265     }
266   }
267   if (from < 0) {
268     from = _end;
269   }
270   return from;
271 }
272 
273 //-----------------------------------------
274 //
275 //  AromaticAtomIterator
276 //
277 //-----------------------------------------
278 template <class Atom_, class Mol_>
AromaticAtomIterator_(Mol_ * mol)279 AromaticAtomIterator_<Atom_, Mol_>::AromaticAtomIterator_(Mol_ *mol) {
280   _mol = mol;
281   _end = mol->getNumAtoms();
282   _pos = _findNext(0);
283 };
284 template <class Atom_, class Mol_>
AromaticAtomIterator_(Mol_ * mol,int pos)285 AromaticAtomIterator_<Atom_, Mol_>::AromaticAtomIterator_(Mol_ *mol, int pos) {
286   _mol = mol;
287   _end = mol->getNumAtoms();
288   _pos = pos;
289 };
290 
291 template <class Atom_, class Mol_>
~AromaticAtomIterator_()292 AromaticAtomIterator_<Atom_, Mol_>::~AromaticAtomIterator_() {}
293 
294 template <class Atom_, class Mol_>
AromaticAtomIterator_(const ThisType & other)295 AromaticAtomIterator_<Atom_, Mol_>::AromaticAtomIterator_(
296     const ThisType &other) {
297   _mol = other._mol;
298   _end = other._end;
299   _pos = other._pos;
300 }
301 
302 template <class Atom_, class Mol_>
303 AromaticAtomIterator_<Atom_, Mol_>
operator =(const ThisType & other)304     &AromaticAtomIterator_<Atom_, Mol_>::operator=(const ThisType &other) {
305   _mol = other._mol;
306   _end = other._end;
307   _pos = other._pos;
308   return *this;
309 }
310 
311 template <class Atom_, class Mol_>
operator ==(const ThisType & other) const312 bool AromaticAtomIterator_<Atom_, Mol_>::operator==(
313     const ThisType &other) const {
314   return _mol == other._mol && _pos == other._pos;
315 }
316 template <class Atom_, class Mol_>
operator !=(const ThisType & other) const317 bool AromaticAtomIterator_<Atom_, Mol_>::operator!=(
318     const ThisType &other) const {
319   return _mol != other._mol || _pos != other._pos;
320 }
321 
322 template <class Atom_, class Mol_>
323 Atom_ *AromaticAtomIterator_<Atom_, Mol_>::operator*() const {
324   PRECONDITION(_mol != nullptr, "no molecule");
325   return (*_mol)[_pos];
326 }
327 // pre-increment
328 template <class Atom_, class Mol_>
329 AromaticAtomIterator_<Atom_, Mol_>
operator ++()330     &AromaticAtomIterator_<Atom_, Mol_>::operator++() {
331   _pos = _findNext(_pos + 1);
332   return *this;
333 }
334 template <class Atom_, class Mol_>
335 AromaticAtomIterator_<Atom_, Mol_> AromaticAtomIterator_<Atom_, Mol_>::
operator ++(int)336 operator++(int) {
337   AromaticAtomIterator_<Atom_, Mol_> res(*this);
338   _pos = _findNext(_pos + 1);
339   return res;
340 }
341 // pre-decrement
342 template <class Atom_, class Mol_>
343 AromaticAtomIterator_<Atom_, Mol_>
operator --()344     &AromaticAtomIterator_<Atom_, Mol_>::operator--() {
345   _pos = _findPrev(_pos - 1);
346   return *this;
347 }
348 template <class Atom_, class Mol_>
349 AromaticAtomIterator_<Atom_, Mol_> AromaticAtomIterator_<Atom_, Mol_>::
operator --(int)350 operator--(int) {
351   AromaticAtomIterator_<Atom_, Mol_> res(*this);
352   _pos = _findPrev(_pos - 1);
353   return res;
354 }
355 template <class Atom_, class Mol_>
_findNext(int from)356 int AromaticAtomIterator_<Atom_, Mol_>::_findNext(int from) {
357   while (from < _end) {
358     if ((*_mol)[from]->getIsAromatic()) {
359       break;
360     } else {
361       from++;
362     }
363   }
364   return from;
365 }
366 
367 template <class Atom_, class Mol_>
_findPrev(int from)368 int AromaticAtomIterator_<Atom_, Mol_>::_findPrev(int from) {
369   while (from > 0) {
370     if ((*_mol)[from]->getIsAromatic()) {
371       break;
372     } else {
373       from--;
374     }
375   }
376   if (from < 0) {
377     from = _end;
378   }
379   return from;
380 }
381 
382 //-----------------------------------------
383 //
384 //  QueryAtomIterator
385 //
386 //-----------------------------------------
387 template <class Atom_, class Mol_>
QueryAtomIterator_(Mol_ * mol,QueryAtom const * what)388 QueryAtomIterator_<Atom_, Mol_>::QueryAtomIterator_(Mol_ *mol,
389                                                     QueryAtom const *what) {
390   PRECONDITION(what, "bad query atom");
391   _mol = mol;
392   _qA = static_cast<QueryAtom *>(what->copy());
393   _end = mol->getNumAtoms();
394   _pos = _findNext(0);
395 };
396 template <class Atom_, class Mol_>
QueryAtomIterator_(Mol_ * mol,int pos)397 QueryAtomIterator_<Atom_, Mol_>::QueryAtomIterator_(Mol_ *mol, int pos) {
398   _mol = mol;
399   _qA = nullptr;
400   _end = mol->getNumAtoms();
401   _pos = pos;
402 };
403 template <class Atom_, class Mol_>
~QueryAtomIterator_()404 QueryAtomIterator_<Atom_, Mol_>::~QueryAtomIterator_() {
405   delete _qA;
406   _qA = nullptr;
407 }
408 template <class Atom_, class Mol_>
QueryAtomIterator_(const QueryAtomIterator_<Atom_,Mol_> & other)409 QueryAtomIterator_<Atom_, Mol_>::QueryAtomIterator_(
410     const QueryAtomIterator_<Atom_, Mol_> &other) {
411   _mol = other._mol;
412   _pos = other._pos;
413   _end = other._end;
414   if (other._qA) {
415     _qA = static_cast<QueryAtom *>(other._qA->copy());
416   } else {
417     _qA = nullptr;
418   }
419 }
420 
421 template <class Atom_, class Mol_>
operator =(const QueryAtomIterator_<Atom_,Mol_> & other)422 QueryAtomIterator_<Atom_, Mol_> &QueryAtomIterator_<Atom_, Mol_>::operator=(
423     const QueryAtomIterator_<Atom_, Mol_> &other) {
424   if (this != &other) {
425     _mol = other._mol;
426     _pos = other._pos;
427     _end = other._end;
428     delete _qA;
429     if (other._qA) {
430       _qA = static_cast<QueryAtom *>(other._qA->copy());
431     } else {
432       _qA = nullptr;
433     }
434   }
435   return *this;
436 }
437 template <class Atom_, class Mol_>
operator ==(const QueryAtomIterator_<Atom_,Mol_> & other) const438 bool QueryAtomIterator_<Atom_, Mol_>::operator==(
439     const QueryAtomIterator_<Atom_, Mol_> &other) const {
440   return _mol == other._mol && _pos == other._pos;
441 }
442 template <class Atom_, class Mol_>
operator !=(const QueryAtomIterator_<Atom_,Mol_> & other) const443 bool QueryAtomIterator_<Atom_, Mol_>::operator!=(
444     const QueryAtomIterator_<Atom_, Mol_> &other) const {
445   return _mol != other._mol || _pos != other._pos;
446 }
447 
448 template <class Atom_, class Mol_>
449 Atom_ *QueryAtomIterator_<Atom_, Mol_>::operator*() const {
450   PRECONDITION(_mol != nullptr, "no molecule");
451   return (*_mol)[_pos];
452 }
453 // pre-increment
454 template <class Atom_, class Mol_>
operator ++()455 QueryAtomIterator_<Atom_, Mol_> &QueryAtomIterator_<Atom_, Mol_>::operator++() {
456   _pos = _findNext(_pos + 1);
457   return *this;
458 }
459 template <class Atom_, class Mol_>
operator ++(int)460 QueryAtomIterator_<Atom_, Mol_> QueryAtomIterator_<Atom_, Mol_>::operator++(
461     int) {
462   QueryAtomIterator_ res(*this);
463   _pos = _findNext(_pos + 1);
464   return res;
465 }
466 // pre-decrement
467 template <class Atom_, class Mol_>
operator --()468 QueryAtomIterator_<Atom_, Mol_> &QueryAtomIterator_<Atom_, Mol_>::operator--() {
469   _pos = _findPrev(_pos - 1);
470   return *this;
471 }
472 template <class Atom_, class Mol_>
operator --(int)473 QueryAtomIterator_<Atom_, Mol_> QueryAtomIterator_<Atom_, Mol_>::operator--(
474     int) {
475   QueryAtomIterator_<Atom_, Mol_> res(*this);
476   _pos = _findPrev(_pos - 1);
477   return res;
478 }
479 template <class Atom_, class Mol_>
_findNext(int from)480 int QueryAtomIterator_<Atom_, Mol_>::_findNext(int from) {
481   PRECONDITION(_mol != nullptr, "no molecule");
482   PRECONDITION(_qA != nullptr, "no query set");
483   while (from < _end) {
484     if (_qA->Match((*_mol)[from])) {
485       break;
486     } else {
487       from++;
488     }
489   }
490   return from;
491 }
492 
493 template <class Atom_, class Mol_>
_findPrev(int from)494 int QueryAtomIterator_<Atom_, Mol_>::_findPrev(int from) {
495   PRECONDITION(_mol != nullptr, "no molecule");
496   PRECONDITION(_qA != nullptr, "no query set");
497   while (from > 0) {
498     if (_qA->Match((*_mol)[from])) {
499       break;
500     } else {
501       from--;
502     }
503   }
504   if (from < 0) {
505     from = _end;
506   }
507   return from;
508 }
509 
510 //-----------------------------------------
511 //
512 //  MatchingAtomIterator
513 //
514 //-----------------------------------------
515 template <class Atom_, class Mol_>
MatchingAtomIterator_(Mol_ * mol,bool (* fn)(Atom_ *))516 MatchingAtomIterator_<Atom_, Mol_>::MatchingAtomIterator_(Mol_ *mol,
517                                                           bool (*fn)(Atom_ *)) {
518   PRECONDITION(fn, "bad query function");
519   _mol = mol;
520   _qF = fn;
521   _end = mol->getNumAtoms();
522   _pos = _findNext(0);
523 };
524 template <class Atom_, class Mol_>
MatchingAtomIterator_(Mol_ * mol,int pos)525 MatchingAtomIterator_<Atom_, Mol_>::MatchingAtomIterator_(Mol_ *mol, int pos) {
526   _mol = mol;
527   _qF = nullptr;
528   _end = mol->getNumAtoms();
529   _pos = pos;
530 };
531 
532 template <class Atom_, class Mol_>
~MatchingAtomIterator_()533 MatchingAtomIterator_<Atom_, Mol_>::~MatchingAtomIterator_() {}
534 
535 template <class Atom_, class Mol_>
MatchingAtomIterator_(const MatchingAtomIterator_<Atom_,Mol_> & other)536 MatchingAtomIterator_<Atom_, Mol_>::MatchingAtomIterator_(
537     const MatchingAtomIterator_<Atom_, Mol_> &other) {
538   _mol = other._mol;
539   _pos = other._pos;
540   _end = other._end;
541   _qF = other._qF;
542 }
543 
544 template <class Atom_, class Mol_>
545 MatchingAtomIterator_<Atom_, Mol_> &MatchingAtomIterator_<Atom_, Mol_>::
operator =(const MatchingAtomIterator_<Atom_,Mol_> & other)546 operator=(const MatchingAtomIterator_<Atom_, Mol_> &other) {
547   if (this != &other) {
548     _mol = other._mol;
549     _pos = other._pos;
550     _end = other._end;
551     _qF = other._qF;
552   }
553   return *this;
554 }
555 template <class Atom_, class Mol_>
operator ==(const MatchingAtomIterator_<Atom_,Mol_> & other) const556 bool MatchingAtomIterator_<Atom_, Mol_>::operator==(
557     const MatchingAtomIterator_<Atom_, Mol_> &other) const {
558   return _mol == other._mol && _pos == other._pos;
559 }
560 template <class Atom_, class Mol_>
operator !=(const MatchingAtomIterator_<Atom_,Mol_> & other) const561 bool MatchingAtomIterator_<Atom_, Mol_>::operator!=(
562     const MatchingAtomIterator_<Atom_, Mol_> &other) const {
563   return _mol != other._mol || _pos != other._pos;
564 }
565 
566 template <class Atom_, class Mol_>
567 Atom_ *MatchingAtomIterator_<Atom_, Mol_>::operator*() const {
568   PRECONDITION(_mol != nullptr, "no molecule");
569   return (*_mol)[_pos];
570 }
571 // pre-increment
572 template <class Atom_, class Mol_>
573 MatchingAtomIterator_<Atom_, Mol_>
operator ++()574     &MatchingAtomIterator_<Atom_, Mol_>::operator++() {
575   _pos = _findNext(_pos + 1);
576   return *this;
577 }
578 template <class Atom_, class Mol_>
579 MatchingAtomIterator_<Atom_, Mol_> MatchingAtomIterator_<Atom_, Mol_>::
operator ++(int)580 operator++(int) {
581   MatchingAtomIterator_ res(*this);
582   _pos = _findNext(_pos + 1);
583   return res;
584 }
585 // pre-decrement
586 template <class Atom_, class Mol_>
587 MatchingAtomIterator_<Atom_, Mol_>
operator --()588     &MatchingAtomIterator_<Atom_, Mol_>::operator--() {
589   _pos = _findPrev(_pos - 1);
590   return *this;
591 }
592 template <class Atom_, class Mol_>
593 MatchingAtomIterator_<Atom_, Mol_> MatchingAtomIterator_<Atom_, Mol_>::
operator --(int)594 operator--(int) {
595   MatchingAtomIterator_<Atom_, Mol_> res(*this);
596   _pos = _findPrev(_pos - 1);
597   return res;
598 }
599 template <class Atom_, class Mol_>
_findNext(int from)600 int MatchingAtomIterator_<Atom_, Mol_>::_findNext(int from) {
601   PRECONDITION(_mol != nullptr, "no molecule");
602   PRECONDITION(_qF != nullptr, "no query set");
603   while (from < _end) {
604     if (_qF((*_mol)[from])) {
605       break;
606     } else {
607       ++from;
608     }
609   }
610   return from;
611 }
612 
613 template <class Atom_, class Mol_>
_findPrev(int from)614 int MatchingAtomIterator_<Atom_, Mol_>::_findPrev(int from) {
615   PRECONDITION(_mol != nullptr, "no molecule");
616   PRECONDITION(_qF != nullptr, "no query set");
617   while (from > 0) {
618     if (_qF((*_mol)[from])) {
619       break;
620     } else {
621       --from;
622     }
623   }
624   if (from < 0) {
625     from = _end;
626   }
627   return from;
628 }
629 
630 template class AtomIterator_<Atom, ROMol>;
631 template class AtomIterator_<const Atom, const ROMol>;
632 
633 template class AromaticAtomIterator_<Atom, ROMol>;
634 template class AromaticAtomIterator_<const Atom, const ROMol>;
635 template class HeteroatomIterator_<Atom, ROMol>;
636 template class HeteroatomIterator_<const Atom, const ROMol>;
637 template class QueryAtomIterator_<Atom, ROMol>;
638 template class QueryAtomIterator_<const Atom, const ROMol>;
639 template class MatchingAtomIterator_<Atom, ROMol>;
640 template class MatchingAtomIterator_<const Atom, const ROMol>;
641 
642 };  // end o' namespace
643