Násobení matic a automatické přetypování

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Násobení matic a automatické přetypování
« Odpověď #60 kdy: 18. 09. 2015, 10:22:27 »
Diskuse se zase zvrtla, tak to shrňme. Jsou tři možnosti:

Vsechny tri moznosti jsou pretypovani, tam ci onde (ta treti je pretypovani po navratu z nasobeni matice). Jediny rozdil je, ze programatori treba v Pythonu chapou jeho typy jako navzajem ruzne, zatimco typovi teoretici to (nekdy) vnimaji jako jeden typ. Jak rikam, typy maji v programovani asi 3 ruzne vyznamy:

  • Umoznuji statickou typovou kontrolu
  • Indikuji zpusob polymorfismu
  • Definuji zpusob ulozeni dat v pameti

V tom tvem tretim pripade jenom kombinujes vyznam slova "typ" 1 a 2, coz je v poradku (protoze slovo typ je zavadejici), ale neni to zadna revoluce. V Haskellu se slovo typ pouziva pro 1. vyznam, v Pythonu pro 2. vyznam, v C pro 3. vyznam (prevazne). Ve vetsine modernejsich jazyku lze kontrolovat vsechny tri vyznamy pomoci ruznych mechanismu (napr. Haskell - typove tridy umoznuji delat vyznam 2).

(I kdyz co umoznuje delat v Haskellu vyznam 3 mi neni jasne. V dobre typovanych jazycich je vyznam 3 neco jako dependency injection, prijde mi, ze je tam nejaka dualita mezi vyznamem 2 a 3 - v podstate dualita mezi typovymi tridami a daty, nebo dualita mezi interfacem a implementaci.)

Takže když mám

Kód: [Vybrat]
func f()->SquareMattix { ...; return SquareMatrix(...) }
tak je někde přetypování? Kde přesně? Možná jen přetypováním myslíme každý něco jiného. Pro mě je přetypování něco ve stylu

Kód: [Vybrat]
let m=Matrix(...); return SquareMatrix(matrix)
nebo

Kód: [Vybrat]
let m:Matrix=...; return m as? SquareMatrix
V prvním případě ale vzniká nový objekt a v tom druhém může vzniknout nil.


Radek Miček

Re:Násobení matic a automatické přetypování
« Odpověď #61 kdy: 18. 09. 2015, 10:34:30 »
To by byl ten případ s (implicitním) přetypováním (operator SquareMatrix()), nicméně ani to mi neumožní napsat v C++ něco jako (m1*m2).trace() (na rozdíl od Swiftu).
Jo, v C++ by bylo třeba něco jako "square(m1*m2).trace()". To není zas tak zlé.

BTW umí nějaký (jiný) jazyk toto?

Kód: [Vybrat]
func *(x:Vector,y:Vector) -> Tensor {...}
func *(x:Vector,y:Vector) -> Double {...}
func *(x:Vector,y:Vector) -> AST {...}

let p:Double = a*b // scalar product
let p:Tensor = a*b // tensor product
let p:AST = a*b // AST

Docela praktické, hlavně ten AST.

V C# lze dosáhnout v podstatě téhož tak, že násobení vrátí instanci MultiplicationResult a třída MultiplicationResult bude obsahovat implicitní konverzi na double a na Tensor. AST lze získat pomocí Expression - tj. násobení místo parametru typu T bude brát parametr typu Expression<T>.

Ve Scale se použije například (ve Scale bude asi hodně možností, jak dosáhnout téhož) trik analogický tomu s CanBuildFrom - tj. násobení bude mít implicitní parametr BuildResult[T] a vracet typ T. Takto definované násobení pak může kdokoliv (i cizí kód) rozšířit na libovolný návratový typ, případně předefinovat jeho chování pro určité návratové typy. S AST lze ve Scale pracovat pomocí maker.

Benchmark by asi dopadl pro C# v tomto případě špatně.

Nevidím důvod, proč by to implementace C# nemohla zoptimalizovat stejně jako Swift. Nevím, jestli to RyuJIT od MS dokáže, nicméně MSIL lze přeložit i do LLVM (Mono, SharpLang, LLILC - zatím značně nekompletní) nebo do C (C# Native).

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Násobení matic a automatické přetypování
« Odpověď #62 kdy: 18. 09. 2015, 10:37:43 »
To by byl ten případ s (implicitním) přetypováním (operator SquareMatrix()), nicméně ani to mi neumožní napsat v C++ něco jako (m1*m2).trace() (na rozdíl od Swiftu).
Jo, v C++ by bylo třeba něco jako "square(m1*m2).trace()". To není zas tak zlé.

BTW umí nějaký (jiný) jazyk toto?

Kód: [Vybrat]
func *(x:Vector,y:Vector) -> Tensor {...}
func *(x:Vector,y:Vector) -> Double {...}
func *(x:Vector,y:Vector) -> AST {...}

