Index: kernel/include/IMP/utility.h =================================================================== --- kernel/include/IMP/utility.h (revision 354) +++ kernel/include/IMP/utility.h (working copy) @@ -8,303 +8,8 @@ #ifndef __IMP_UTILITY_H #define __IMP_UTILITY_H +#include "macros.h" -//! Implement comparison in a class using field as the variable to compare -/** The macro requires that This be defined as the type of the current class. - */ -#define IMP_COMPARISONS_1(field) \ - /** */ bool operator==(const This &o) const { \ - return (field== o.field); \ - } \ - /** */ bool operator!=(const This &o) const { \ - return (field!= o.field); \ - } \ - /** */ bool operator<(const This &o) const { \ - IMP_assert(!is_default() && !o.is_default(), \ - "Ordering with uninitialized index is undefined"); \ - return (field< o.field); \ - } \ - /** */ bool operator>(const This &o) const { \ - IMP_assert(!is_default() && !o.is_default(), \ - "Ordering with uninitialized index is undefined"); \ - return (field> o.field); \ - } \ - /** */ bool operator>=(const This &o) const { \ - IMP_assert(!is_default() && !o.is_default(), \ - "Ordering with uninitialized index is undefined"); \ - return (field>= o.field); \ - } \ - /** */ bool operator<=(const This &o) const { \ - IMP_assert(!is_default() && !o.is_default(), \ - "Ordering with uninitialized index is undefined"); \ - return (field<= o.field); \ - } - -//! Implement comparison in a class using field as the variable to compare -/** The macro requires that This be defined as the type of the current class. - */ -#define IMP_COMPARISONS_2(f0, f1) \ - /** */ bool operator==(const This &o) const { \ - return (f0== o.f0 && f1==o.f1); \ - } \ - /** */ bool operator!=(const This &o) const { \ - return (f0!= o.f0 || f1 != o.f1); \ - } \ - /** */ bool operator<(const This &o) const { \ - IMP_assert(!is_default() && !o.is_default(), \ - "Ordering with uninitialized index is undefined"); \ - if (f0< o.f0) return true; \ - else if (f0 > o.f0) return false; \ - else return f1 < o.f1; \ - } \ - /** */ bool operator>(const This &o) const { \ - IMP_assert(!is_default() && !o.is_default(), \ - "Ordering with uninitialized index is undefined"); \ - if (f0 > o.f0) return true; \ - else if (f0 < o.f0) return false; \ - else return f1 > o.f1; \ - } \ - /** */ bool operator>=(const This &o) const { \ - IMP_assert(!is_default() && !o.is_default(), \ - "Ordering with uninitialized index is undefined"); \ - return operator>(o) || operator==(o); \ - } \ - /** */ bool operator<=(const This &o) const { \ - IMP_assert(!is_default() && !o.is_default(), \ - "Ordering with uninitialized index is undefined"); \ - return operator<(o) || operator==(o); \ - } - -//! Implement comparison in a class using field as the variable to compare -/** The macro requires that This be defined as the type of the current class. - */ -#define IMP_COMPARISONS_3(f0, f1, f2) \ - /** */ bool operator==(const This &o) const { \ - return (f0== o.f0 && f1==o.f1 && f2 == o.f2); \ - } \ - /** */ bool operator!=(const This &o) const { \ - return (f0!= o.f0 || f1 != o.f1 || f2 != o.f2); \ - } \ - /** */ bool operator<(const This &o) const { \ - IMP_assert(!is_default() && !o.is_default(), \ - "Ordering with uninitialized index is undefined"); \ - if (f0< o.f0) return true; \ - else if (f0 > o.f0) return false; \ - if (f1< o.f1) return true; \ - else if (f1 > o.f1) return false; \ - else return f2 < o.f2; \ - } \ - /** */ bool operator>(const This &o) const { \ - IMP_assert(!is_default() && !o.is_default(), \ - "Ordering with uninitialized index is undefined"); \ - if (f0 > o.f0) return true; \ - else if (f0 < o.f0) return false; \ - if (f1 > o.f1) return true; \ - else if (f1 < o.f1) return false; \ - else return f2 > o.f2; \ - } \ - /** */ bool operator>=(const This &o) const { \ - IMP_assert(!is_default() && !o.is_default(), \ - "Ordering with uninitialized index is undefined"); \ - return operator>(o) || operator==(o); \ - } \ - /** */ bool operator<=(const This &o) const { \ - IMP_assert(!is_default() && !o.is_default(), \ - "Ordering with uninitialized index is undefined"); \ - return operator<(o) || operator==(o); \ - } - -//! Implement operator<< on class name, assuming it has one template argument -/** class name should also define the method std::ostream &show(std::ostream&) - */ -#define IMP_OUTPUT_OPERATOR_1(name) /** write to a stream*/ \ -template \ - inline std::ostream &operator<<(std::ostream &out, const name &i) \ - { \ - return i.show(out); \ - } - -//! Implement operator<< on class name -/** class name should also define the method std::ostream &show(std::ostream&) - */ -#define IMP_OUTPUT_OPERATOR(name) /** write to a stream*/ \ - inline std::ostream &operator<<(std::ostream &out, const name &i) \ - { \ - i.show(out); \ - return out; \ - } - -//! Define the basic things you need for a Restraint. -/** These are: show, evaluate, version, last_modified_by - \param[in] version_string The version string. - \param[in] lmb_string The name of the last modifier. -*/ -#define IMP_RESTRAINT(version_string, lmb_string) \ - /** evaluate the restraint*/ \ - virtual Float evaluate(DerivativeAccumulator *accum); \ - /** write information about the restraint to the stream*/ \ - virtual void show(std::ostream &out=std::cout) const; \ - /** \return the current version*/ \ - virtual std::string version() const {return std::string(version_string);}\ - /** \return the last person to modify this restraint */ \ - virtual std::string last_modified_by() const {return std::string(lmb_string);} - -//! Define the basic things you need for an optimizer. -/** These are: optimize, version, last_modified_by - \param[in] version_string The version string. - \param[in] lmb_string The name of the last modifier. -*/ -#define IMP_OPTIMIZER(version_string, lmb_string) \ - /** \short Optimize the model. - \param[in] max_steps The maximum number of steps to take. - \return The final score. - */ \ - virtual Float optimize(unsigned int max_steps); \ - /** \return the current version*/ \ - virtual std::string version() const {return std::string(version_string);}\ - /** \return the last person to modify this restraint */ \ - virtual std::string last_modified_by() const {return std::string(lmb_string);} - - -//! Define the basics needed for an OptimizerState -/** - This macro declares the required functions - - void update() - - void show(std::ostream &out) const - and defines the functions - - version - - last_modified_by - - \param[in] version_string The version. - \param[in] lmb_string The person who last modified it. -*/ -#define IMP_OPTIMIZER_STATE(version_string, lmb_string) \ - /** update the state*/ \ - virtual void update(); \ - /** write information about the state to the stream*/ \ - virtual void show(std::ostream &out=std::cout) const; \ - /** \return the current version*/ \ - virtual std::string version() const {return std::string(version_string);} \ - /** \return the last person to modify this restraint */ \ - virtual std::string last_modified_by() const {return std::string(lmb_string);} - -//! See IMP_OPTIMIZER_STATE -#define IMP_SCORE_STATE(version_string, lmb_string)\ - IMP_OPTIMIZER_STATE(version_string, lmb_string) - -//! Use the swap_with member function to swap two objects -#define IMP_SWAP(name) \ - inline void swap(name &a, name &b) { \ - a.swap_with(b); \ - } - -//! swap two member variables assuming the other object is called o -#define IMP_SWAP_MEMBER(var_name) \ - std::swap(var_name, o.var_name); - - - -//! use a copy_from method to create a copy constructor and operator= -#define IMP_COPY_CONSTRUCTOR(TC) TC(const TC &o){copy_from(o);} \ - TC& operator=(const TC &o) {copy_from(o); return *this;} - - - - -//! Use this to add a container of IMP objects -/** - Such a container adds public methods add_foo, get_foo, number_of_foo - and a private type foo_iterator, with methods foo_begin, foo_end. - \param[in] Ucname The name of the type in uppercase - \param[in] lcname The name of the type in lower case - \param[in] IndexType The type to use for the index. This should be - an instantiation of Index or something similar. - - Eventually we can add removal and correctness checks. - */ -#define IMP_CONTAINER(Ucname, lcname, IndexType) \ - public: \ - /** \short Add an object. - \param[in] obj Pointer to the object - \return index of object within the object - */ \ - IndexType add_##lcname(Ucname *obj); \ - /** \short Get object refered to by the index - \throws IndexException if the index is out of range - */ \ - Ucname *get_##lcname(IndexType i) const ; \ - /** \short return the number of objects*/ \ - unsigned int number_of_##lcname##s() const { \ - return lcname##_vector_.size();} \ -/** \short Get a container of all the objects. - This is for Python as the container can be used like a Python list*/\ -const std::vector &get_##lcname##s() const { \ - return lcname##_vector_;} \ -/** \short An iterator through the objects. - The value type is a pointer.*/ \ - typedef std::vector::iterator Ucname##Iterator; \ -/** \short A const iterator through the objects. - The value type is a pointer.*/ \ - typedef std::vector::const_iterator Ucname##ConstIterator; \ - Ucname##Iterator lcname##s_begin() {return lcname##_vector_.begin();} \ - Ucname##Iterator lcname##s_end() {return lcname##_vector_.end();} \ - Ucname##ConstIterator lcname##s_begin() const { \ - return lcname##_vector_.begin();} \ - Ucname##ConstIterator lcname##s_end() const { \ - return lcname##_vector_.end();} \ -private: \ - std::vector lcname##_vector_; - - - -//! Use this to add a container of IMP objects -/** - This code should go in a .cpp file. One macro for each IMP_CONTAINER. - \param[in] init Code to modify the passed in object. The object is obj - its index index. - */ -#define IMP_CONTAINER_IMPL(Class, Ucname, lcname, IndexType, init) \ - IndexType Class::add_##lcname(Ucname *obj) { \ - IndexType index(lcname##_vector_.size()); \ - for (unsigned int i=0; i< lcname##_vector_.size(); ++i) { \ - IMP_assert(lcname##_vector_[i] != obj, #Ucname \ - " can only be added once to container"); \ - } \ - lcname##_vector_.push_back(obj); \ - init; \ - IMP_CHECK_OBJECT(obj); \ - return index; \ - } \ - Ucname *Class::get_##lcname(IndexType i) const { \ - IMP_check(i.get_index() < lcname##_vector_.size(), \ - "Index " << i << " out of range", \ - IndexException(#Ucname)); \ - Ucname *r= lcname##_vector_[i.get_index()]; \ - IMP_CHECK_OBJECT(r); \ - return r; \ - } \ - - -//! Destroy the things in the container -/** - Put this in the containing object desctructor when you use the - IMP_CONTAINER macro. - \param[in] Ucname the uppercase name - \param[in] lcname the lower case name - */ -#define IMP_CONTAINER_DELETE(Ucname, lcname) \ - for (Ucname##Iterator it= lcname##s_begin(); \ - it != lcname##s_end(); ++it) { \ - delete *it; \ - } \ - lcname##_vector_.clear(); - -//! Call the assert_is_valid method in the object base -#define IMP_CHECK_OBJECT(obj) do { \ - IMP_assert(obj != NULL, "NULL object"); \ - (obj)->assert_is_valid(); \ - } while (false) - namespace IMP { Index: kernel/include/IMP/macros.h =================================================================== --- kernel/include/IMP/macros.h (revision 0) +++ kernel/include/IMP/macros.h (revision 0) @@ -0,0 +1,402 @@ +/** + * \file IMP/macros.h \brief Various general useful macros for IMP. + * + * Copyright 2007-8 Sali Lab. All rights reserved. + * + */ + +#ifndef __IMP_MACROS_H +#define __IMP_MACROS_H + + +//! Implement comparison in a class using field as the variable to compare +/** The macro requires that This be defined as the type of the current class. + */ +#define IMP_COMPARISONS_1(field) \ + /** */ bool operator==(const This &o) const { \ + return (field== o.field); \ + } \ + /** */ bool operator!=(const This &o) const { \ + return (field!= o.field); \ + } \ + /** */ bool operator<(const This &o) const { \ + IMP_assert(!is_default() && !o.is_default(), \ + "Ordering with uninitialized index is undefined"); \ + return (field< o.field); \ + } \ + /** */ bool operator>(const This &o) const { \ + IMP_assert(!is_default() && !o.is_default(), \ + "Ordering with uninitialized index is undefined"); \ + return (field> o.field); \ + } \ + /** */ bool operator>=(const This &o) const { \ + IMP_assert(!is_default() && !o.is_default(), \ + "Ordering with uninitialized index is undefined"); \ + return (field>= o.field); \ + } \ + /** */ bool operator<=(const This &o) const { \ + IMP_assert(!is_default() && !o.is_default(), \ + "Ordering with uninitialized index is undefined"); \ + return (field<= o.field); \ + } + +//! Implement comparison in a class using field as the variable to compare +/** The macro requires that This be defined as the type of the current class. + */ +#define IMP_COMPARISONS_2(f0, f1) \ + /** */ bool operator==(const This &o) const { \ + return (f0== o.f0 && f1==o.f1); \ + } \ + /** */ bool operator!=(const This &o) const { \ + return (f0!= o.f0 || f1 != o.f1); \ + } \ + /** */ bool operator<(const This &o) const { \ + IMP_assert(!is_default() && !o.is_default(), \ + "Ordering with uninitialized index is undefined"); \ + if (f0< o.f0) return true; \ + else if (f0 > o.f0) return false; \ + else return f1 < o.f1; \ + } \ + /** */ bool operator>(const This &o) const { \ + IMP_assert(!is_default() && !o.is_default(), \ + "Ordering with uninitialized index is undefined"); \ + if (f0 > o.f0) return true; \ + else if (f0 < o.f0) return false; \ + else return f1 > o.f1; \ + } \ + /** */ bool operator>=(const This &o) const { \ + IMP_assert(!is_default() && !o.is_default(), \ + "Ordering with uninitialized index is undefined"); \ + return operator>(o) || operator==(o); \ + } \ + /** */ bool operator<=(const This &o) const { \ + IMP_assert(!is_default() && !o.is_default(), \ + "Ordering with uninitialized index is undefined"); \ + return operator<(o) || operator==(o); \ + } + +//! Implement comparison in a class using field as the variable to compare +/** The macro requires that This be defined as the type of the current class. + */ +#define IMP_COMPARISONS_3(f0, f1, f2) \ + /** */ bool operator==(const This &o) const { \ + return (f0== o.f0 && f1==o.f1 && f2 == o.f2); \ + } \ + /** */ bool operator!=(const This &o) const { \ + return (f0!= o.f0 || f1 != o.f1 || f2 != o.f2); \ + } \ + /** */ bool operator<(const This &o) const { \ + IMP_assert(!is_default() && !o.is_default(), \ + "Ordering with uninitialized index is undefined"); \ + if (f0< o.f0) return true; \ + else if (f0 > o.f0) return false; \ + if (f1< o.f1) return true; \ + else if (f1 > o.f1) return false; \ + else return f2 < o.f2; \ + } \ + /** */ bool operator>(const This &o) const { \ + IMP_assert(!is_default() && !o.is_default(), \ + "Ordering with uninitialized index is undefined"); \ + if (f0 > o.f0) return true; \ + else if (f0 < o.f0) return false; \ + if (f1 > o.f1) return true; \ + else if (f1 < o.f1) return false; \ + else return f2 > o.f2; \ + } \ + /** */ bool operator>=(const This &o) const { \ + IMP_assert(!is_default() && !o.is_default(), \ + "Ordering with uninitialized index is undefined"); \ + return operator>(o) || operator==(o); \ + } \ + /** */ bool operator<=(const This &o) const { \ + IMP_assert(!is_default() && !o.is_default(), \ + "Ordering with uninitialized index is undefined"); \ + return operator<(o) || operator==(o); \ + } + +//! Implement operator<< on class name, assuming it has one template argument +/** class name should also define the method std::ostream &show(std::ostream&) + */ +#define IMP_OUTPUT_OPERATOR_1(name) /** write to a stream*/ \ +template \ + inline std::ostream& operator<<(std::ostream &out, const name &i) \ + { \ + i.show(out); \ + return out; \ + } + +//! Implement operator<< on class name +/** class name should also define the method std::ostream &show(std::ostream&) + */ +#define IMP_OUTPUT_OPERATOR(name) /** write to a stream*/ \ + inline std::ostream &operator<<(std::ostream &out, const name &i) \ + { \ + i.show(out); \ + return out; \ + } + +//! Define the basic things you need for a Restraint. +/** These are: show, evaluate, version, last_modified_by + \param[in] version_string The version string. + \param[in] lmb_string The name of the last modifier. +*/ +#define IMP_RESTRAINT(version_string, lmb_string) \ + /** evaluate the restraint*/ \ + virtual Float evaluate(DerivativeAccumulator *accum); \ + /** write information about the restraint to the stream*/ \ + virtual void show(std::ostream &out=std::cout) const; \ + /** \return the current version*/ \ + virtual std::string version() const {return std::string(version_string);}\ + /** \return the last person to modify this restraint */ \ + virtual std::string last_modified_by() const {return std::string(lmb_string);} + +//! Define the basic things you need for an optimizer. +/** These are: optimize, version, last_modified_by + \param[in] version_string The version string. + \param[in] lmb_string The name of the last modifier. +*/ +#define IMP_OPTIMIZER(version_string, lmb_string) \ + /** \short Optimize the model. + \param[in] max_steps The maximum number of steps to take. + \return The final score. + */ \ + virtual Float optimize(unsigned int max_steps); \ + /** \return the current version*/ \ + virtual std::string version() const {return std::string(version_string);}\ + /** \return the last person to modify this restraint */ \ + virtual std::string last_modified_by() const {return std::string(lmb_string);} + + +//! Define the basics needed for an OptimizerState +/** + This macro declares the required functions + - void update() + - void show(std::ostream &out) const + and defines the functions + - version + - last_modified_by + + \param[in] version_string The version. + \param[in] lmb_string The person who last modified it. +*/ +#define IMP_OPTIMIZER_STATE(version_string, lmb_string) \ + /** update the state*/ \ + virtual void update(); \ + /** write information about the state to the stream*/ \ + virtual void show(std::ostream &out=std::cout) const; \ + /** \return the current version*/ \ + virtual std::string version() const {return std::string(version_string);} \ + /** \return the last person to modify this restraint */ \ + virtual std::string last_modified_by() const {return std::string(lmb_string);} + +//! See IMP_OPTIMIZER_STATE +#define IMP_SCORE_STATE(version_string, lmb_string)\ + IMP_OPTIMIZER_STATE(version_string, lmb_string) + +//! Use the swap_with member function to swap two objects +#define IMP_SWAP(name) \ + inline void swap(name &a, name &b) { \ + a.swap_with(b); \ + } + +//! swap two member variables assuming the other object is called o +#define IMP_SWAP_MEMBER(var_name) \ + std::swap(var_name, o.var_name); + + + +//! use a copy_from method to create a copy constructor and operator= +#define IMP_COPY_CONSTRUCTOR(TC) TC(const TC &o){copy_from(o);} \ + TC& operator=(const TC &o) {copy_from(o); return *this;} + + + + +//! Use this to add a container of IMP objects +/** + Such a container adds public methods add_foo, get_foo, number_of_foo + and a private type foo_iterator, with methods foo_begin, foo_end. + \param[in] Ucname The name of the type in uppercase + \param[in] lcname The name of the type in lower case + \param[in] IndexType The type to use for the index. This should be + an instantiation of Index or something similar. + + Eventually we can add removal and correctness checks. + */ +#define IMP_CONTAINER(Ucname, lcname, IndexType) \ + public: \ + /** \short Add an object. + \param[in] obj Pointer to the object + \return index of object within the object + */ \ + IndexType add_##lcname(Ucname *obj); \ + /** \short Add several objects. + \param[in] obj a vector of pointers + */ \ + void add_##lcname##s(const std::vector& obj); \ + /** \short Get object refered to by the index + \throws IndexException if the index is out of range + */ \ + Ucname *get_##lcname(IndexType i) const ; \ + /** \short return the number of objects*/ \ + unsigned int number_of_##lcname##s() const { \ + return lcname##_vector_.size();} \ +/** \short Get a container of all the objects. + This is for Python as the container can be used like a Python list*/\ +const std::vector &get_##lcname##s() const { \ + return lcname##_vector_;} \ +/** \short An iterator through the objects. + The value type is a pointer.*/ \ + typedef std::vector::iterator Ucname##Iterator; \ +/** \short A const iterator through the objects. + The value type is a pointer.*/ \ + typedef std::vector::const_iterator Ucname##ConstIterator; \ + Ucname##Iterator lcname##s_begin() {return lcname##_vector_.begin();} \ + Ucname##Iterator lcname##s_end() {return lcname##_vector_.end();} \ + Ucname##ConstIterator lcname##s_begin() const { \ + return lcname##_vector_.begin();} \ + Ucname##ConstIterator lcname##s_end() const { \ + return lcname##_vector_.end();} \ +private: \ + std::vector lcname##_vector_; + + + +//! Use this to add a container of IMP objects +/** + This code should go in a .cpp file. One macro for each IMP_CONTAINER. + \param[in] init Code to modify the passed in object. The object is obj + its index index. + */ +#define IMP_CONTAINER_IMPL(Class, Ucname, lcname, IndexType, init) \ + IndexType Class::add_##lcname(Ucname *obj) { \ + IndexType index(lcname##_vector_.size()); \ + for (unsigned int i=0; i< lcname##_vector_.size(); ++i) { \ + IMP_assert(lcname##_vector_[i] != obj, #Ucname \ + " can only be added once to container"); \ + } \ + lcname##_vector_.push_back(obj); \ + init; \ + IMP_CHECK_OBJECT(obj); \ + return index; \ + } \ + void Class::add_##lcname##s(const std::vector &objs) { \ + for (unsigned int i=0; i< objs.size(); ++i) { \ + add_##lcname(objs[i]); \ + } \ + } \ + Ucname *Class::get_##lcname(IndexType i) const { \ + IMP_check(i.get_index() < lcname##_vector_.size(), \ + "Index " << i << " out of range", \ + IndexException(#Ucname)); \ + Ucname *r= lcname##_vector_[i.get_index()]; \ + IMP_CHECK_OBJECT(r); \ + return r; \ + } \ + + +//! Destroy the things in the container +/** + Put this in the containing object desctructor when you use the + IMP_CONTAINER macro. + \param[in] Ucname the uppercase name + \param[in] lcname the lower case name + */ +#define IMP_CONTAINER_DELETE(Ucname, lcname) \ + for (Ucname##Iterator it= lcname##s_begin(); \ + it != lcname##s_end(); ++it) { \ + delete *it; \ + } \ + lcname##_vector_.clear(); + + +//! Use this to add a set of IMP objects owned by the containing one +/** + Such a container adds public methods add_foo, get_foo, number_of_foo + and a private type foo_iterator, with methods foo_begin, foo_end. + \param[in] Ucname The name of the type in uppercase + \param[in] lcname The name of the type in lower case + \param[in] IndexType The type to use for the index. This should be + an instantiation of Index or something similar. + + Eventually we can add removal and correctness checks. + */ +#define IMP_CHILDREN(Ucname, lcname, IndexType) \ + public: \ + /** \short Add an object. + \param[in] obj Pointer to the object + \return index of object within the object + */ \ + IndexType add_##lcname(Ucname *obj); \ + /** \short Add several objects. + \param[in] obj a vector of pointers + */ \ + void add_##lcname##s(const std::vector& obj); \ + /** \short Get object refered to by the index + \throws IndexException if the index is out of range + */ \ + Ucname *get_##lcname(IndexType i) const ; \ + /** \short return the number of objects*/ \ + unsigned int number_of_##lcname##s() const { \ + return lcname##_vector_.size();} \ +/** \short Get a container of all the objects. + This is for Python as the container can be used like a Python list*/\ +const std::vector &get_##lcname##s() const { \ + return lcname##_vector_;} \ +/** \short An iterator through the objects. + The value type is a pointer.*/ \ +typedef std::vector::iterator Ucname##Iterator; \ +/** \short A const iterator through the objects. + The value type is a pointer.*/ \ +typedef std::vector::const_iterator Ucname##ConstIterator; \ +Ucname##Iterator lcname##s_begin() {return lcname##_vector_.begin();} \ +Ucname##Iterator lcname##s_end() {return lcname##_vector_.end();} \ +Ucname##ConstIterator lcname##s_begin() const { \ + return lcname##_vector_.begin();} \ +Ucname##ConstIterator lcname##s_end() const { \ + return lcname##_vector_.end();} \ +private: \ +std::vector > lcname##_vector_; + + + +//! Use this to add a container of IMP objects +/** + This code should go in a .cpp file. One macro for each IMP_CONTAINER. + \param[in] init Code to modify the passed in object. The object is obj + its index index. + */ +#define IMP_CHILDREN_IMPL(Class, Ucname, lcname, IndexType, init) \ + IndexType Class::add_##lcname(Ucname *obj) { \ + IndexType index(lcname##_vector_.size()); \ + for (unsigned int i=0; i< lcname##_vector_.size(); ++i) { \ + IMP_assert(lcname##_vector_[i] != obj, #Ucname \ + " can only be added once to container"); \ + } \ + lcname##_vector_.push_back(obj); \ + init; \ + IMP_CHECK_OBJECT(obj); \ + return index; \ + } \ + void Class::add_##lcname##s(const std::vector &objs) { \ + for (unsigned int i=0; i< objs.size(); ++i) { \ + add_##lcname(objs[i]); \ + } \ + } \ + Ucname *Class::get_##lcname(IndexType i) const { \ + IMP_check(i.get_index() < lcname##_vector_.size(), \ + "Index " << i << " out of range", \ + IndexException(#Ucname)); \ + Ucname *r= lcname##_vector_[i.get_index()]; \ + IMP_CHECK_OBJECT(r); \ + return r; \ + } \ + + +//! Call the assert_is_valid method in the object base +#define IMP_CHECK_OBJECT(obj) do { \ + IMP_assert(obj != NULL, "NULL object"); \ + (obj)->assert_is_valid(); \ + } while (false) + +#endif /* __IMP_MACROS_H */ Index: kernel/include/IMP/decorators/utility.h =================================================================== --- kernel/include/IMP/decorators/utility.h (revision 354) +++ kernel/include/IMP/decorators/utility.h (working copy) @@ -9,220 +9,6 @@ #ifndef __IMP_DECORATOR_UTILITY_H #define __IMP_DECORATOR_UTILITY_H +#include "macros.h" -//! Define the basic things needed by a Decorator. -/** The key things this defines are a default constructor, a static create - function, a static cast function, a method get_particle(), a method - get_model() and comparisons. - - \param[in] Name is the name of the decorator, such as NameDecorator - \param[in] Parent The class name for the parent of this class, - typically DecoratorBase - \param[in] check_required is code which returns a bool which checks - if a Particle *p has the required fields - \param[in] add_required is code which adds the required fields - - It requires that the implementer of the Decorator implement the static - method: - - - void initialize_static_data() which initializes static data such as - AttributeKey instances. Ideally, this should internally make sure it - is only done once. - */ -#define IMP_DECORATOR(Name, Parent, check_required, add_required) \ - protected: \ - static bool decorator_keys_initialized_; \ - static void decorator_initialize_static_data(); \ - static bool has_required_attributes(::IMP::Particle *p) { \ - if (!Parent::has_required_attributes(p)) return false; \ - check_required; \ - } \ - static void add_required_attributes(::IMP::Particle *p) { \ - Parent::add_required_attributes(p); \ - add_required; \ - } \ - friend class DecoratorBase; \ - Name(::IMP::Particle* p): Parent(p) { \ - IMP_assert(has_required_attributes(p), \ - "This is not a particle of type " \ - << #Name << *p); \ - } \ -public: \ - typedef Name This; \ - /** The default constructor. This is used as a null value */ \ - Name(): Parent(){} \ - /** Add the necessary attributes to p and return a decorator. */ \ - static Name create(::IMP::Particle *p) { \ - return IMP::DecoratorBase::create(p); \ - } \ - /** Check that p has the necessary attributes and return a decorator. \ - \throws InvalidStateException if some required attributes are \ - missing \ - */ \ - static Name cast(::IMP::Particle *p) { \ - return IMP::DecoratorBase::cast(p); \ - } \ - /** Write information about this decorator to out. Each line should \ - prefixed by prefix*/ \ - void show(std::ostream &out=std::cout, \ - std::string prefix=std::string()) const; - - -/** - Put this macro in to the .cpp with code to initialize the keys - used by the decorator. This will make sure that the keys are - initialized before use and initialized exactly once. - \param[in] Name the name of the decorate - \param[in] Parent the name of the parent decorator to make sure its keys - are initalized - \param[in] work The list of statements to initialize the keys. - this should probably look something like {a_key_=IntKey("Foo");...} - */ -#define IMP_DECORATOR_INITIALIZE(Name, Parent, work)\ - bool Name::decorator_keys_initialized_=false; \ - void Name::decorator_initialize_static_data() { \ - if (decorator_keys_initialized_) return; \ - else { \ - Parent::decorator_initialize_static_data(); \ - work; \ - decorator_keys_initialized_=true; \ - } \ - } - -//! Perform actions dependent on whether a particle has an attribute. -/** A common pattern is to check if a particle has a particular attribute, - do one thing if it does and another if it does not. This macro implements - that pattern. It requires that the method get_particle() return the - particle being used. - - \param[in] AttributeKey The key for the attribute - \param[in] Type The type for the attribute ("Int", "Float", "String") - \param[in] has_action The action to take if the Particle has the attribute. - The attribute value is stored in the variable VALUE. - \param[in] not_has_action The action to take if the Particle does not have - the attribute. - */ -#define IMP_DECORATOR_GET(AttributeKey, Type, has_action, not_has_action) \ - if (get_particle()->has_attribute(AttributeKey)) { \ - Type VALUE = get_particle()->get_value(AttributeKey); \ - has_action; \ - } else { \ - not_has_action; \ - } - - -//! Set an attribute, creating it if it does not already exist. -/** Another commont pattern is to have an assumed value if the attribute - is not there. Then, you sometimes need to set the value whether it - is there or not. - */ -#define IMP_DECORATOR_SET(AttributeKey, value) \ - if (get_particle()->has_attribute(AttributeKey)) { \ - get_particle()->set_value(AttributeKey, value) ; \ - } else { \ - get_particle()->add_attribute(AttributeKey, value); \ - } - -//! define methods for getting and setting a particular simple field -/** - This macros defines methods to get an set a particular attribute. - - \param[in] name The lower case name of the attribute - \param[in] AttributeKey The AttributeKey object controlling - the attribute. - \param[in] Type The type of the attribute (upper case). - \param[in] ReturnType The type to return from the get. -*/ -#define IMP_DECORATOR_GET_SET(name, AttributeKey, Type, ReturnType) \ - /** \return the attribute value */ \ - ReturnType get_##name() const { \ - return static_cast(get_particle()->get_value(AttributeKey)); \ - } \ - /** Set the attribute \param[in] t the value */ \ - void set_##name(ReturnType t) { \ - get_particle()->set_value(AttributeKey, t); \ - } - -//! Define methods for getting and setting an optional simple field. -/** - See IMP_DECORATOR_GET_SET. - - \param[in] name The lower case name of the attribute - \param[in] AttributeKey The AttributeKey object controlling - the attribute. - \param[in] Type The type of the attribute (upper case). - \param[in] ReturnType The type to return from the get. - \param[in] default_value The value returned if the attribute is missing. - */ -#define IMP_DECORATOR_GET_SET_OPT(name, AttributeKey, Type, \ - ReturnType, default_value) \ - /** \return the attribute value*/ \ - ReturnType get_##name() const { \ - IMP_DECORATOR_GET(AttributeKey, Type, \ - return static_cast(VALUE), \ - return default_value); \ - } \ - /** \param[in] t the value to set the attribute to*/ \ - void set_##name(ReturnType t) { \ - IMP_DECORATOR_SET(AttributeKey, t); \ - } - - -//! Define a set of attributes which form an array -/** - This macro should go in the header and IMP_DECORATOR_ARRAY_CPP into the .cpp - and IMP_DECORATOR_ARRAY_INIT in the initialize_static_data function - - To use the array, use functions - - - Type internal_get_name(unsigned int i) - - - void internal_add_name(Type) - - - unsigned int internal_get_number_of_name() const - */ -#define IMP_DECORATOR_ARRAY_DECL(name, Type) \ - protected: \ - static IntKey number_of_##name##_key_; \ - static std::vector name##_keys_; \ - static void generate_##name##_keys(unsigned int i); \ - static const Type##Key get_##name##_key(unsigned int i) { \ - if (i >= name##_keys_.size()) generate_##name##_keys(i); \ - return name##_keys_[i]; \ - } \ - Type internal_get_##name(unsigned int i) const{ \ - IMP_DECORATOR_GET(get_##name##_key(i), Type, \ - return VALUE, \ - throw IndexException(); return Type()); \ - } \ - int internal_add_##name(Type t); \ - unsigned int internal_get_number_of_##name() const { \ - IMP_DECORATOR_GET(number_of_##name##_key_, \ - Int, return VALUE, return 0); \ - } \ - -//! See IMP_DECORATOR_ARRAY_DECL -#define IMP_DECORATOR_ARRAY_DEF(DecoratorType, name, Type) \ - IntKey DecoratorType##Decorator::number_of_##name##_key_; \ - std::vector DecoratorType##Decorator::name##_keys_; \ - void DecoratorType##Decorator::generate_##name##_keys(unsigned int i) \ - { \ - while (!(i < name##_keys_.size())) { \ - std::ostringstream oss; \ - oss << #DecoratorType " " #name " " << name##_keys_.size(); \ - name##_keys_.push_back(Type##Key(oss.str().c_str())); \ - } \ - } \ - int DecoratorType##Decorator::internal_add_##name(Type t) { \ - int nc= internal_get_number_of_##name(); \ - get_particle()->add_attribute(get_##name##_key(nc), t); \ - IMP_DECORATOR_SET(number_of_##name##_key_, nc+1); \ - return nc; \ - } - -//! See IMP_DECORATOR_ARRAY_DECL -#define IMP_DECORATOR_ARRAY_INIT(DecoratorType, name, Type) \ - number_of_##name##_key_= IntKey(#DecoratorType " num " #name); - - #endif /* __IMP_DECORATOR_UTILITY_H */ Index: kernel/include/IMP/decorators/macros.h =================================================================== --- kernel/include/IMP/decorators/macros.h (revision 0) +++ kernel/include/IMP/decorators/macros.h (revision 0) @@ -0,0 +1,230 @@ +/** + * \file decorators/macros.h \brief Various important macros + * for implementing decorators. + * + * Copyright 2007-8 Sali Lab. All rights reserved. + * + */ + +#ifndef __IMP_DECORATOR_MACROS_H +#define __IMP_DECORATOR_MACROS_H + + +//! Define the basic things needed by a Decorator. +/** The key things this defines are a default constructor, a static create + function, a static cast function, a method get_particle(), a method + get_model() and comparisons. + + \param[in] Name is the name of the decorator, such as NameDecorator + \param[in] Parent The class name for the parent of this class, + typically DecoratorBase + \param[in] check_required is code which returns a bool which checks + if a Particle *p has the required fields + \param[in] add_required is code which adds the required fields + + It requires that the implementer of the Decorator implement the static + method: + + - void initialize_static_data() which initializes static data such as + AttributeKey instances. Ideally, this should internally make sure it + is only done once. + */ +#define IMP_DECORATOR(Name, Parent, check_required, add_required) \ + protected: \ + static bool decorator_keys_initialized_; \ + static void decorator_initialize_static_data(); \ + static bool has_required_attributes(::IMP::Particle *p) { \ + if (!Parent::has_required_attributes(p)) return false; \ + check_required; \ + } \ + static void add_required_attributes(::IMP::Particle *p) { \ + if (!Parent::has_required_attributes(p)) { \ + Parent::add_required_attributes(p); \ + } \ + add_required; \ + } \ + friend class DecoratorBase; \ + Name(::IMP::Particle* p): Parent(p) { \ + IMP_assert(has_required_attributes(p), \ + "This is not a particle of type " \ + << #Name << *p); \ + } \ +public: \ + typedef Name This; \ + /** The default constructor. This is used as a null value */ \ + Name(): Parent(){} \ + /** Add the necessary attributes to p and return a decorator. */ \ + static Name create(::IMP::Particle *p) { \ + return IMP::DecoratorBase::create(p); \ + } \ + /** Check that p has the necessary attributes and return a decorator. \ + \throws InvalidStateException if some required attributes are \ + missing \ + */ \ + static Name cast(::IMP::Particle *p) { \ + return IMP::DecoratorBase::cast(p); \ + } \ + /** Write information about this decorator to out. Each line should \ + prefixed by prefix*/ \ + void show(std::ostream &out=std::cout, \ + std::string prefix=std::string()) const; + + +/** + Put this macro in to the .cpp with code to initialize the keys + used by the decorator. This will make sure that the keys are + initialized before use and initialized exactly once. + \param[in] Name the name of the decorate + \param[in] Parent the name of the parent decorator to make sure its keys + are initalized + \param[in] work The list of statements to initialize the keys. + this should probably look something like {a_key_=IntKey("Foo");...} + */ +#define IMP_DECORATOR_INITIALIZE(Name, Parent, work)\ + bool Name::decorator_keys_initialized_=false; \ + void Name::decorator_initialize_static_data() { \ + if (decorator_keys_initialized_) return; \ + else { \ + Parent::decorator_initialize_static_data(); \ + work; \ + decorator_keys_initialized_=true; \ + } \ + } + +//! Perform actions dependent on whether a particle has an attribute. +/** A common pattern is to check if a particle has a particular attribute, + do one thing if it does and another if it does not. This macro implements + that pattern. It requires that the method get_particle() return the + particle being used. + + \param[in] AttributeKey The key for the attribute + \param[in] Type The type for the attribute ("Int", "Float", "String") + \param[in] has_action The action to take if the Particle has the attribute. + The attribute value is stored in the variable VALUE. + \param[in] not_has_action The action to take if the Particle does not have + the attribute. + */ +#define IMP_DECORATOR_GET(AttributeKey, Type, has_action, not_has_action) \ + if (get_particle()->has_attribute(AttributeKey)) { \ + Type VALUE = get_particle()->get_value(AttributeKey); \ + has_action; \ + } else { \ + not_has_action; \ + } + + +//! Set an attribute, creating it if it does not already exist. +/** Another commont pattern is to have an assumed value if the attribute + is not there. Then, you sometimes need to set the value whether it + is there or not. + */ +#define IMP_DECORATOR_SET(AttributeKey, value) \ + if (get_particle()->has_attribute(AttributeKey)) { \ + get_particle()->set_value(AttributeKey, value) ; \ + } else { \ + get_particle()->add_attribute(AttributeKey, value); \ + } + +//! define methods for getting and setting a particular simple field +/** + This macros defines methods to get an set a particular attribute. + + \param[in] name The lower case name of the attribute + \param[in] AttributeKey The AttributeKey object controlling + the attribute. + \param[in] Type The type of the attribute (upper case). + \param[in] ReturnType The type to return from the get. +*/ +#define IMP_DECORATOR_GET_SET(name, AttributeKey, Type, ReturnType) \ + /** \return the attribute value */ \ + ReturnType get_##name() const { \ + return static_cast(get_particle()->get_value(AttributeKey)); \ + } \ + /** Set the attribute \param[in] t the value */ \ + void set_##name(ReturnType t) { \ + get_particle()->set_value(AttributeKey, t); \ + } + +//! Define methods for getting and setting an optional simple field. +/** + See IMP_DECORATOR_GET_SET. + + \param[in] name The lower case name of the attribute + \param[in] AttributeKey The AttributeKey object controlling + the attribute. + \param[in] Type The type of the attribute (upper case). + \param[in] ReturnType The type to return from the get. + \param[in] default_value The value returned if the attribute is missing. + */ +#define IMP_DECORATOR_GET_SET_OPT(name, AttributeKey, Type, \ + ReturnType, default_value) \ + /** \return the attribute value*/ \ + ReturnType get_##name() const { \ + IMP_DECORATOR_GET(AttributeKey, Type, \ + return static_cast(VALUE), \ + return default_value); \ + } \ + /** \param[in] t the value to set the attribute to*/ \ + void set_##name(ReturnType t) { \ + IMP_DECORATOR_SET(AttributeKey, t); \ + } + + +//! Define a set of attributes which form an array +/** + This macro should go in the header and IMP_DECORATOR_ARRAY_CPP into the .cpp + and IMP_DECORATOR_ARRAY_INIT in the initialize_static_data function + + To use the array, use functions + + - Type internal_get_name(unsigned int i) + + - void internal_add_name(Type) + + - unsigned int internal_get_number_of_name() const + */ +#define IMP_DECORATOR_ARRAY_DECL(name, Type) \ + protected: \ + static IntKey number_of_##name##_key_; \ + static std::vector name##_keys_; \ + static void generate_##name##_keys(unsigned int i); \ + static const Type##Key get_##name##_key(unsigned int i) { \ + if (i >= name##_keys_.size()) generate_##name##_keys(i); \ + return name##_keys_[i]; \ + } \ + Type internal_get_##name(unsigned int i) const{ \ + IMP_DECORATOR_GET(get_##name##_key(i), Type, \ + return VALUE, \ + throw IndexException(); return Type()); \ + } \ + int internal_add_##name(Type t); \ + unsigned int internal_get_number_of_##name() const { \ + IMP_DECORATOR_GET(number_of_##name##_key_, \ + Int, return VALUE, return 0); \ + } \ + +//! See IMP_DECORATOR_ARRAY_DECL +#define IMP_DECORATOR_ARRAY_DEF(DecoratorType, name, Type) \ + IntKey DecoratorType##Decorator::number_of_##name##_key_; \ + std::vector DecoratorType##Decorator::name##_keys_; \ + void DecoratorType##Decorator::generate_##name##_keys(unsigned int i) \ + { \ + while (!(i < name##_keys_.size())) { \ + std::ostringstream oss; \ + oss << #DecoratorType " " #name " " << name##_keys_.size(); \ + name##_keys_.push_back(Type##Key(oss.str().c_str())); \ + } \ + } \ + int DecoratorType##Decorator::internal_add_##name(Type t) { \ + int nc= internal_get_number_of_##name(); \ + get_particle()->add_attribute(get_##name##_key(nc), t); \ + IMP_DECORATOR_SET(number_of_##name##_key_, nc+1); \ + return nc; \ + } + +//! See IMP_DECORATOR_ARRAY_DECL +#define IMP_DECORATOR_ARRAY_INIT(DecoratorType, name, Type) \ + number_of_##name##_key_= IntKey(#DecoratorType " num " #name); + + +#endif /* __IMP_DECORATOR_UTILITY_H */ Index: kernel/pyext/IMP_macros.i =================================================================== --- kernel/pyext/IMP_macros.i (revision 354) +++ kernel/pyext/IMP_macros.i (working copy) @@ -1,46 +1,5 @@ -/* Ignore shared object import/export stuff */ #define IMPDLLEXPORT #define IMPDLLLOCAL -#define IMP_COMPARISONS_1(f) bool operator==(const This &o) const ; bool operator<(const This &o) const; bool operator>(const This &o) const; bool operator!=(const This &o) const; bool operator<=(const This &o) const; bool operator>=(const This &o) const; -#define IMP_OUTPUT_OPERATOR_1(f) -#define IMP_OUTPUT_OPERATOR(f) -#define IMP_RESTRAINT(a,b) \ - virtual Float evaluate(DerivativeAccumulator *accum);\ - virtual void show(std::ostream &out=std::cout) const;\ - virtual std::string version() const {return std::string(a);}\ - virtual std::string last_modified_by() const {return std::string(b);} -#define IMP_OPTIMIZER(a, b) \ - virtual Float optimize(unsigned int max_steps);\ - virtual std::string version() const {return std::string(a);};\ - virtual std::string last_modified_by() const {return std::string(b);}; -#define IMP_DECORATOR_GET(a,b,c,d) -#define IMP_DECORATOR_GET_SET(n,a,t,r) r get_##n() const;\ - void set_##n(t); -#define IMP_DECORATOR_GET_SET_OPT(n,a,t,r,d) r get_##n() const;\ - void set_##n(t); -#define IMP_DECORATOR(Name, Parent, a,b) \ - public:\ - typedef Name This;\ - public: Name(); \ - static Name create(::IMP::Particle *p);\ - static Name cast(::IMP::Particle *p);\ - void show(std::ostream &out=std::cout, std::string pre="") -#define IMP_DECORATOR_ARRAY_DECL(a, b) -#define IMP_CONTAINER(Ucname, lcname, IndexType) \ - public: \ - IndexType add_##lcname(Ucname *obj); \ - Ucname *get_##lcname(IndexType i) const ; \ - unsigned int number_of_##lcname##s() const {return lcname##_vector_.size();} \ -const std::vector &get_##lcname##s() const {\ - return lcname##_vector_;}\ - - #define IMP_OPTIMIZER_STATE(version_string, lmb_string) \ - virtual void update(); \ - virtual void show(std::ostream &out=std::cout) const; \ - virtual std::string version() const {return std::string(version_string);} \ - virtual std::string last_modified_by() const {return std::string(lmb_string);} - - -#define IMP_SCORE_STATE(version_string, lmb_string)\ - IMP_OPTIMIZER_STATE(version_string, lmb_string) +%include "IMP/macros.h" +%include "IMP/decorators/macros.h"