Replace compat::make_unique with std::make_unique
[alexxy/gromacs.git] / src / gromacs / options / basicoptions.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*! \file
36  * \brief
37  * Declares option objects for basic option types.
38  *
39  * Together with options.h, this header forms the part of the public API
40  * that most classes will use to provide options.
41  *
42  * \author Teemu Murtola <teemu.murtola@gmail.com>
43  * \inpublicapi
44  * \ingroup module_options
45  */
46 #ifndef GMX_OPTIONS_BASICOPTIONS_H
47 #define GMX_OPTIONS_BASICOPTIONS_H
48
49 #include <memory>
50 #include <string>
51 #include <vector>
52
53 #include "gromacs/options/abstractoption.h"
54 #include "gromacs/options/ivaluestore.h"
55 #include "gromacs/utility/arrayref.h"
56 #include "gromacs/utility/basedefinitions.h"
57 #include "gromacs/utility/gmxassert.h"
58
59 namespace gmx
60 {
61
62 class BooleanOptionInfo;
63 class BooleanOptionStorage;
64 class IntegerOptionInfo;
65 class IntegerOptionStorage;
66 class Int64OptionInfo;
67 class Int64OptionStorage;
68 class DoubleOptionInfo;
69 class DoubleOptionStorage;
70 class FloatOptionInfo;
71 class FloatOptionStorage;
72 class StringOptionInfo;
73 class StringOptionStorage;
74 class EnumOptionInfo;
75 class EnumOptionStorage;
76
77 //! \addtogroup module_options
78 //! \{
79
80 /*! \brief
81  * Specifies an option that provides boolean values.
82  *
83  * Example:
84  * \code
85    bool  bPBC;
86    using gmx::BooleanOption;
87    options.addOption(BooleanOption("pbc").store(&bPBC));
88  * \endcode
89  *
90  * Public methods in this class do not throw.
91  *
92  * \inpublicapi
93  */
94 class BooleanOption : public OptionTemplate<bool, BooleanOption>
95 {
96     public:
97         //! OptionInfo subclass corresponding to this option type.
98         typedef BooleanOptionInfo InfoType;
99
100         //! Initializes an option with the given name.
101         explicit BooleanOption(const char *name) : MyBase(name) {}
102
103     private:
104         //! Creates a BooleanOptionStorage object.
105         AbstractOptionStorage *createStorage(
106             const OptionManagerContainer &managers) const override;
107 };
108
109 /*! \brief
110  * Specifies an option that provides integer values.
111  *
112  * Examples:
113  * \code
114    using gmx::IntegerOption;
115    // Simple option
116    int  rcut = 0;
117    options.addOption(IntegerOption("rcut").store(&rcut));
118    // Vector-valued option
119    int  box[3] = {1, 1, 1};  // Default value
120    options.addOption(IntegerOption("box").store(box).vector());
121  * \endcode
122  *
123  * Public methods in this class do not throw.
124  *
125  * \inpublicapi
126  */
127 class IntegerOption : public OptionTemplate<int, IntegerOption>
128 {
129     public:
130         //! OptionInfo subclass corresponding to this option type.
131         typedef IntegerOptionInfo InfoType;
132
133         //! Initializes an option with the given name.
134         explicit IntegerOption(const char *name) : MyBase(name) {}
135
136         /*! \brief
137          * Sets the option to return a vector value.
138          *
139          * A vector value returns a fixed number of values, the default being
140          * three (can be changed with valueCount()).  However, it also accepts
141          * a single value, in which case the value is used to fill the whole
142          * vector.
143          */
144         MyClass &vector() { setVector(); return me(); }
145
146     private:
147         //! Creates an IntegerOptionStorage object.
148         AbstractOptionStorage *createStorage(
149             const OptionManagerContainer &managers) const override;
150
151         /*! \brief
152          * Needed to initialize IntegerOptionStorage from this class without
153          * otherwise unnecessary accessors.
154          */
155         friend class IntegerOptionStorage;
156 };
157
158 /*! \brief
159  * Specifies an option that provides 64-bit integer values.
160  *
161  * Public methods in this class do not throw.
162  *
163  * \see IntegerOption
164  *
165  * \inpublicapi
166  */
167 class Int64Option : public OptionTemplate<int64_t, Int64Option>
168 {
169     public:
170         //! OptionInfo subclass corresponding to this option type.
171         typedef Int64OptionInfo InfoType;
172
173         //! Initializes an option with the given name.
174         explicit Int64Option(const char *name) : MyBase(name) {}
175
176     private:
177         //! Creates an Int64OptionStorage object.
178         AbstractOptionStorage *createStorage(
179             const OptionManagerContainer &managers) const override;
180
181         /*! \brief
182          * Needed to initialize Int64OptionStorage from this class without
183          * otherwise unnecessary accessors.
184          */
185         friend class Int64OptionStorage;
186 };
187
188 /*! \brief
189  * Specifies an option that provides floating-point (double) values.
190  *
191  * Public methods in this class do not throw.
192  *
193  * \inpublicapi
194  */
195 class DoubleOption : public OptionTemplate<double, DoubleOption>
196 {
197     public:
198         //! OptionInfo subclass corresponding to this option type.
199         typedef DoubleOptionInfo InfoType;
200
201         //! Initializes an option with the given name.
202         explicit DoubleOption(const char *name) : MyBase(name), bTime_(false)
203         {
204         }
205
206         //! \copydoc IntegerOption::vector()
207         MyClass &vector() { setVector(); return me(); }
208         /*! \brief
209          * Marks this option as providing a time value whose unit can be changed.
210          *
211          * By itself, this option does nothing.  It marks the option as a time
212          * value such that TimeUnitManager::scaleTimeOptions() can process it.
213          * In typical cases, \Gromacs scales the time options just before
214          * Options::finish() has been called, so the option value is only
215          * available after all option values have been processed.
216          * All values in the program are in ps (including any default value);
217          * user-provided values are scaled according to the time unit set in
218          * TimeUnitManager.
219          */
220         MyClass &timeValue() { bTime_ = true; return me(); }
221
222     private:
223         //! Creates a DoubleOptionStorage object.
224         AbstractOptionStorage *createStorage(
225             const OptionManagerContainer &managers) const override;
226
227         bool bTime_;
228
229         /*! \brief
230          * Needed to initialize DoubleOptionStorage from this class without
231          * otherwise unnecessary accessors.
232          */
233         friend class DoubleOptionStorage;
234 };
235
236 /*! \brief
237  * Specifies an option that provides floating-point (float) values.
238  *
239  * Public methods in this class do not throw.
240  *
241  * \see DoubleOption
242  *
243  * \inpublicapi
244  */
245 class FloatOption : public OptionTemplate<float, FloatOption>
246 {
247     public:
248         //! OptionInfo subclass corresponding to this option type.
249         typedef FloatOptionInfo InfoType;
250
251         //! Initializes an option with the given name.
252         explicit FloatOption(const char *name) : MyBase(name), bTime_(false)
253         {
254         }
255
256         //! \copydoc IntegerOption::vector()
257         MyClass &vector() { setVector(); return me(); }
258         //! \copydoc DoubleOption::timeValue()
259         MyClass &timeValue() { bTime_ = true; return me(); }
260
261     private:
262         //! Creates a FloatOptionStorage object.
263         AbstractOptionStorage *createStorage(
264             const OptionManagerContainer &managers) const override;
265
266         bool bTime_;
267
268         /*! \brief
269          * Needed to initialize FloatOptionStorage from this class without
270          * otherwise unnecessary accessors.
271          */
272         friend class FloatOptionStorage;
273 };
274
275 /*! \brief
276  * Specifies an option that provides string values.
277  *
278  * Examples:
279  * \code
280    using gmx::StringOption;
281    // Simple option
282    std::string  str;
283    options.addOption(StringOption("str").store(&str));
284    // Option that only accepts predefined values
285    const char * const  allowed[] = { "atom", "residue", "molecule" };
286    std::string  str;
287    options.addOption(StringOption("type").enumValue(allowed).store(&str));
288  * \endcode
289  *
290  * Public methods in this class do not throw.
291  *
292  * \inpublicapi
293  */
294 class StringOption : public OptionTemplate<std::string, StringOption>
295 {
296     public:
297         //! OptionInfo subclass corresponding to this option type.
298         typedef StringOptionInfo InfoType;
299
300         //! Initializes an option with the given name.
301         explicit StringOption(const char *name)
302             : MyBase(name), enumValues_(nullptr), enumValuesCount_(0),
303               defaultEnumIndex_(-1)
304         {
305         }
306
307         /*! \brief
308          * Sets the option to only accept one of a fixed set of strings.
309          *
310          * \param[in] values  Array of strings to accept.
311          *
312          * Also accepts prefixes of the strings; if a prefix matches more than
313          * one of the possible strings, the shortest one is used (in a tie, the
314          * first one is).
315          *
316          * The strings are copied once the option is created.
317          */
318         template <size_t count>
319         MyClass &enumValue(const char *const (&values)[count])
320         {
321             GMX_ASSERT(enumValues_ == nullptr,
322                        "Multiple sets of enumerated values specified");
323             enumValues_      = values;
324             enumValuesCount_ = count;
325             return me();
326         }
327         /*! \brief
328          * Sets the option to only accept one of a fixed set of strings.
329          *
330          * \param[in] values  Array of strings to accept, with a NULL pointer
331          *      following the last string.
332          *
333          * Works otherwise as the array version, but accepts a pointer to
334          * an array of undetermined length.  The end of the array is indicated
335          * by a NULL pointer in the array.
336          *
337          * \see enumValue()
338          */
339         MyClass &enumValueFromNullTerminatedArray(const char *const *values)
340         {
341             GMX_ASSERT(enumValues_ == nullptr,
342                        "Multiple sets of enumerated values specified");
343             enumValues_      = values;
344             enumValuesCount_ = -1;
345             return me();
346         }
347         /*! \brief
348          * Sets the default value using an index into the enumeration table.
349          *
350          * Cannot be specified without enumValue().
351          */
352         MyClass &defaultEnumIndex(int index)
353         {
354             GMX_ASSERT(index >= 0, "Invalid enumeration index");
355             defaultEnumIndex_ = index;
356             return me();
357         }
358
359     private:
360         //! Creates a StringOptionStorage object.
361         AbstractOptionStorage *createStorage(
362             const OptionManagerContainer &managers) const override;
363
364         const char *const      *enumValues_;
365         int                     enumValuesCount_;
366         int                     defaultEnumIndex_;
367
368         /*! \brief
369          * Needed to initialize StringOptionStorage from this class without
370          * otherwise unnecessary accessors.
371          */
372         friend class StringOptionStorage;
373 };
374
375 //! \}
376
377 namespace internal
378 {
379
380 /*! \internal
381  * \brief
382  * Type-specific implementation for IOptionValueStore for an enum option.
383  *
384  * This class is instantiated for each enum type for which EnumOption is used,
385  * and takes care of managing `int`-to-`enum` conversions.  Having this part in
386  * the header allows the actual storage implementation to not be in the header,
387  * which would require exposing all the internals through this one header...
388  *
389  * \ingroup module_options
390  */
391 template <typename EnumType>
392 class EnumIndexStore : public IOptionValueStore<int>
393 {
394     public:
395         //! Initializes the storage for the given actual enum variables.
396         EnumIndexStore(EnumType *store, std::vector<EnumType> *storeVector)
397             : store_(store), storeVector_(storeVector)
398         {
399             if (storeVector_ != nullptr)
400             {
401                 for (EnumType value : *storeVector_)
402                 {
403                     intStore_.push_back(static_cast<int>(value));
404                 }
405             }
406             else if (store_ != nullptr)
407             {
408                 // TODO: Copy more than one value if that would make sense.
409                 intStore_.push_back(static_cast<int>(store_[0]));
410             }
411         }
412
413         int valueCount() override { return static_cast<int>(intStore_.size()); }
414         ArrayRef<int> values() override { return intStore_; }
415         void clear() override
416         {
417             intStore_.clear();
418             if (storeVector_ != nullptr)
419             {
420                 storeVector_->clear();
421             }
422         }
423         void reserve(size_t count) override
424         {
425             intStore_.reserve(intStore_.size() + count);
426             if (storeVector_ != nullptr)
427             {
428                 storeVector_->reserve(storeVector_->size() + count);
429             }
430         }
431         void append(const int &value) override
432         {
433             const size_t count = intStore_.size();
434             intStore_.push_back(value);
435             if (store_ != nullptr)
436             {
437                 store_[count] = static_cast<EnumType>(value);
438             }
439             if (storeVector_ != nullptr)
440             {
441                 storeVector_->push_back(static_cast<EnumType>(value));
442             }
443         }
444
445     private:
446         //! Stores the integer values for values().
447         std::vector<int>       intStore_;
448         EnumType              *store_;
449         std::vector<EnumType> *storeVector_;
450 };
451
452 //! \cond internal
453 /*! \internal
454  * \brief
455  * Helper to create EnumOptionStorage instances.
456  *
457  * This function works as a proxy between EnumOption::createStorage() and the
458  * EnumOptionStorage constructor, such that the latter does not need to be
459  * exposed in the header.
460  *
461  * \ingroup module_options
462  */
463 AbstractOptionStorage *
464 createEnumOptionStorage(const AbstractOption &option,
465                         const char *const *enumValues, int count,
466                         int defaultValue, int defaultValueIfSet,
467                         std::unique_ptr<IOptionValueStore<int> > store);
468 //! \endcond
469
470 }   // namespace internal
471
472 //! \addtogroup module_options
473 //! \{
474
475 /*! \brief
476  * Specifies an option that accepts enumerated string values and writes the
477  * selected index into an `enum` variable.
478  *
479  * \tparam EnumType  Type of the variable that receives the values
480  *     (can also be `int`).
481  *
482  * Examples:
483  * \code
484    enum MyEnum { eAtom, eRes, eMol };
485    using gmx::EnumOption;
486    const char * const  allowed[] = { "atom", "residue", "molecule" };
487    MyEnum       value = eAtom; // default value
488    options.addOption(EnumOption<MyEnum>("type").enumValue(allowed).store(&value));
489  * \endcode
490  *
491  * storeCount() is not currently implemented for this option type, and
492  * providing multiple default values through an array passed to store() does
493  * not work consistently in all cases.
494  * In the current implementation, the values of the enum type should correspond
495  * to indices in the array passed to enumValue(), i.e., be consencutive
496  * starting from zero.  Only values corresponding to valid indices are accepted
497  * as parameters to, e.g., defaultValue().  However, other values can be used
498  * as the initial value of the variable (`value` in the above example), and
499  * those will be preserved if the option is not set.
500  *
501  * Public methods in this class do not throw.
502  *
503  * \inpublicapi
504  */
505 template <typename EnumType>
506 class EnumOption : public OptionTemplate<EnumType, EnumOption<EnumType> >
507 {
508     public:
509         //! OptionInfo subclass corresponding to this option type.
510         typedef EnumOptionInfo InfoType;
511
512         // This needs to be duplicated from OptionTemplate because this class
513         // is a template.
514         //! Short-hand for the base class.
515         typedef OptionTemplate<EnumType, EnumOption<EnumType> > MyBase;
516
517         //! Initializes an option with the given name.
518         explicit EnumOption(const char *name)
519             : MyBase(name), enumValues_(nullptr), enumValuesCount_(0)
520         {
521         }
522
523         /*! \brief
524          * Sets the option to only accept one of a fixed set of strings.
525          *
526          * \param[in] values  Array of strings to accept.
527          *
528          * Also accepts prefixes of the strings; if a prefix matches more than
529          * one of the possible strings, the shortest one is used (in a tie, the
530          * first one is).
531          *
532          * The strings are copied once the option is created.
533          */
534         template <size_t count>
535         EnumOption &enumValue(const char *const (&values)[count])
536         {
537             GMX_ASSERT(enumValues_ == nullptr,
538                        "Multiple sets of enumerated values specified");
539             enumValues_      = values;
540             enumValuesCount_ = count;
541             return MyBase::me();
542         }
543         /*! \brief
544          * Sets the option to only accept one of a fixed set of strings.
545          *
546          * \param[in] values  Array of strings to accept, with a NULL pointer
547          *      following the last string.
548          *
549          * Works otherwise as the array version, but accepts a pointer to
550          * an array of undetermined length.  The end of the array is indicated
551          * by a NULL pointer in the array.
552          *
553          * \see enumValue()
554          */
555         EnumOption &enumValueFromNullTerminatedArray(const char *const *values)
556         {
557             GMX_ASSERT(enumValues_ == nullptr,
558                        "Multiple sets of enumerated values specified");
559             enumValues_      = values;
560             enumValuesCount_ = -1;
561             return MyBase::me();
562         }
563
564     private:
565         //! Helper function to convert default values for storate initialization.
566         static int convertToInt(const EnumType *defaultValue)
567         {
568             return defaultValue != nullptr ? static_cast<int>(*defaultValue) : -1;
569         }
570
571         //! Creates a EnumOptionStorage object.
572         AbstractOptionStorage *createStorage(
573             const OptionManagerContainer & /*managers*/) const override
574         {
575             // TODO: Implement storeCount() if necessary.
576             return internal::createEnumOptionStorage(
577                     *this, enumValues_, enumValuesCount_,
578                     convertToInt(MyBase::defaultValue()),
579                     convertToInt(MyBase::defaultValueIfSet()),
580                     std::make_unique<internal::EnumIndexStore<EnumType> >(
581                             MyBase::store(), MyBase::storeVector()));
582         }
583
584         const char *const      *enumValues_;
585         int                     enumValuesCount_;
586
587         /*! \brief
588          * Needed to initialize EnumOptionStorage from this class without
589          * otherwise unnecessary accessors.
590          */
591         friend class EnumOptionStorage;
592 };
593
594 //! Shorthand for an enumerated option that stores into an `int` variable.
595 typedef EnumOption<int> EnumIntOption;
596
597 /*! \brief
598  * Wrapper class for accessing boolean option information.
599  *
600  * \inpublicapi
601  */
602 class BooleanOptionInfo : public OptionInfo
603 {
604     public:
605         //! Creates an option info object for the given option.
606         explicit BooleanOptionInfo(BooleanOptionStorage *option);
607
608         //! Returns the default value for this option.
609         bool defaultValue() const;
610
611     private:
612         const BooleanOptionStorage &option() const;
613 };
614
615 /*! \brief
616  * Wrapper class for accessing integer option information.
617  *
618  * \inpublicapi
619  */
620 class IntegerOptionInfo : public OptionInfo
621 {
622     public:
623         //! Creates an option info object for the given option.
624         explicit IntegerOptionInfo(IntegerOptionStorage *option);
625 };
626
627 /*! \brief
628  * Wrapper class for accessing 64-bit integer option information.
629  *
630  * \inpublicapi
631  */
632 class Int64OptionInfo : public OptionInfo
633 {
634     public:
635         //! Creates an option info object for the given option.
636         explicit Int64OptionInfo(Int64OptionStorage *option);
637 };
638
639 /*! \brief
640  * Wrapper class for accessing floating-point option information.
641  *
642  * \inpublicapi
643  */
644 class DoubleOptionInfo : public OptionInfo
645 {
646     public:
647         //! Creates an option info object for the given option.
648         explicit DoubleOptionInfo(DoubleOptionStorage *option);
649
650         //! Whether the option specifies a time value.
651         bool isTime() const;
652
653         /*! \brief
654          * Sets a scale factor for user-provided values.
655          *
656          * Any user-provided value is scaled by the provided factor.
657          * Programmatically set default values are not scaled.
658          * If called multiple times, later calls override the previously set
659          * value.  In other words, the scaling is not cumulative.
660          */
661         void setScaleFactor(double factor);
662
663     private:
664         DoubleOptionStorage &option();
665         const DoubleOptionStorage &option() const;
666 };
667
668 /*! \brief
669  * Wrapper class for accessing floating-point option information.
670  *
671  * \inpublicapi
672  */
673 class FloatOptionInfo : public OptionInfo
674 {
675     public:
676         //! Creates an option info object for the given option.
677         explicit FloatOptionInfo(FloatOptionStorage *option);
678
679         //! Whether the option specifies a time value.
680         bool isTime() const;
681
682         //! \copydoc DoubleOptionInfo::setScaleFactor()
683         void setScaleFactor(double factor);
684
685     private:
686         FloatOptionStorage &option();
687         const FloatOptionStorage &option() const;
688 };
689
690 /*! \brief
691  * Wrapper class for accessing string option information.
692  *
693  * \inpublicapi
694  */
695 class StringOptionInfo : public OptionInfo
696 {
697     public:
698         //! Creates an option info object for the given option.
699         explicit StringOptionInfo(StringOptionStorage *option);
700
701         /*! \brief
702          * Whether this option accepts an enumerated set of values.
703          *
704          * Returns true if StringOption::enumValues() was used when creating
705          * this option.
706          */
707         bool isEnumerated() const;
708         /*! \brief
709          * Returns the set of allowed values for this option.
710          *
711          * Returns an empty vector if isEnumerated() returns false.
712          */
713         const std::vector<std::string> &allowedValues() const;
714
715     private:
716         const StringOptionStorage &option() const;
717 };
718
719 /*! \brief
720  * Wrapper class for accessing enum option information.
721  *
722  * \inpublicapi
723  */
724 class EnumOptionInfo : public OptionInfo
725 {
726     public:
727         //! Creates an option info object for the given option.
728         explicit EnumOptionInfo(EnumOptionStorage *option);
729
730         /*! \brief
731          * Returns the set of allowed values for this option.
732          */
733         const std::vector<std::string> &allowedValues() const;
734
735     private:
736         const EnumOptionStorage &option() const;
737 };
738
739 /*! \typedef RealOption
740  * \brief
741  * Typedef for either DoubleOption or FloatOption, depending on precision.
742  *
743  * Generally, new would be better using DoubleOption, but this is provided for
744  * cases where the output value needs to be of type `real` for some reason.
745  */
746 /*! \typedef RealOptionInfo
747  * \brief
748  * Typedef for either DoubleOptionInfo or FloatOptionInfo, depending on precision.
749  *
750  * Generally, new would be better using DoubleOption, but this is provided for
751  * cases where the output value needs to be of type `real` for some reason.
752  */
753 #if GMX_DOUBLE
754 typedef DoubleOption     RealOption;
755 typedef DoubleOptionInfo RealOptionInfo;
756 #else
757 typedef FloatOption      RealOption;
758 typedef FloatOptionInfo  RealOptionInfo;
759 #endif
760
761 //! \}
762
763 } // namespace gmx
764
765 #endif