let p:Double = a*b // scalar product
let p:Tensor = a*b // tensor product
let p:AST = a*b // AST

Docela praktické, hlavně ten AST.

V C# lze dosáhnout v podstatě téhož tak, že násobení vrátí instanci MultiplicationResult a třída MultiplicationResult bude obsahovat implicitní konverzi na double a na Tensor. AST lze získat pomocí Expression - tj. násobení místo parametru typu T bude brát parametr typu Expression<T>.

Ve Scale se použije například (ve Scale bude asi hodně možností, jak dosáhnout téhož) trik analogický tomu s CanBuildFrom - tj. násobení bude mít implicitní parametr BuildResult[T] a vracet typ T. Takto definované násobení pak může kdokoliv (i cizí kód) rozšířit na libovolný návratový typ, případně předefinovat jeho chování pro určité návratové typy. S AST lze ve Scale pracovat pomocí maker.

Benchmark by asi dopadl pro C# v tomto případě špatně.

Nevidím důvod, proč by to implementace C# nemohla zoptimalizovat stejně jako Swift. Nevím, jestli to RyuJIT od MS dokáže, nicméně MSIL lze přeložit i do LLVM (Mono, SharpLang, LLILC - zatím značně nekompletní) nebo do C (C# Native).
To nevím, jak C# optimalizuje. Vtip je v tom, že Swift tady nic optimalizovat nemusí, jedna metoda se vybere v době překladu. Pokud instanci MultiplicationResult v C# použiju víckrát, tak tam moc prostoru k optimalizaci není.

Radek Miček

Re:Násobení matic a automatické přetypování
« Odpověď #63 kdy: 18. 09. 2015, 10:54:28 »
To by byl ten případ s (implicitním) přetypováním (operator SquareMatrix()), nicméně ani to mi neumožní napsat v C++ něco jako (m1*m2).trace() (na rozdíl od Swiftu).
Jo, v C++ by bylo třeba něco jako "square(m1*m2).trace()". To není zas tak zlé.

BTW umí nějaký (jiný) jazyk toto?

Kód: [Vybrat]
func *(x:Vector,y:Vector) -> Tensor {...}
func *(x:Vector,y:Vector) -> Double {...}
func *(x:Vector,y:Vector) -> AST {...}

let p:Double = a*b // scalar product
let p:Tensor = a*b // tensor product
let p:AST = a*b // AST

Docela praktické, hlavně ten AST.

V C# lze dosáhnout v podstatě téhož tak, že násobení vrátí instanci MultiplicationResult a třída MultiplicationResult bude obsahovat implicitní konverzi na double a na Tensor. AST lze získat pomocí Expression - tj. násobení místo parametru typu T bude brát parametr typu Expression<T>.

Ve Scale se použije například (ve Scale bude asi hodně možností, jak dosáhnout téhož) trik analogický tomu s CanBuildFrom - tj. násobení bude mít implicitní parametr BuildResult[T] a vracet typ T. Takto definované násobení pak může kdokoliv (i cizí kód) rozšířit na libovolný návratový typ, případně předefinovat jeho chování pro určité návratové typy. S AST lze ve Scale pracovat pomocí maker.

Benchmark by asi dopadl pro C# v tomto případě špatně.

Nevidím důvod, proč by to implementace C# nemohla zoptimalizovat stejně jako Swift. Nevím, jestli to RyuJIT od MS dokáže, nicméně MSIL lze přeložit i do LLVM (Mono, SharpLang, LLILC - zatím značně nekompletní) nebo do C (C# Native).
Pokud instanci MultiplicationResult v C# použiju víckrát, tak tam moc prostoru k optimalizaci není.


Zoptimalizuje se to tak, že MultiplicationResult se nebude vytvářet vůbec a pro každé použití implicitní konverze se data, jenž původně byla součástí MultiplicationResult, přímo předají kódu z implicitní konverze. Taková optimalizace může být například důsledkem escape analysis.

JS

Re:Násobení matic a automatické přetypování
« Odpověď #64 kdy: 18. 09. 2015, 11:09:33 »
Takže když mám

Kód: [Vybrat]
func f()->SquareMattix { ...; return SquareMatrix(...) }
tak je někde přetypování? Kde přesně? Možná jen přetypováním myslíme každý něco jiného.

Mel bys tu funkci napsat celou, takthle to neni moc jasne. Ta funkce bere dve obecne (obdelnikove) matice a volitelne vraci ctvercovou. Tak ci onak to bude muset uzivatel pretypovat na zaklade toho, ze vysledna matice je ctvercova. Prijde mi, ze to tvoje reseni sice umozni vyjadrit, ze soucin dvou ctvercovych matic je ctvercova matice, ale ze soucin dvou obdelnikovych muze byt ctvercova uz ne.