Entwicklung einer einfachen Matrizenklasse



  • Dieser Beitrag wurde gelöscht!


  • So, jetzt nochmal.
    Gut, dann jetzt, wie man zB eine Einheitsmatrix erstellt. Da hätte ich zwei Vorschläge, der erste erscheint mir besser. Kann aber sein, das es besseres gibt, was mir nur nicht einfällt.
    Ich lass das jetzt auch stehen, auch wenn mir in der Zwischenzeit was anderes einfällt

    template<typename T>
    class UnitMat_T : public Mat2D_T<T>
    {
    public:
    	using size_t = std::size_t;
    
    	UnitMat_T(const size_t size)
    		: Mat2D_T<T>(size, size)
    	{
    		for (size_t n = 0; n < size; ++n)
    			(*this)(n, n) = static_cast<T>(1);
    	}
    };
    
    
    template<typename T>
    Mat2D_T<T>getUnitMat(const std::size_t size)
    {
    	Mat2D_T<T> ut(size, size);
    
    	for (std::size_t n = 0; n < size; ++n)
    		ut(n, n) = static_cast<T>(1);
    
    	return ut;
    }
    


  • @zeropage sagte in Entwicklung einer einfachen Matrizenklasse:

    So, jetzt nochmal.
    Gut, dann jetzt, wie man zB eine Einheitsmatrix erstellt. Da hätte ich zwei Vorschläge, der erste erscheint mir besser. [...]

    template<typename T>
    class UnitMat_T : public Mat2D_T<T>
    

    Also ich finde den zweiten besser. UnitMat_T ist wie ein float_value_1_t. Wenn du keinen extrem guten Grund hast, für einen speziellen Wert einen eigenen Typen zu haben, dann lass es. Es wird noch genug andere Gelegenheiten geben, sich das Leben selbst schwer zu machen 😉

    Eigener Typ für quadratische Matrizen könnte ich noch akzeptieren. Die haben ja durchaus etwas andere algebraische Eigenschaften, die einen zusätzlichen Typen rechtfertigen können.



  • Ok. Und die Funktion (dann auch ohne Template?) getUnitMat()oder gleichUnitMat()kann ich dann in den Mat2Dnamespace schieben?



  • Dieser Beitrag wurde gelöscht!


  • Also so? (mit meinem haben wollen Point). Obwohl eigentlich Blödsinn, ich möchte ja einen Typ Point. Aber ich lösch das nicht schon wieder.

    namespace Mat2D
    {
    	template<typename val_t>
    	Mat2D_T<val_t> UnitMat(const std::size_t size)
    	{
    		Mat2D_T<val_t> ut(size, size);
    
    		for (std::size_t n = 0; n < size; ++n)
    			ut(n, n) = static_cast<val_t>(1);
    
    		return ut;
    	}
    	template<typename val_t>
    	Mat2D_T<val_t> Point2D(const val_t x, const val_t y)
    	{
    		Mat2D_T<val_t> p{ { x, y, static_cast<val_t>(1) } };
    		return p;
    	}
    	template<typename val_t>
    	Mat2D_T<val_t> Point3D(const val_t x, const val_t y, const val_t z)
    	{
    		Mat2D_T<val_t> p{ { x, y, z } };
    		return p;
    	}
    
    	void print(const Mat2D_T<int>& mT, const int cwidth = 4, std::ostream& stream = std::cout);
    	void printElement(const Mat2D_T<int>& mT, const size_t row, const size_t column, const int cwidth, std::ostream& stream = std::cout);
    	void print(const Mat2D_T<float>& mT, const int cwidth = 4, std::ostream& stream = std::cout);
    	void printElement(const Mat2D_T<float>& mT, const size_t row, const size_t column, const int cwidth, std::ostream& stream = std::cout);
    	void print(const Mat2D_T<double>& mT, const int cwidth = 4, std::ostream& stream = std::cout);
    	void printElement(const Mat2D_T<double>& mT, const size_t row, const size_t column, const int cwidth, std::ostream& stream = std::cout);
    }
    
    
    


  • @zeropage sagte in Entwicklung einer einfachen Matrizenklasse:

    static_cast<val_t>(1)

    wth?



  • Erst mal 'wth' nachschlagen. "what the hell" oder "heaven" plus Fragezeichen.
    Öhm, was nimmt man denn da, wenn es eine 1 sein soll?


  • Mod

    Versuch es mal mit 1.



  • @SeppJ sagte in Entwicklung einer einfachen Matrizenklasse:

    Versuch es mal mit 1.

    1 geht auch, aber ich finde es sogar gut, mit eigentlich überflüssigen static_cast die bewusste Absicht zu dokumentieren. Da weiss später jeder dass es so gewollt war.


  • Mod

    Bewusste Absicht von was? 1 ist 1. noch dazu auf der rechten Seite einer Zuweisung. Soll man wirklich für den Fall programmieren, dass val_t einen überladenen Zuweisungsoperator hat? Der zudem eine sehr sonderbare (nicht-arithmetische) Semantik hätte.



  • @Finnegan sagte in Entwicklung einer einfachen Matrizenklasse:

    mit eigentlich überflüssigen static_cast die bewusste Absicht zu dokumentieren.

    val_t{ 1 } ^^



  • @SeppJ sagte in Entwicklung einer einfachen Matrizenklasse:

    Bewusste Absicht von was? 1 ist 1. noch dazu auf der rechten Seite einer Zuweisung. Soll man wirklich für den Fall programmieren, dass val_t einen überladenen Zuweisungsoperator hat? Der zudem eine sehr sonderbare (nicht-arithmetische) Semantik hätte.

    Simple Dokumentation, dass man die Repräsentation der 1 als float, complex oder sonstwas in dem Element speichern möchte und man sich bewusst ist, dass die Matrix nicht unbedingt ints enthält. Da denke ich nichtmal an komische Typen, sondern dass jemand, der meinen Code liest, klar meine Intention herauslesen kann.

    Hier mag es trivial sein, woanders vielleicht nicht (und jemand stellt meinen Code um wo vielleicht eine Integer Promotion nicht mehr so läuft wie beabsichtigt). Es schadet jedenfalls nicht, klar in Code auszudrücken, was man will.

    @Swordfish sagte in Entwicklung einer einfachen Matrizenklasse:

    val_t{ 1 } ^^

    Ja, das wär auch okay 😉


  • Mod

    @Finnegan sagte in Entwicklung einer einfachen Matrizenklasse:

    @SeppJ sagte in Entwicklung einer einfachen Matrizenklasse:

    Bewusste Absicht von was? 1 ist 1. noch dazu auf der rechten Seite einer Zuweisung. Soll man wirklich für den Fall programmieren, dass val_t einen überladenen Zuweisungsoperator hat? Der zudem eine sehr sonderbare (nicht-arithmetische) Semantik hätte.

    Simple Dokumentation, dass man die Repräsentation der 1 als float, complex oder sonstwas in dem Element speichern möchte und man sich bewusst ist, dass die Matrix nicht unbedingt ints enthält. Da denke ich nichtmal an komische Typen, sondern dass jemand, der meinen Code liest, klar meine Intention herauslesen kann.

    Du hast komische Absichten und Dokumentation. Da steht links eine Variable von irgendeinem Typ, rechts der Wert 1, dazwischen ein =. Wie braucht man da noch extra Dokumentation, dass diese Zeile bezwecken soll, dass die Variable links den Wert rechts annimmt?

    Schreibst du auch std::string str = static_cast<std::string>("Hallo");?



  • @Swordfish sagte in Entwicklung einer einfachen Matrizenklasse:

    val_t{ 1 }

    Oh, cool. Wollte ich zuerst machen, erschien mir aber zu simpel. Aber noch wunderbarer ist einfach = 1. Hatte ich auch im Sinn, erschien mir aber schon unmöglich simpler.



  • @SeppJ sagte in Entwicklung einer einfachen Matrizenklasse:

    Du hast komische Absichten und Dokumentation. Da steht links eine Variable von irgendeinem Typ, rechts der Wert 1, dazwischen ein =.

    Links steht ein Funktionsaufruf.

    Wie braucht man da noch extra Dokumentation, dass diese Zeile bezwecken soll, dass die Variable links den Wert rechts annimmt?

    Nein, mein Code sagt, dass es meine Absicht ist, einen Wert vom Typ val_t zuzuweisen, dessen Wert 1 ist. Das sind zwei Eigenschaften, nicht nur der Wert.

    Bei diesem Code hier ist es wumpe, aber das weiss ich auch nur, weil ich den Code-Kontext kenne. Nur an der betreffenden Zeile kann ich das nicht sehen. Z.B. bei ein std::any oder etwas anderem mit Type Deduction könnte der Code im weiteren Verlauf empfindlich auf den fehlenden Cast reagieren.

    Bei einer Matrix rührt mein Bedürfnis dazu auch vornehmlich daher, dass ich eigentlich keine "Eins" will, sondern das Neutrale Element von val_t bezüglich Multiplikation. Das drückt der Cast für mich auch noch aus - ich will ein 1-Element des Typen val_t. Dazu kommt, dass das hier quasi Library-Code ist, da bin ich immer etwas expliziter. In User-Code würde ich auch ne blanke 1 schreiben ...

    Schreibst du auch std::string str = static_cast<std::string>("Hallo");?

    ... so einen Cast mache ich also nicht immer. Hier^^^ z.B. nicht 😉

    Ansonsten sehe ich keinen Schaden das so zu schreiben und verstehe nicht ganz warum das überhaupt eine Diskussion Wert ist. Ich zwinge ja niemanden, das auch so zu machen.


  • Mod

    @Finnegan sagte in Entwicklung einer einfachen Matrizenklasse:

    Ansonsten sehe ich keinen Schaden das so zu schreiben und verstehe nicht ganz warum das überhaupt eine Diskussion Wert ist. Ich zwinge ja niemanden, das auch so zu machen.

    Weil das komisch inkonsistenter Cargo-Cult ist. Wenn du irgendwie argumentierst, dass das sinnvoll ist, dann musst du std::string str = static_cast<std::string>("Hallo"); schreiben. Gerade dann, denn da macht der Cast ja tatsächlich etwas. Tust du aber nicht, weil das offensichtlicher Unsinn ist. Und genauso offensichtlicher Unsinn ist der Fall hier auch, wo du es plötzlich doch machen willst. Das heißt, du machst bloß irgendwelche Muster nach, die du mal gesehen hast, aber ohne sie verstanden zu haben.

    Mal anders gesagt: Was würde passieren, wenn da ut(n, n) = static_cast<float>(1) stünde, aber val_t kein float ist? Wird da deiner Meinung nach dann ein float gespeichert?



  • Wenn das so gemacht wird, ist es ok?

            template <typename val_t>
    	Mat2D_T<val_t> UnitMat(const std::size_t size)
    	{
    		Mat2D_T<val_t> ut(size, size);
    
    		for (std::size_t n = 0; n < size; ++n)
    			ut(n, n) = { 1 };
    
    		return ut;
    	}
    	template <typename val_t>
    	Mat2D_T<val_t> Point2D(const val_t x, const val_t y)
    	{
    		Mat2D_T<val_t> p{ { x, y, { 1 } } };
    		return p;
    	}
    	template <typename val_t>
    	Mat2D_T<val_t> Point2D(const std::initializer_list<val_t>& list)
    	{
    		Mat2D_T<val_t> p{ list };
    		return p;
    	}
    	template <typename val_t>
    	Mat2D_T<val_t> Point3D(const val_t x, const val_t y, const val_t z) 
    	{
    		Mat2D_T<val_t> p{ { x, y, z } };
    		return p;
    	}
    	template <typename val_t>
    	Mat2D_T<val_t> Point3D(const std::initializer_list<val_t> list)
    	{
    		Mat2D_T<val_t> p{ list };
    		return p;
    	}
    

  • Mod

    Lässt sich Zeile 7 überhaupt übersetzen?



  • Huch, Schreck! Sollte es nicht?

    Mat2D_T<float> ut = Mat2D::UnitMat<float>(4);
    Mat2D::print(ut);
    

    Unter Visual Studio 19 geht das bei mir. Ich kann aber gerne die geschweiften Klammern weglassen, wenn das wirklich kein Ding ist.
    Oder eben

    ut(n, n) = val_t{ 1 };
    

Anmelden zum Antworten