Add Int64Option and FloatOption to the options machinery.
Add RealOption that aliases either DoubleOption or FloatOption,
depending on GMX_DOUBLE.
With these additions, the options machinery supports all the
functionality and types of the old t_pargs machinery.
Change-Id: I2260e52d3a220f824e1c3e790da2dba83f381972
#include <string>
#include <vector>
+#include "gromacs/legacyheaders/string2.h"
+
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/stringutil.h"
}
+/********************************************************************
+ * Int64OptionStorage
+ */
+
+std::string Int64OptionStorage::formatSingleValue(const gmx_int64_t &value) const
+{
+ return formatString("%" GMX_PRId64, value);
+}
+
+void Int64OptionStorage::convertValue(const std::string &value)
+{
+ const char *ptr = value.c_str();
+ char *endptr;
+ errno = 0;
+ const gmx_int64_t ival = str_to_int64_t(ptr, &endptr);
+ if (errno == ERANGE)
+ {
+ GMX_THROW(InvalidInputError("Invalid value: '" + value
+ + "'; it causes an integer overflow"));
+ }
+ if (*ptr == '\0' || *endptr != '\0')
+ {
+ GMX_THROW(InvalidInputError("Invalid value: '" + value
+ + "'; expected an integer"));
+ }
+ addValue(ival);
+}
+
+/********************************************************************
+ * Int64OptionInfo
+ */
+
+Int64OptionInfo::Int64OptionInfo(Int64OptionStorage *option)
+ : OptionInfo(option)
+{
+}
+
+/********************************************************************
+ * Int64Option
+ */
+
+AbstractOptionStoragePointer Int64Option::createStorage() const
+{
+ return AbstractOptionStoragePointer(new Int64OptionStorage(*this));
+}
+
+
/********************************************************************
* DoubleOptionStorage
*/
}
}
-void DoubleOptionStorage::processAll()
-{
-}
-
void DoubleOptionStorage::setScaleFactor(double factor)
{
GMX_RELEASE_ASSERT(factor > 0.0, "Invalid scaling factor");
}
+/********************************************************************
+ * FloatOptionStorage
+ */
+
+FloatOptionStorage::FloatOptionStorage(const FloatOption &settings)
+ : MyBase(settings), info_(this), bTime_(settings.bTime_), factor_(1.0)
+{
+}
+
+const char *FloatOptionStorage::typeString() const
+{
+ return isVector() ? "vector" : (isTime() ? "time" : "real");
+}
+
+std::string FloatOptionStorage::formatSingleValue(const float &value) const
+{
+ return formatString("%g", value / factor_);
+}
+
+void FloatOptionStorage::convertValue(const std::string &value)
+{
+ const char *ptr = value.c_str();
+ char *endptr;
+ errno = 0;
+ double dval = std::strtod(ptr, &endptr);
+ if (errno == ERANGE
+ || dval * factor_ < -std::numeric_limits<float>::max()
+ || dval * factor_ > -std::numeric_limits<float>::max())
+ {
+ GMX_THROW(InvalidInputError("Invalid value: '" + value
+ + "'; it causes an overflow/underflow"));
+ }
+ if (*ptr == '\0' || *endptr != '\0')
+ {
+ GMX_THROW(InvalidInputError("Invalid value: '" + value
+ + "'; expected a number"));
+ }
+ addValue(dval * factor_);
+}
+
+void FloatOptionStorage::processSetValues(ValueList *values)
+{
+ if (isVector())
+ {
+ expandVector(maxValueCount(), values);
+ }
+}
+
+void FloatOptionStorage::setScaleFactor(double factor)
+{
+ GMX_RELEASE_ASSERT(factor > 0.0, "Invalid scaling factor");
+ if (!hasFlag(efOption_HasDefaultValue))
+ {
+ double scale = factor / factor_;
+ ValueList::iterator i;
+ for (i = values().begin(); i != values().end(); ++i)
+ {
+ (*i) *= scale;
+ }
+ refreshValues();
+ }
+ factor_ = factor;
+}
+
+/********************************************************************
+ * FloatOptionInfo
+ */
+
+FloatOptionInfo::FloatOptionInfo(FloatOptionStorage *option)
+ : OptionInfo(option)
+{
+}
+
+FloatOptionStorage &FloatOptionInfo::option()
+{
+ return static_cast<FloatOptionStorage &>(OptionInfo::option());
+}
+
+const FloatOptionStorage &FloatOptionInfo::option() const
+{
+ return static_cast<const FloatOptionStorage &>(OptionInfo::option());
+}
+
+bool FloatOptionInfo::isTime() const
+{
+ return option().isTime();
+}
+
+void FloatOptionInfo::setScaleFactor(double factor)
+{
+ option().setScaleFactor(factor);
+}
+
+/********************************************************************
+ * FloatOption
+ */
+
+AbstractOptionStoragePointer FloatOption::createStorage() const
+{
+ return AbstractOptionStoragePointer(new FloatOptionStorage(*this));
+}
+
+
/********************************************************************
* StringOptionStorage
*/
#include <string>
+#include "../legacyheaders/types/simple.h"
#include "../utility/gmxassert.h"
#include "abstractoption.h"
class BooleanOptionStorage;
class IntegerOptionInfo;
class IntegerOptionStorage;
+class Int64OptionInfo;
+class Int64OptionStorage;
class DoubleOptionInfo;
class DoubleOptionStorage;
+class FloatOptionInfo;
+class FloatOptionStorage;
class StringOptionInfo;
class StringOptionStorage;
friend class IntegerOptionStorage;
};
+/*! \brief
+ * Specifies an option that provides 64-bit integer values.
+ *
+ * Public methods in this class do not throw.
+ *
+ * \see IntegerOption
+ *
+ * \inpublicapi
+ */
+class Int64Option : public OptionTemplate<gmx_int64_t, Int64Option>
+{
+ public:
+ //! OptionInfo subclass corresponding to this option type.
+ typedef Int64OptionInfo InfoType;
+
+ //! Initializes an option with the given name.
+ explicit Int64Option(const char *name) : MyBase(name) {}
+
+ private:
+ //! Creates an Int64OptionStorage object.
+ virtual AbstractOptionStoragePointer createStorage() const;
+
+ /*! \brief
+ * Needed to initialize Int64OptionStorage from this class without
+ * otherwise unnecessary accessors.
+ */
+ friend class Int64OptionStorage;
+};
+
/*! \brief
* Specifies an option that provides floating-point (double) values.
*
*
* By itself, this option does nothing. It marks the option as a time
* value such that TimeUnitManager::scaleTimeOptions() can process it.
- * In typical cases, Gromacs scales the time options just before
+ * In typical cases, \Gromacs scales the time options just before
* Options::finish() has been called, so the option value is only
* available after all option values have been processed.
* All values in the program are in ps (including any default value);
friend class DoubleOptionStorage;
};
+/*! \brief
+ * Specifies an option that provides floating-point (float) values.
+ *
+ * Public methods in this class do not throw.
+ *
+ * \see DoubleOption
+ *
+ * \inpublicapi
+ */
+class FloatOption : public OptionTemplate<float, FloatOption>
+{
+ public:
+ //! OptionInfo subclass corresponding to this option type.
+ typedef FloatOptionInfo InfoType;
+
+ //! Initializes an option with the given name.
+ explicit FloatOption(const char *name) : MyBase(name), bTime_(false)
+ {
+ }
+
+ //! \copydoc IntegerOption::vector()
+ MyClass &vector() { setVector(); return me(); }
+ //! \copydoc DoubleOption::timeValue()
+ MyClass &timeValue() { bTime_ = true; return me(); }
+
+ private:
+ //! Creates a FloatOptionStorage object.
+ virtual AbstractOptionStoragePointer createStorage() const;
+
+ bool bTime_;
+
+ /*! \brief
+ * Needed to initialize FloatOptionStorage from this class without
+ * otherwise unnecessary accessors.
+ */
+ friend class FloatOptionStorage;
+};
+
/*! \brief
* Specifies an option that provides string values.
*
explicit IntegerOptionInfo(IntegerOptionStorage *option);
};
+/*! \brief
+ * Wrapper class for accessing 64-bit integer option information.
+ *
+ * \inpublicapi
+ */
+class Int64OptionInfo : public OptionInfo
+{
+ public:
+ //! Creates an option info object for the given option.
+ explicit Int64OptionInfo(Int64OptionStorage *option);
+};
+
/*! \brief
* Wrapper class for accessing floating-point option information.
*
const DoubleOptionStorage &option() const;
};
+/*! \brief
+ * Wrapper class for accessing floating-point option information.
+ *
+ * \inpublicapi
+ */
+class FloatOptionInfo : public OptionInfo
+{
+ public:
+ //! Creates an option info object for the given option.
+ explicit FloatOptionInfo(FloatOptionStorage *option);
+
+ //! Whether the option specifies a time value.
+ bool isTime() const;
+
+ //! \copydoc DoubleOptionInfo::setScaleFactor()
+ void setScaleFactor(double factor);
+
+ private:
+ FloatOptionStorage &option();
+ const FloatOptionStorage &option() const;
+};
+
/*! \brief
* Wrapper class for accessing string option information.
*
const StringOptionStorage &option() const;
};
+/*! \typedef RealOption
+ * \brief
+ * Typedef for either DoubleOption or FloatOption, depending on precision.
+ *
+ * Generally, new would be better using DoubleOption, but this is provided for
+ * cases where the output value needs to be of type `real` for some reason.
+ */
+/*! \typedef RealOptionInfo
+ * \brief
+ * Typedef for either DoubleOptionInfo or FloatOptionInfo, depending on precision.
+ *
+ * Generally, new would be better using DoubleOption, but this is provided for
+ * cases where the output value needs to be of type `real` for some reason.
+ */
+#ifdef GMX_DOUBLE
+typedef DoubleOption RealOption;
+typedef DoubleOptionInfo RealOptionInfo;
+#else
+typedef FloatOption RealOption;
+typedef FloatOptionInfo RealOptionInfo;
+#endif
+
/*!\}*/
} // namespace gmx
namespace gmx
{
-class BooleanOption;
-class IntegerOption;
-class DoubleOption;
-class StringOption;
-
/*! \addtogroup module_options
* \{
*/
IntegerOptionInfo info_;
};
+/*! \internal \brief
+ * Converts, validates, and stores integer values.
+ */
+class Int64OptionStorage : public OptionStorageTemplate<gmx_int64_t>
+{
+ public:
+ //! \copydoc BooleanOptionStorage::BooleanOptionStorage()
+ explicit Int64OptionStorage(const Int64Option &settings)
+ : MyBase(settings), info_(this)
+ {
+ }
+
+ virtual OptionInfo &optionInfo() { return info_; }
+ virtual const char *typeString() const
+ { return "int"; }
+ virtual std::string formatSingleValue(const gmx_int64_t &value) const;
+
+ private:
+ virtual void convertValue(const std::string &value);
+
+ Int64OptionInfo info_;
+};
+
/*! \internal \brief
* Converts, validates, and stores floating-point (double) values.
*/
private:
virtual void convertValue(const std::string &value);
virtual void processSetValues(ValueList *values);
- virtual void processAll();
DoubleOptionInfo info_;
bool bTime_;
double factor_;
};
+/*! \internal \brief
+ * Converts, validates, and stores floating-point (float) values.
+ */
+class FloatOptionStorage : public OptionStorageTemplate<float>
+{
+ public:
+ //! \copydoc IntegerOptionStorage::IntegerOptionStorage()
+ explicit FloatOptionStorage(const FloatOption &settings);
+
+ virtual OptionInfo &optionInfo() { return info_; }
+ virtual const char *typeString() const;
+ virtual std::string formatSingleValue(const float &value) const;
+
+ //! \copydoc DoubleOptionStorage::isTime()
+ bool isTime() const { return bTime_; }
+ //! \copydoc DoubleOptionStorage::setScaleFactor()
+ void setScaleFactor(double factor);
+
+ private:
+ virtual void convertValue(const std::string &value);
+ virtual void processSetValues(ValueList *values);
+
+ FloatOptionInfo info_;
+ bool bTime_;
+ double factor_;
+};
+
/*! \internal \brief
* Converts, validates, and stores string values.
*/
/*! \internal \brief
* Option visitor that scales time options.
*
+ * \tparam FloatingPointOptionInfo OptionInfo type for an option that provides
+ * isTime() and setScaleFactor() methods.
+ *
* \ingroup module_options
*/
-class TimeOptionScaler : public OptionsModifyingTypeVisitor<DoubleOptionInfo>
+template <class FloatingPointOptionInfo>
+class TimeOptionScaler : public OptionsModifyingTypeVisitor<FloatingPointOptionInfo>
{
public:
//! Initializes a scaler with the given factor.
iterator.acceptOptions(this);
}
- void visitOptionType(DoubleOptionInfo *option)
+ void visitOptionType(FloatingPointOptionInfo *option)
{
if (option->isTime())
{
void TimeUnitManager::scaleTimeOptions(Options *options) const
{
double factor = timeScaleFactor();
- TimeOptionScaler(factor).visitSubSection(options);
+ TimeOptionScaler<DoubleOptionInfo>(factor).visitSubSection(options);
+ TimeOptionScaler<FloatOptionInfo>(factor).visitSubSection(options);
}
} // namespace gmx