diff --git a/eo/src/utils/eoHowMany.h b/eo/src/utils/eoHowMany.h
index e0b24e56..908dce90 100644
--- a/eo/src/utils/eoHowMany.h
+++ b/eo/src/utils/eoHowMany.h
@@ -26,53 +26,92 @@
#ifndef eoHowMany_h
#define eoHowMany_h
-/**
- * to be used in selection / replacement procedures to indicate whether
- * the argument (rate, a double) shoudl be treated as a rate (number=rate*popSize)
- * or as an absolute integer (number=rate regardless of popsize).
- * the default value shoudl ALWAYS be true (eo_as_a_rate).
- *
- * this construct is mandatory because in some cases you might not know the
+/** A helper class, to determine a number of individuals from another one
+ * Typically, is used in selection / replacement procedures, e.g.
+ * the number of offspring from the number of parents, or
+ * the number of survivors for an eoReduce functor, ...
+ *
+ * Such construct is very useful because in some cases you might not know the
* population size that will enter the replacement. For instance, you
* cannot simply have a pre-computed (double) rate of 1/popSize
- * if you want 1 guy
+ * if you want to select or kill just 1 guy. Using an eoHowMany
+ * allows one to modify the population size without touching anything else.
+ *
+ * There are 3 possible way to compute the return value from the argument:
+ * - a rate -> return rate*popSize
+ * - an absolute POSITIVE integer --> return rate (regardless of popsize)
+ * - an absolute NEGATIVE integer --> return popsize-rate
+ * Note that a negative rate is unnecessary because a rate is relative anyway.
+ *
+ * It has 2 private members, a double for case 1,
+ * and an integer for cases 2 and 3 above
*
* Example use: in eoGeneralBreeder.h
* Example reading from parser: in
* do/make_algo_scalar.h line 141
+
+ * MS 10/04/2002:
+ * Added the possibility to have a negative number -
+ * when treated as a number: returns then (size - combien)
+ * Should not modify anything when a positive number is passed in the ctor
+ *
+ * It is an eoPersistent because we need to be able to use eoParamValue
*/
class eoHowMany : public eoPersistent
{
public:
- /** Original Ctor from direct rate + bool */
+ /** Original Ctor from direct rate + bool
+ @param rate the rate, OR the integer to store, depending on 2nd arg.
+ @param _interpret_as_rate to tell whether the rate actually is a rate
+ */
eoHowMany(double _rate = 0.0, bool _interpret_as_rate = true):
- rate(0), combien(0)
+ rate(_rate), combien(0)
{
if (_interpret_as_rate)
{
- rate = _rate;
+ if (_rate<0)
+ throw std::logic_error("Negative rate in eoHowMany!");
}
else
{
- if (_rate<0)
- throw std::logic_error("Negative number in eoHowMany!");
- combien = (unsigned int)_rate;
+ rate = 0.0; // just in case, but shoud be unused
+ combien = int(_rate); // negative values are allowed here
if (combien != _rate)
cout << "Warning: Number was rounded in eoHowMany";
}
}
+ /** Ctor from an int - both from int and unsigned int are needed
+ * to avoid ambiguity with the Ctor from a double */
+ eoHowMany(int _combien) : rate(0.0), combien(_combien) {}
+
+ /** Ctor from an unsigned int - both from int and unsigned int are needed
+ * to avoid ambiguity with the Ctor from a double */
+ eoHowMany(unsigned int _combien) : rate(0.0), combien(_combien) {}
+
/// Virtual dtor. They are needed in virtual class hierarchies.
virtual ~eoHowMany() {}
+ /** Does what it was designed for
+ * - combien==0 : return rate*_size
+ * - else
+ * - combien>0 : return combien (regardless of _size)
+ * - combien<0 : return _size-|combien|
+ */
unsigned int operator()(unsigned int _size)
{
if (combien == 0)
{
return (unsigned int) (rate * _size);
}
- return combien;
+ if (combien < 0)
+ {
+ if (_size+combien<0)
+ throw runtime_error("Negative result in eoHowMany");
+ return _size+combien;
+ }
+ return unsigned(combien);
}
virtual void printOn(ostream& _os) const
@@ -112,16 +151,16 @@ public:
rate /= 100.0;
}
else
- combien = unsigned(rate); // and rate will not be used
+ combien = int(rate); // and rate will not be used
// minimal check
- if ( (combien <= 0) && (rate <= 0.0) )
- throw runtime_error("Invalid parameters read in eoHowMany::readFrom");
+ if ( rate <= 0.0 )
+ throw runtime_error("Negative rate read in eoHowMany::readFrom");
}
private :
double rate;
- unsigned combien;
+ int combien;
};