@@ -1103,10 +1103,17 @@ private:
11031103 double _shape;
11041104}
11051105
1106- // / Float parameter following a x^N type mapping (eg: something that doesn't fit in the other categories)
1106+ // / Float parameter following a x^N type mapping
1107+ // / (eg: something that doesn't fit in the other categories)
1108+ // /
1109+ // / To go normalized: min to max => 0 to 1 => exponentiation
1110+ // / Note: when `shape` is 1.0, this is simply a `LinearFloatParameter`.
11071111class PowFloatParameter : FloatParameter
11081112{
1109- this (int index, string name, string label, double min, double max, double defaultValue, double shape) nothrow @nogc
1113+ nothrow :
1114+ @nogc :
1115+
1116+ this (int index, string name, string label, double min, double max, double defaultValue, double shape)
11101117 {
11111118 super (index, name, label, min, max, defaultValue);
11121119 _shape = shape;
@@ -1121,10 +1128,12 @@ class PowFloatParameter : FloatParameter
11211128 v = 1.0 ;
11221129 v = v ^^ (1 / _shape);
11231130
1124- // Note: It's not entirely impossible to imagine a particular way that 1 would be exceeded, since pow
1125- // is implemented with an exp approximation and a log approximation.
1126- // TODO: produce ill case in isolation to see
1127- assert (v >= 0 && v <= 1 ); // will still assert on NaN
1131+ // Note: It's not entirely impossible to imagine a particular
1132+ // way that 1 would be exceeded, since `pow` is implemented
1133+ // with an exp approximation and a log approximation.
1134+ if (v > 1 )
1135+ v = 1 ;
1136+
11281137 return v;
11291138 }
11301139
@@ -1141,3 +1150,73 @@ class PowFloatParameter : FloatParameter
11411150private :
11421151 double _shape;
11431152}
1153+
1154+
1155+ // / Float parameter following a x^N type mapping like `PowFloatParameter`,
1156+ // / but this exponentiation happens as if from -1 to 1 instead of from 0 to 1.
1157+ // /
1158+ // / This allows to model parameters who get a large maximum value,
1159+ // / while still favouring reasonable values around the center.
1160+ // /
1161+ // / To go normalized: min to max => -1 to 1 => exponentiation => 0 to 1
1162+ // / Note: when `shape` is 1.0, this is simply a `LinearFloatParameter`.
1163+ class BipolarFloatParameter : FloatParameter
1164+ {
1165+ nothrow :
1166+ @nogc :
1167+
1168+ this (int index, string name, string label, double min, double max, double defaultValue, double shape)
1169+ {
1170+ super (index, name, label, min, max, defaultValue);
1171+ _shape = shape;
1172+ }
1173+
1174+ override double toNormalized (double value)
1175+ {
1176+ // map to [-1, 1]
1177+ double v = - 1.0 + 2.0 * (value - _min) / (_max - _min);
1178+ if (v < - 1.0 ) v = - 1.0 ;
1179+ if (v > 1.0 ) v = 1.0 ;
1180+
1181+ // signed pow
1182+ double sign = v >= 0.0 ? + 1 : - 1 ;
1183+ if (v < 0 ) v = - v;
1184+ assert (v >= 0 );
1185+ v = sign * (v ^^ (1 / _shape));
1186+
1187+ // map to [0, 1]
1188+ v = 0.5 * (v + 1 );
1189+ if (v < - 1.0 ) v = - 1.0 ;
1190+ if (v > 1.0 ) v = 1.0 ;
1191+
1192+ return v;
1193+ }
1194+
1195+ override double fromNormalized (double normalizedValue)
1196+ {
1197+ // map to [-1, 1]
1198+ normalizedValue = - 1 + 2 * normalizedValue;
1199+
1200+ // sign pow
1201+ double sign = normalizedValue >= 0 ? + 1 : - 1 ;
1202+ if (normalizedValue < 0 ) normalizedValue = - normalizedValue;
1203+ assert (normalizedValue >= 0 );
1204+ double v = (normalizedValue ^^ _shape) * sign;
1205+
1206+ // map to [0, 1]
1207+ v = 0.5 * (v + 1 );
1208+ if (v < - 1.0 ) v = - 1.0 ;
1209+ if (v > 1.0 ) v = 1.0 ;
1210+
1211+ // map to [min, max]
1212+ v = _min + v * (_max - _min);
1213+ if (v < _min)
1214+ v = _min;
1215+ if (v > _max)
1216+ v = _max;
1217+ return v;
1218+ }
1219+
1220+ private :
1221+ double _shape;
1222+ }
0 commit comments