Parameters: look for ways to properly clamp signed / unsigned
Signed and unsigned integral types have a partial overlap of definition domains, yet due to the automatic promotion rules it is impossible to write a domain clamping function directly, since `std::numeric_limits` returns the domain boundaries in the given type, and `int(-1) < uint(0)` evaluates to false, due to int being is promoted to uint. The attempt to circumvent this problem here relies on a check if the comparison crosses the zero point, and otherwise relies explicitly on the promotion to the number with the larger domain.
This commit is contained in:
parent
11bb3bce73
commit
e3b6b87e93
3 changed files with 432 additions and 10 deletions
|
|
@ -168,11 +168,46 @@ _Pragma("GCC diagnostic ignored \"-Woverloaded-virtual\"")
|
|||
|
||||
/* ===== type conversion details ===== */
|
||||
|
||||
/** Constraint: type \a SUB can not represent the full domain of type \a BAS
|
||||
* @todo implicitly also implements a limitation to »numeric« types,
|
||||
* due to the use of std::numeric_limits
|
||||
*/
|
||||
template<typename SUB, typename BAS>
|
||||
concept sub_domain = std::signed_integral<SUB> != std::signed_integral<BAS>
|
||||
or std::numeric_limits<SUB>::max() < std::numeric_limits<BAS>::max()
|
||||
or std::numeric_limits<SUB>::lowest() > std::numeric_limits<BAS>::lowest()
|
||||
;
|
||||
|
||||
template<typename NUM>
|
||||
inline constexpr bool
|
||||
isNeg (NUM const& num)
|
||||
{
|
||||
return num < NUM(0);
|
||||
};
|
||||
|
||||
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wsign-compare\"")
|
||||
// the following functions are specifically crafted to work around
|
||||
// the ambiguities caused by automatic signed-to-unsigned promotion;
|
||||
// furthermore, the automatic promotion allows to perform the comparison.
|
||||
|
||||
template<typename X, typename Y>
|
||||
inline constexpr bool
|
||||
isLower_safe (X const& x, Y const& y)
|
||||
{
|
||||
return isNeg(x) == isNeg(y)? x < y
|
||||
: isNeg(x);
|
||||
}
|
||||
|
||||
template<typename X, typename Y>
|
||||
inline constexpr bool
|
||||
isLarger_safe (X const& x, Y const& y)
|
||||
{
|
||||
return isNeg(x) == isNeg(y)? x > y
|
||||
: isNeg(y);
|
||||
}
|
||||
_Pragma("GCC diagnostic pop")
|
||||
|
||||
/** generic helper to conform into a common value domain
|
||||
* @tparam SUB the implied target value domain
|
||||
|
|
@ -187,14 +222,23 @@ _Pragma("GCC diagnostic ignored \"-Woverloaded-virtual\"")
|
|||
return value;
|
||||
}
|
||||
|
||||
/** special case: clamp the source value into the target value domain */
|
||||
template<typename SUB, typename BAS> requires sub_domain<SUB,BAS>
|
||||
/** special case: clamp the source value into the target value domain.
|
||||
* @remark tricky due to automatic conversions between signed/unsigned */
|
||||
template<typename SUB, typename BAS> requires (sub_domain<SUB,BAS>
|
||||
and not same_as<SUB,bool>)
|
||||
inline constexpr BAS
|
||||
preClamp (BAS const& rawVal)
|
||||
{
|
||||
static_assert (std::is_constructible_v<BAS,SUB const&>
|
||||
,"Value domains must overlap at least partially "
|
||||
"and values must be cross-constructible within overlap");
|
||||
|
||||
auto upperBound = numeric_limits<SUB>::max();
|
||||
auto lowerBound = numeric_limits<SUB>::lowest();
|
||||
return util::limited (lowerBound, rawVal, upperBound);
|
||||
|
||||
return isLarger_safe(rawVal, upperBound)? BAS(upperBound)
|
||||
: isLower_safe (rawVal, lowerBound)? BAS(lowerBound)
|
||||
: rawVal;
|
||||
}
|
||||
|
||||
/** special case: trigger a bool at the 0.5 level */
|
||||
|
|
|
|||
|
|
@ -91,17 +91,24 @@ SHOW_EXPR(preClamp<uint> (-55))
|
|||
SHOW_EXPR((sub_domain<uint,int>))
|
||||
SHOW_EXPR((sub_domain<int,uint>))
|
||||
SHOW_EXPR((sub_domain<short,long>))
|
||||
SHOW_EXPR((sub_domain<long,short>))
|
||||
SHOW_EXPR(std::numeric_limits<uint>::max())
|
||||
SHOW_EXPR(std::numeric_limits<int>::max())
|
||||
SHOW_EXPR(std::numeric_limits<uint>::lowest())
|
||||
SHOW_EXPR(std::numeric_limits<int>::lowest())
|
||||
// concept sub_domain = std::numeric_limits<SUB>::max() < std::numeric_limits<BAS>::max()
|
||||
// or std::numeric_limits<SUB>::lowest() > std::numeric_limits<BAS>::lowest()
|
||||
//SHOW_EXPR(std::numeric_limits<uint>::lowest() > std::numeric_limits<int>::lowest())
|
||||
//SHOW_EXPR(abs(std::numeric_limits<uint>::lowest()) < (std::numeric_limits<int>::lowest()))
|
||||
|
||||
SHOW_EXPR(preClamp<short> (INT64_MAX))
|
||||
SHOW_EXPR(preClamp<short> (INT64_MIN))
|
||||
|
||||
SHOW_EXPR(preClamp<ushort> (numeric_limits<float>::max()))
|
||||
SHOW_EXPR(preClamp<ushort> (numeric_limits<float>::lowest()))
|
||||
|
||||
SHOW_EXPR(preClamp<float> (numeric_limits<uint64_t>::max()))
|
||||
SHOW_EXPR(preClamp<float> (numeric_limits<double>::lowest()))
|
||||
|
||||
SHOW_EXPR(preClamp<bool> (0.5));
|
||||
SHOW_EXPR(preClamp<bool> (0.5 + numeric_limits<double>::epsilon()))
|
||||
SHOW_EXPR(preClamp<bool> (numeric_limits<double>::min()))
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -81663,15 +81663,22 @@
|
|||
<icon BUILTIN="clanbomber"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1782923489065" ID="ID_298169531" MODIFIED="1782923571066" TEXT="Verzicht auf Destruktor-Aufruf">
|
||||
<node CREATED="1782923489065" ID="ID_298169531" MODIFIED="1782923489065" TEXT="Verzicht auf Destruktor-Aufruf">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
andernfalls <b>muß</b> ich eine VTable mitschleppen, und das würde mir Bauchschmerzen machen, da die Parameter-Auswertund nun doch in die Render-Engine hineinreicht
|
||||
andernfalls <b>muß</b> ich eine VTable mitschleppen, und das würde mir Bauchschmerzen machen, da die Parameter-Auswertung nun doch in die Render-Engine hineinreicht
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<node CREATED="1784672063532" HGAP="26" ID="ID_874197913" MODIFIED="1784672142538" TEXT="nicht mehr so klar — VTable brauche ich ohnehin für die Kopierbarkeit" VSHIFT="2">
|
||||
<arrowlink COLOR="#fedeb1" DESTINATION="ID_1260735860" ENDARROW="Default" ENDINCLINATION="221;-1409;" ID="Arrow_ID_871558965" STARTARROW="None" STARTINCLINATION="1349;50;"/>
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1784672159561" ID="ID_1607967603" MODIFIED="1784672179337" TEXT="Unterscheidung »Basiswerte« — »komplexe Parameter«?">
|
||||
<icon BUILTIN="help"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1782923626958" ID="ID_386912733" MODIFIED="1782923647319" TEXT="Gefordert ist also: ein halb-dynamischer safety-Check">
|
||||
|
|
@ -82662,7 +82669,8 @@
|
|||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1784480336698" ID="ID_440800496" MODIFIED="1784480356903" TEXT="Spielräume">
|
||||
<icon BUILTIN="yes"/>
|
||||
<icon BUILTIN="forward"/>
|
||||
<node CREATED="1784480360439" ID="ID_1260735860" MODIFIED="1784480368981" TEXT="nicht zu sehr verrückt machen....">
|
||||
<node CREATED="1784480360439" ID="ID_1260735860" MODIFIED="1784672142539" TEXT="nicht zu sehr verrückt machen....">
|
||||
<linktarget COLOR="#fedeb1" DESTINATION="ID_1260735860" ENDARROW="Default" ENDINCLINATION="221;-1409;" ID="Arrow_ID_871558965" SOURCE="ID_874197913" STARTARROW="None" STARTINCLINATION="1349;50;"/>
|
||||
<icon BUILTIN="ksmiletris"/>
|
||||
</node>
|
||||
<node CREATED="1784480371646" ID="ID_74554440" MODIFIED="1784480388324">
|
||||
|
|
@ -83122,6 +83130,275 @@
|
|||
<node COLOR="#5b280f" CREATED="1784593459863" ID="ID_492548018" MODIFIED="1784593634425" TEXT="aber signed vs. unsigned- Werte lassen sich überhaupt nicht ohne Weiteres vergleichen">
|
||||
<arrowlink COLOR="#c30d0f" DESTINATION="ID_1240698281" ENDARROW="Default" ENDINCLINATION="318;0;" ID="Arrow_ID_1820583210" STARTARROW="None" STARTINCLINATION="195;6;"/>
|
||||
<icon BUILTIN="closed"/>
|
||||
<node CREATED="1784669864149" ID="ID_1893387322" MODIFIED="1784669867944" TEXT="man könnte....">
|
||||
<node CREATED="1784669870432" ID="ID_111028032" MODIFIED="1784669894580" TEXT="in Einzelfälle aufteilen">
|
||||
<node BACKGROUND_COLOR="#accdc3" COLOR="#3f4015" CREATED="1784669944683" ID="ID_739218208" MODIFIED="1784670003838" STYLE="fork" TEXT="Stackoverflow.AI generiert folgende Fallunterscheidung....">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">#include <type_traits> </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">#include <limits> </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">#include <cmath>    // std::isnan, std::trunc, std::llround (if needed) </font>
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">template<typename X, typename U> </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">constexpr X safe_clamp_cast(U value) noexcept { </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">    using Dx = std::numeric_limits<X>; </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">    using Du = std::numeric_limits<U>; </font>
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">    // If target can represent all values of source, direct cast is safe. </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">    if constexpr (std::is_same_v<X, U> || </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">                  (std::is_integral_v<X> && std::is_integral_v<U> && </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">                   (std::is_signed_v<X> == std::is_signed_v<U>) && </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">                   (sizeof(X) >= sizeof(U))) || </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">                  (std::is_floating_point_v<X> && std::is_floating_point_v<U> && </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">                   (sizeof(X) >= sizeof(U)))) { </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">        return static_cast<X>(value); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">    } </font>
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">    // Handle floating source separately </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">    if constexpr (std::is_floating_point_v<U>) { </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">        if (std::isnan(value)) { </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">            // policy: map NaN to 0 (could be Dx::lowest() or Dx::min() depending on needs) </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">            return static_cast<X>(0); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">        } </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">        long double v = static_cast<long double>(value); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">        if (v <= static_cast<long double>(Dx::lowest())) return static_cast<X>(Dx::lowest()); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">        if (v >= static_cast<long double>(Dx::max()))    return static_cast<X>(Dx::max()); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">        // when casting float->int, truncate toward zero (same as static_cast) </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">        return static_cast<X>(v); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">    } </font>
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">    // Now source is integral (U), target X might be integral or floating </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">    if constexpr (std::is_integral_v<U> && std::is_floating_point_v<X>) { </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">        // integer -> float: float may not represent huge integers exactly, but no UB; clamp to finite range </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">        long double v = static_cast<long double>(value); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">        if (v <= static_cast<long double>(Dx::lowest())) return static_cast<X>(Dx::lowest()); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">        if (v >= static_cast<long double>(Dx::max()))    return static_cast<X>(Dx::max()); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">        return static_cast<X>(v); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">    } </font>
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">    // Both integral but possibly differing signedness/range </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">    if constexpr (std::is_integral_v<X> && std::is_integral_v<U>) { </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">        if constexpr (std::is_signed_v<U> && !std::is_signed_v<X>) { </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">            // signed source -> unsigned target </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">            if (value < 0) return static_cast<X>(0); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">            using UT_prom = std::make_unsigned_t<U>; </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">            UT_prom uv = static_cast<UT_prom>(value); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">            if (uv > static_cast<std::make_unsigned_t<X>>(Dx::max())) return static_cast<X>(Dx::max()); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">            return static_cast<X>(uv); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">        } else if constexpr (!std::is_signed_v<U> && std::is_signed_v<X>) { </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">            // unsigned source -> signed target </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">            using UX_prom = std::make_unsigned_t<X>; </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">            if (value > static_cast<std::make_unsigned_t<U>>(Dx::max())) return static_cast<X>(Dx::max()); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">            return static_cast<X>(value); // safe </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">        } else { </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">            // same signedness but different sizes </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">            if constexpr (sizeof(U) > sizeof(X)) { </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">                if (value > static_cast<U>(Dx::max())) return static_cast<X>(Dx::max()); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">                if (std::is_signed_v<U> && value < static_cast<U>(Dx::lowest())) return static_cast<X>(Dx::lowest()); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">            } </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">            return static_cast<X>(value); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">        } </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">    } </font>
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">    // Fallback </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">    return static_cast<X>(value); </font>
|
||||
</p>
|
||||
<p>
|
||||
<font face="Monospaced" size="2">}</font>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<edge COLOR="#808080" STYLE="bezier" WIDTH="thin"/>
|
||||
<icon BUILTIN="wizard"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1784669896248" ID="ID_406155259" LINK="https://stackoverflow.com/a/53027613/444796" MODIFIED="1784670033706" TEXT="die Vergleichsoperation sicher machen">
|
||||
<node CREATED="1784670911841" ID="ID_601580251" MODIFIED="1784671009442" TEXT="man kann sicher auf "negativ" testen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Unter der Annahme, daß lediglich die signed/unsigned Integers das Problem sind; denn für jeden Integer-Typ kann man val < TY(0) bilden
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<node CREATED="1784671014259" ID="ID_242078970" MODIFIED="1784671026710" TEXT="�� das sollte in util-hpp"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1784671027530" ID="ID_398950707" MODIFIED="1784671109521" TEXT="oops ... da ist geich daneben ein Bug">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
die Funktion "noneg()" macht den Verlgeich genau falsch herum:  <font color="#a10000">0 < uint(-1) ⟹ true</font>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="broken-line"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1784676789512" ID="ID_597609808" MODIFIED="1784676806736" TEXT="danach ⟹ Fallunterscheidung cross-sign">
|
||||
<node CREATED="1784676809839" ID="ID_1209038292" MODIFIED="1784676891332" TEXT="wenn beide auf der positiven oder negativen Seite ⟹ kann vergleichen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
hier hilft uns die automatische Promotion in den Typ mit dem höheren Rank: nur deshalb können wir die Vergleichsoperation machen. Zudem kann der Verleich im negativen Segment überhaupt nur stattfinden, wenn beide Typen negativ sind, also mithin signed
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1784676822935" ID="ID_148161124" MODIFIED="1784676835365" TEXT="sonst genügt es, festzustellen, wer auf der negativen Seite steht"/>
|
||||
</node>
|
||||
<node CREATED="1784676915183" ID="ID_426278136" MODIFIED="1784676924529" TEXT="»Untiefen«">
|
||||
<node CREATED="1784676925660" ID="ID_659876949" MODIFIED="1784676940511" TEXT="nicht wirklich klar, was hier »zahlenartige« Typen sind...."/>
|
||||
<node CREATED="1784676941683" ID="ID_1586533827" MODIFIED="1784676970939" TEXT="Annahme: wenn auseinander konstruierbar ⟹ Wert-Domänen überlappen sich"/>
|
||||
<node CREATED="1784676972079" ID="ID_459908237" MODIFIED="1784677047037" TEXT="Trennung der Wert-Domänen liegt tatsächlich auf der Null, mithin innerhalb der Sub-Domäne"/>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1784677065579" ID="ID_1383641297" MODIFIED="1784677094780" TEXT="schalte -Wsign-compare explizit ab für diese Funktion">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1784677107645" HGAP="26" ID="ID_290383571" MODIFIED="1784677121609" TEXT="GCC-spezifisches Pragma" VSHIFT="7">
|
||||
<icon BUILTIN="clanbomber"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -83167,6 +83444,9 @@
|
|||
</html></richcontent>
|
||||
<linktarget COLOR="#4490cf" DESTINATION="ID_1748150865" ENDARROW="Default" ENDINCLINATION="-102;-5;" ID="Arrow_ID_1245799800" SOURCE="ID_1119403748" STARTARROW="None" STARTINCLINATION="-15;97;"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#b3020b" CREATED="1784674883894" ID="ID_25505345" MODIFIED="1784674910088" TEXT="viele offene Flanken hier: setzt eigentlich »zahlenartige« Basistypen vorraus">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -83186,6 +83466,97 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1784672238011" ID="ID_1348610595" MODIFIED="1784672242463" TEXT="offene Fragen">
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1784672283635" ID="ID_164133408" MODIFIED="1784672380497" TEXT="wollen wir eine Art »String« unterstützen?">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
hier steckt das Thema Speicher, deep-copy, interned-strings, Konstanten, Inline-IDs? Vielleicht genügt guter Support für Ennumerationen?
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1784672304720" ID="ID_1556240219" MODIFIED="1784672496130" TEXT="wie repräsentieren wir Ennummerationen / Finite-Domain?">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
gemeint ist: man muß die Ennumeratoren irgendwo in Textform vorhalten, und muß parsen können; einzelne Ennumeratoren könnten dynamisch hinzugefügt werden, oder gar ganze Finite-Domains per Konfiguration oder dynamischer Definition. Hier tut sich ein Abgrund an Komplexität auf — im Grunde verweist das direkt in den Themenkomplex »<b>Domain-Ontology</b>«
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1784672517211" ID="ID_189232786" MODIFIED="1784672718824" TEXT="wollen wir »numerische« Parameter eigens per Typ fassen?">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
was heißt hier »numerisch«?
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
sind bool und char mit eingeschlossen?
|
||||
</li>
|
||||
<li>
|
||||
wollen wir spezielle Custom-Types, wie Big-Deciamal varianten hier miterfassen?
|
||||
</li>
|
||||
<li>
|
||||
was ist mit Brüchen (boost::rational) und Komplexen Zahlen? Bitte nicht lachen...
|
||||
</li>
|
||||
<li>
|
||||
wollen wir auf das Konzept einer Algebra abstellen? Also zumindest eine Gruppe sowie eine Ordnungsrelation?
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1784672543927" ID="ID_1055715376" MODIFIED="1784673139404" TEXT="beruhen die BaseDomains eigentlich immer auf einem »numerischen« Parameter?">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Im ersten Entwurf habe ich die unterliegenden Typen einfach in eine Typelist gepackt. Die Analyse zeigte ganz klar, daß diese Menge der Basiswerte bereits zur Compile-time festgelegt sein muß, sonst tun sich ganz ekelhafte Probleme auf mit Registrierung und Locking im Zusammenhang mit dem Laden von dynamischen Objekten (Plug-ins)....
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1784672259758" ID="ID_1765265570" MODIFIED="1784673727205" TEXT="wie gehen wir mit Produkttypen um (Vektoren, Farben)?">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Ein billiger Ansatz wäre, das Thema zu ignorieren, und solche Parameter einfach als eine Gruppe von Einzelparametern zu behandeln. Das wäre angemessen, wenn man das als Randthema betrachtet. Gegen diesen Ansatz spricht, daß man an einen Farbwert auch eine Kalibrierungskurve und einen Farbraum anhängen möchte, sonst wird Arbeiten mit professionellen Medien-Produktionsprozessen (HDR, Grading, Mastering) praktisch unmöglich. Auch an verschiedene Spielarten von »3D« sollte man denken, incl. virtueller Projektionsräume. Ein MIttelweg wäre, daß man Parameter-Tupel unterstützt, denen Metadaten angehängt werden
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1784672899810" ID="ID_116986809" MODIFIED="1784673414049" TEXT="wie steht's mit der Animation von »shape Keys« und Masken?">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
....zunächst einmal sind das Produkttypen, aber mit einer hohen Kardinalität. Das Konzept der Shape-Keys reduziert das wieder auf eine Achse, auf der man einen Kontrollparameter animieren kann. Bei Masken besteht das zusätzliche (in der Praxis sehr relevante) Problem, daß »unterwegs« weitere Maskenpunkte dazukommen können, und daß einzelne Maskenpunkte noch weitere Parameter tragen können, wie z.B. eine feather-strength, was extrem wichtig ist für Rotoscoping.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1784673142319" ID="ID_79827229" MODIFIED="1784673414046" TEXT="es könnte auf zwei Kategorien hinauslaufen: einfach vs komplex">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...das heißt, die <i>einfachen Parameter</i> wären tatsächlich in der Speichergröße beschränkt (z.B. 4 Slots) und könnten stets inline transportiert werden; nur für diese einfachen Parameter gäbe es den Ansatz eines generischen Parameters. Wohingegen die <i>komplexen Parameter</i>  von Vornherein symbolisch repräsentiert werden, und nur als Funktion zugänglich sind, möglicherweise überhaupt nur als Resultat einer Animations-Auswertung auf Basis <i>einfacher Steuerparameter.</i> Damit würden im »Parameter-System« auch zwei Zonen entstehen; die <i>einfachen Parameter</i> wären im Kernsystem festgelegt, die Basis-Parameter vielleicht sogar zur Compile-Zeit— wohingegen alle komplexen Parameter in eine »Domain-Ontology« gehören und indirekt über ein Plug-in angesprochen werden....
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1783088795196" ID="ID_1506122335" MODIFIED="1783088801007" TEXT="Einsichten">
|
||||
|
|
|
|||
Loading…
Reference in a new issue