j'ai entendu que les jeux videos de nos jours, sont toujours concu en c
et non en c++,
ma quesiton est POUrquoi??, le c++ a quand meme beaucoup plus d'avantage
que le c non
merci
Ps: ceci n'est pas un troll; je suis en premiere année informatique, et
je commence a apprendre le c++, et les differences du c, et etant
passionné de jeu (c'est la dedans que j'aimerais travailler) je me
posait cette question
... appelle 7 fois le destructeur de Vector, soit deux fois de trop (gcc 3.2).
Oui, mais là le destructeur a un effet de bord, donc le compilo ne peut pas optimiser en virant certains temporaires.
C'est quantique : l'expérience change dès que tu l'observes :)
Chris
Richard Delorme
Richard Delorme writes:
| | > Richard Delorme wrote: | >> Bien sûr un programme C compatible C++ fonctionne à la même vitesse | >> que le compilateur soit en mode C ou C++. Néanmoins les approches | >> offertes par le C++, comme la programmation objet, générique,... | >> peuvent conduire à un programme légèrement plus lent, | > | > Heuh... En quoi la généricité rendrait-elle plus lent ? | | Parce qu'elle prend en compte tous les cas de figure,
dans ce cas ce n'est pas de généricité : c'est de la masturbation intellectuelle.
La généricité, c'est écrire du code général *pour un ensemble de critères données*. En particulier, lorsqu'on spécialise on doit retrouver au moins la même performance que si on avait écrit le code directement.
[...]
Je ne dit pas le contraire, mais la spécialisation n'est qu'une méthode, peut-être élégante, de réécrire le code. Et comme je l'ai indiqué dans le message précédent : « La présence d'un algorithme tout-cuit dans la STL va naturellement conduire à son utilisation et non à rechercher quelquechose de plus performant. »
| Sous Qt (version 3.1.2) l'épaisse surcouche ressemble à :
cela en dit long sur la couche Qt, mais c'est à peu près tout.
J'ai peur que cet exemple soit assez représentatif. La surcouche WxWindow, pour citer une alternative à Qt, pour la fonction équivalente qui est wxWindowDC::DoDrawRectangle(), est à peu près de même taille.
-- Richard
Richard Delorme <abulmo@nospam.fr> writes:
|
| > Richard Delorme wrote:
| >> Bien sûr un programme C compatible C++ fonctionne à la même vitesse
| >> que le compilateur soit en mode C ou C++. Néanmoins les approches
| >> offertes par le C++, comme la programmation objet, générique,...
| >> peuvent conduire à un programme légèrement plus lent,
| >
| > Heuh... En quoi la généricité rendrait-elle plus lent ?
|
| Parce qu'elle prend en compte tous les cas de figure,
dans ce cas ce n'est pas de généricité : c'est de la masturbation
intellectuelle.
La généricité, c'est écrire du code général *pour un ensemble de
critères données*. En particulier, lorsqu'on spécialise on doit
retrouver au moins la même performance que si on avait écrit le code
directement.
[...]
Je ne dit pas le contraire, mais la spécialisation n'est qu'une méthode,
peut-être élégante, de réécrire le code. Et comme je l'ai indiqué dans le
message précédent : « La présence d'un algorithme tout-cuit dans la STL va
naturellement conduire à son utilisation et non à rechercher quelquechose
de plus performant. »
| Sous Qt (version 3.1.2) l'épaisse surcouche ressemble à :
cela en dit long sur la couche Qt, mais c'est à peu près tout.
J'ai peur que cet exemple soit assez représentatif. La surcouche WxWindow,
pour citer une alternative à Qt, pour la fonction équivalente qui est
wxWindowDC::DoDrawRectangle(), est à peu près de même taille.
| | > Richard Delorme wrote: | >> Bien sûr un programme C compatible C++ fonctionne à la même vitesse | >> que le compilateur soit en mode C ou C++. Néanmoins les approches | >> offertes par le C++, comme la programmation objet, générique,... | >> peuvent conduire à un programme légèrement plus lent, | > | > Heuh... En quoi la généricité rendrait-elle plus lent ? | | Parce qu'elle prend en compte tous les cas de figure,
dans ce cas ce n'est pas de généricité : c'est de la masturbation intellectuelle.
La généricité, c'est écrire du code général *pour un ensemble de critères données*. En particulier, lorsqu'on spécialise on doit retrouver au moins la même performance que si on avait écrit le code directement.
[...]
Je ne dit pas le contraire, mais la spécialisation n'est qu'une méthode, peut-être élégante, de réécrire le code. Et comme je l'ai indiqué dans le message précédent : « La présence d'un algorithme tout-cuit dans la STL va naturellement conduire à son utilisation et non à rechercher quelquechose de plus performant. »
| Sous Qt (version 3.1.2) l'épaisse surcouche ressemble à :
cela en dit long sur la couche Qt, mais c'est à peu près tout.
J'ai peur que cet exemple soit assez représentatif. La surcouche WxWindow, pour citer une alternative à Qt, pour la fonction équivalente qui est wxWindowDC::DoDrawRectangle(), est à peu près de même taille.
-- Richard
Loïc Joly
Cyrille Karmann wrote:
Par exemple, quelqu'un qui veut faire un moteur 3D fera peut-être une classe Vector pour représenter les vecteurs. Intuitivement, il fera quelque chose comme ceci pour les opérations mathématiques:
2 avantages : - Je n'ai pas à écrire cette classe - Cette classe élimine certains temporaires grace à de la magie noire à base de teplates et peut conduire à du code bien plus rapide (et aussi à du plus lent, suivant le type qui est mis dans le tableau. Sur mes bench, un tinyvec<std::complex, ...> était moins performant que la version naïve ci-dessus. Et selon les compilos, le facteur de gain allait de 2 à 10 par rapport à ce même code, et était parfois plus rapide que la solution qui passe des références plutôt que de retourner des valeurs).
-- Loïc
Cyrille Karmann wrote:
Par exemple, quelqu'un qui veut faire un moteur 3D fera peut-être une
classe Vector pour représenter les vecteurs. Intuitivement, il fera
quelque chose comme ceci pour les opérations mathématiques:
2 avantages :
- Je n'ai pas à écrire cette classe
- Cette classe élimine certains temporaires grace à de la magie noire à
base de teplates et peut conduire à du code bien plus rapide (et aussi à
du plus lent, suivant le type qui est mis dans le tableau. Sur mes
bench, un tinyvec<std::complex, ...> était moins performant que la
version naïve ci-dessus. Et selon les compilos, le facteur de gain
allait de 2 à 10 par rapport à ce même code, et était parfois plus
rapide que la solution qui passe des références plutôt que de retourner
des valeurs).
Par exemple, quelqu'un qui veut faire un moteur 3D fera peut-être une classe Vector pour représenter les vecteurs. Intuitivement, il fera quelque chose comme ceci pour les opérations mathématiques:
2 avantages : - Je n'ai pas à écrire cette classe - Cette classe élimine certains temporaires grace à de la magie noire à base de teplates et peut conduire à du code bien plus rapide (et aussi à du plus lent, suivant le type qui est mis dans le tableau. Sur mes bench, un tinyvec<std::complex, ...> était moins performant que la version naïve ci-dessus. Et selon les compilos, le facteur de gain allait de 2 à 10 par rapport à ce même code, et était parfois plus rapide que la solution qui passe des références plutôt que de retourner des valeurs).
-- Loïc
Richard Delorme
"Richard Delorme" a écrit dans le message news: 3f819e98$0$24668$
Parce qu'elle prend en compte tous les cas de figure, tandis que, le plus souvent, on n'a que des cas particuliers à traiter.
C'est sûr que le but de template, c'est d'éviter la situation "que des cas particuliers à traiter". Il me semble que les bons auteurs insistent sur la possibilité de spécialiser un template lorsqu'il y a de bonnes raisons. En revanche, pour une classe de la STL, j'avoue ne l'avoir jamais fait, et je ne sais si c'est toujours faisable ou même permis.
Si tu ne l'as jamais fait, cela prouve que c'est une pratique peu courante. Si le C++ permet de faire du code aussi efficace que le C, je crois, qu'en pratique, on ne prend pas la peine de le faire.
Un des problèmes de l'objet, c'est qu'il y a des appels de fonction
implicite, fait à l'insu du plein gré du programmeur (constructeur, destructeur, ...), en particulier lorsque des objets temporaires sont créés.
Là je ne comprends pas : le constructeur alloue - ce que C doit faire (*) aussi ! Ensuite, il fait ce qu'on a écrit, et dans le cas d'un constructeur vide de code utilisateur, je serais étonné qu'un bon compilateur génère du superflu. Enfin, si tu codes quelque chose à bon escient dans le constructeur, c'est que, d'une façon ou d'une autre, tu le coderas aussi en C !
Je me suis mal expliqué alors. Je me plaçais du point de vue de
MaClasse A;
Le constructeur/destructeur sont appelés de manière implicite, sans que l'on écrive un appel de fonction. Tandis qu'en C, pour
MaStruct B;
rien ne se passe, et il faut des appels de fonctions explicites :
Comme on ne voit pas les appels au constructeurs/destructeurs, on a tendance à en minimiser l'impact. Voir l'exemple de l'opérateur addition dans ce message plus bas dans ce fil :
-- Richard
"Richard Delorme" <abulmo@nospam.fr> a écrit dans le message news:
3f819e98$0$24668$7a628cd7@news.club-internet.fr...
Parce qu'elle prend en compte tous les cas de figure, tandis que, le plus
souvent, on n'a que des cas particuliers à traiter.
C'est sûr que le but de template, c'est d'éviter la situation
"que des cas particuliers à traiter".
Il me semble que les bons auteurs insistent sur la possibilité
de spécialiser un template lorsqu'il y a de bonnes raisons.
En revanche, pour une classe de la STL, j'avoue ne l'avoir
jamais fait, et je ne sais si c'est toujours faisable ou même
permis.
Si tu ne l'as jamais fait, cela prouve que c'est une pratique peu courante.
Si le C++ permet de faire du code aussi efficace que le C, je crois, qu'en
pratique, on ne prend pas la peine de le faire.
Un des problèmes de l'objet, c'est qu'il y a des appels de fonction
implicite, fait à l'insu du plein gré du programmeur (constructeur,
destructeur, ...), en particulier lorsque des objets temporaires sont
créés.
Là je ne comprends pas : le constructeur alloue - ce que C doit
faire (*) aussi ! Ensuite, il fait ce qu'on a écrit, et dans le cas d'un
constructeur vide de code utilisateur, je serais étonné qu'un bon
compilateur génère du superflu. Enfin, si tu codes quelque chose
à bon escient dans le constructeur, c'est que, d'une façon ou d'une
autre, tu le coderas aussi en C !
Je me suis mal expliqué alors. Je me plaçais du point de vue de
MaClasse A;
Le constructeur/destructeur sont appelés de manière implicite, sans que l'on
écrive un appel de fonction. Tandis qu'en C, pour
MaStruct B;
rien ne se passe, et il faut des appels de fonctions explicites :
Comme on ne voit pas les appels au constructeurs/destructeurs, on a tendance
à en minimiser l'impact. Voir l'exemple de l'opérateur addition dans ce
message plus bas dans ce fil : <GFr.19ebb398c96ef31c989965@news.free.fr>
"Richard Delorme" a écrit dans le message news: 3f819e98$0$24668$
Parce qu'elle prend en compte tous les cas de figure, tandis que, le plus souvent, on n'a que des cas particuliers à traiter.
C'est sûr que le but de template, c'est d'éviter la situation "que des cas particuliers à traiter". Il me semble que les bons auteurs insistent sur la possibilité de spécialiser un template lorsqu'il y a de bonnes raisons. En revanche, pour une classe de la STL, j'avoue ne l'avoir jamais fait, et je ne sais si c'est toujours faisable ou même permis.
Si tu ne l'as jamais fait, cela prouve que c'est une pratique peu courante. Si le C++ permet de faire du code aussi efficace que le C, je crois, qu'en pratique, on ne prend pas la peine de le faire.
Un des problèmes de l'objet, c'est qu'il y a des appels de fonction
implicite, fait à l'insu du plein gré du programmeur (constructeur, destructeur, ...), en particulier lorsque des objets temporaires sont créés.
Là je ne comprends pas : le constructeur alloue - ce que C doit faire (*) aussi ! Ensuite, il fait ce qu'on a écrit, et dans le cas d'un constructeur vide de code utilisateur, je serais étonné qu'un bon compilateur génère du superflu. Enfin, si tu codes quelque chose à bon escient dans le constructeur, c'est que, d'une façon ou d'une autre, tu le coderas aussi en C !
Je me suis mal expliqué alors. Je me plaçais du point de vue de
MaClasse A;
Le constructeur/destructeur sont appelés de manière implicite, sans que l'on écrive un appel de fonction. Tandis qu'en C, pour
MaStruct B;
rien ne se passe, et il faut des appels de fonctions explicites :
Comme on ne voit pas les appels au constructeurs/destructeurs, on a tendance à en minimiser l'impact. Voir l'exemple de l'opérateur addition dans ce message plus bas dans ce fil :
-- Richard
Alain Naigeon
"Fabien LE LEZ" a écrit dans le message news:
On Mon, 6 Oct 2003 16:59:29 +0200, "Chewee" wrote:
Je travaille moi aussi dans le jeu vidéo et c'est ce que j'ai toujours entendu...
Le C est meilleur que le C++, je le dis depuis 20 ans ;-)
Si tu trolles dans l'espace dual, on ne va plus s'en sortir ;-)
--
Français *==> "Musique renaissance" <==* English midi - facsimiles - ligatures - mensuration http://anaigeon.free.fr | http://www.medieval.org/emfaq/anaigeon/ Alain Naigeon - - Strasbourg, France
"Fabien LE LEZ" <gramster@gramster.com> a écrit dans le message news:
tcl3ovovpot9sfu03l2eekdcl2es1q8o4s@4ax.com...
On Mon, 6 Oct 2003 16:59:29 +0200, "Chewee" <chewee@NOSPAMchewee.net>
wrote:
Je travaille moi aussi dans le jeu vidéo et c'est ce que j'ai toujours
entendu...
Le C est meilleur que le C++, je le dis depuis 20 ans ;-)
Si tu trolles dans l'espace dual, on ne va plus s'en sortir ;-)
--
Français *==> "Musique renaissance" <==* English
midi - facsimiles - ligatures - mensuration
http://anaigeon.free.fr | http://www.medieval.org/emfaq/anaigeon/
Alain Naigeon - anaigeon@free.fr - Strasbourg, France
"Christophe Lephay" a écrit dans le message news: blsoh7$g86$
"Fabien LE LEZ" a écrit dans le message de news:
... appelle 7 fois le destructeur de Vector, soit deux fois de trop (gcc
3.2).
Oui, mais là le destructeur a un effet de bord, donc le compilo ne peut pas optimiser en virant certains temporaires.
C'est quantique : l'expérience change dès que tu l'observes :)
T'ss [HS] : c'est juste l'interprétation courante des équations, rien d'autre.
--
Français *==> "Musique renaissance" <==* English midi - facsimiles - ligatures - mensuration http://anaigeon.free.fr | http://www.medieval.org/emfaq/anaigeon/ Alain Naigeon - - Strasbourg, France
Jonathan Mcdougall
Un des problèmes de l'objet, c'est qu'il y a des appels de fonction
implicite, fait à l'insu du plein gré du programmeur (constructeur, destructeur, ...), en particulier lorsque des objets temporaires sont créés.
Là je ne comprends pas : le constructeur alloue - ce que C doit faire (*) aussi ! Ensuite, il fait ce qu'on a écrit, et dans le cas d'un constructeur vide de code utilisateur, je serais étonné qu'un bon compilateur génère du superflu. Enfin, si tu codes quelque chose à bon escient dans le constructeur, c'est que, d'une façon ou d'une autre, tu le coderas aussi en C !
Je me suis mal expliqué alors. Je me plaçais du point de vue de
MaClasse A;
Le constructeur/destructeur sont appelés de manière implicite, sans que l'on
écrive un appel de fonction. Tandis qu'en C, pour
MaStruct B;
rien ne se passe, et il faut des appels de fonctions explicites :
Comme on ne voit pas les appels au constructeurs/destructeurs, on a tendance
à en minimiser l'impact.
Quel impact?
Jonathan
Un des problèmes de l'objet, c'est qu'il y a des appels de fonction
implicite, fait à l'insu du plein gré du programmeur (constructeur,
destructeur, ...), en particulier lorsque des objets temporaires sont
créés.
Là je ne comprends pas : le constructeur alloue - ce que C doit
faire (*) aussi ! Ensuite, il fait ce qu'on a écrit, et dans le cas d'un
constructeur vide de code utilisateur, je serais étonné qu'un bon
compilateur génère du superflu. Enfin, si tu codes quelque chose
à bon escient dans le constructeur, c'est que, d'une façon ou d'une
autre, tu le coderas aussi en C !
Je me suis mal expliqué alors. Je me plaçais du point de vue de
MaClasse A;
Le constructeur/destructeur sont appelés de manière implicite, sans que
l'on
écrive un appel de fonction. Tandis qu'en C, pour
MaStruct B;
rien ne se passe, et il faut des appels de fonctions explicites :
Un des problèmes de l'objet, c'est qu'il y a des appels de fonction
implicite, fait à l'insu du plein gré du programmeur (constructeur, destructeur, ...), en particulier lorsque des objets temporaires sont créés.
Là je ne comprends pas : le constructeur alloue - ce que C doit faire (*) aussi ! Ensuite, il fait ce qu'on a écrit, et dans le cas d'un constructeur vide de code utilisateur, je serais étonné qu'un bon compilateur génère du superflu. Enfin, si tu codes quelque chose à bon escient dans le constructeur, c'est que, d'une façon ou d'une autre, tu le coderas aussi en C !
Je me suis mal expliqué alors. Je me plaçais du point de vue de
MaClasse A;
Le constructeur/destructeur sont appelés de manière implicite, sans que l'on
écrive un appel de fonction. Tandis qu'en C, pour
MaStruct B;
rien ne se passe, et il faut des appels de fonctions explicites :
Comme on ne voit pas les appels au constructeurs/destructeurs, on a tendance
à en minimiser l'impact.
Quel impact?
Jonathan
Alain Naigeon
"Richard Delorme" a écrit dans le message news: 3f81ed93$0$24670$
Je ne dit pas le contraire, mais la spécialisation n'est qu'une méthode, peut-être élégante, de réécrire le code.
Oui, mais écrire pour tous les cas envisagés sauf celui-ci, ou écrire séparément pour chacun d'eux, c'est pas kif-kif.
Et comme je l'ai indiqué dans le message précédent : « La présence d'un algorithme tout-cuit dans la STL va naturellement conduire à son utilisation et non à rechercher quelquechose de plus performant. »
Regretter qu'un codeur prenne la mauvaise pente n'autorise pas à reporter le défaut sur le langage, qui est conçu pour tous les autres (dans lesquels je ne me compte pas prétentieusement). En l'occurrence, je trouve C++ compliqué (quoique nettement moins insupportable que C), mais la spécialisation template n'est pas franchement un truc obscur, je trouve. Tu as f(X1...Xn), tu fixes un Xp à la valeur X0p, et tu restes avec un template si n était >1 - conceptuellement très simple, et la syntaxe le reflète assez bien, il me semble.
--
Français *==> "Musique renaissance" <==* English midi - facsimiles - ligatures - mensuration http://anaigeon.free.fr | http://www.medieval.org/emfaq/anaigeon/ Alain Naigeon - - Strasbourg, France
"Richard Delorme" <abulmo@nospam.fr> a écrit dans le message news:
3f81ed93$0$24670$7a628cd7@news.club-internet.fr...
Je ne dit pas le contraire, mais la spécialisation n'est qu'une méthode,
peut-être élégante, de réécrire le code.
Oui, mais écrire pour tous les cas envisagés sauf celui-ci,
ou écrire séparément pour chacun d'eux, c'est pas kif-kif.
Et comme je l'ai indiqué dans le
message précédent : « La présence d'un algorithme tout-cuit dans la STL va
naturellement conduire à son utilisation et non à rechercher quelquechose
de plus performant. »
Regretter qu'un codeur prenne la mauvaise pente
n'autorise pas à reporter le défaut sur le langage,
qui est conçu pour tous les autres (dans lesquels
je ne me compte pas prétentieusement).
En l'occurrence, je trouve C++ compliqué (quoique
nettement moins insupportable que C), mais la
spécialisation template n'est pas franchement un
truc obscur, je trouve. Tu as f(X1...Xn), tu fixes un
Xp à la valeur X0p, et tu restes avec un template
si n était >1 - conceptuellement très simple, et la
syntaxe le reflète assez bien, il me semble.
--
Français *==> "Musique renaissance" <==* English
midi - facsimiles - ligatures - mensuration
http://anaigeon.free.fr | http://www.medieval.org/emfaq/anaigeon/
Alain Naigeon - anaigeon@free.fr - Strasbourg, France
"Richard Delorme" a écrit dans le message news: 3f81ed93$0$24670$
Je ne dit pas le contraire, mais la spécialisation n'est qu'une méthode, peut-être élégante, de réécrire le code.
Oui, mais écrire pour tous les cas envisagés sauf celui-ci, ou écrire séparément pour chacun d'eux, c'est pas kif-kif.
Et comme je l'ai indiqué dans le message précédent : « La présence d'un algorithme tout-cuit dans la STL va naturellement conduire à son utilisation et non à rechercher quelquechose de plus performant. »
Regretter qu'un codeur prenne la mauvaise pente n'autorise pas à reporter le défaut sur le langage, qui est conçu pour tous les autres (dans lesquels je ne me compte pas prétentieusement). En l'occurrence, je trouve C++ compliqué (quoique nettement moins insupportable que C), mais la spécialisation template n'est pas franchement un truc obscur, je trouve. Tu as f(X1...Xn), tu fixes un Xp à la valeur X0p, et tu restes avec un template si n était >1 - conceptuellement très simple, et la syntaxe le reflète assez bien, il me semble.
--
Français *==> "Musique renaissance" <==* English midi - facsimiles - ligatures - mensuration http://anaigeon.free.fr | http://www.medieval.org/emfaq/anaigeon/ Alain Naigeon - - Strasbourg, France
Fabien LE LEZ
On Tue, 07 Oct 2003 01:02:23 +0200, Richard Delorme wrote:
Comme on ne voit pas les appels au constructeurs/destructeurs, on a tendance à en minimiser l'impact.
Encore faut-il qu'il y ait un impact. J'ai l'impression que tu prends le problème dans le mauvais sens. Optimiser dès le début me paraît discutable, même pour les jeux. Mieux vaut faire rapidement un programme fiable (ce que permet le C++), ce qui laisse du temps pour tester le programme et repérer, pendant l'exécution, les goulots d'étranglement qu'il faudra effectivement optimiser.
On Tue, 07 Oct 2003 01:02:23 +0200, Richard Delorme <abulmo@nospam.fr>
wrote:
Comme on ne voit pas les appels au constructeurs/destructeurs, on a tendance
à en minimiser l'impact.
Encore faut-il qu'il y ait un impact.
J'ai l'impression que tu prends le problème dans le mauvais sens.
Optimiser dès le début me paraît discutable, même pour les jeux. Mieux
vaut faire rapidement un programme fiable (ce que permet le C++), ce
qui laisse du temps pour tester le programme et repérer, pendant
l'exécution, les goulots d'étranglement qu'il faudra effectivement
optimiser.
On Tue, 07 Oct 2003 01:02:23 +0200, Richard Delorme wrote:
Comme on ne voit pas les appels au constructeurs/destructeurs, on a tendance à en minimiser l'impact.
Encore faut-il qu'il y ait un impact. J'ai l'impression que tu prends le problème dans le mauvais sens. Optimiser dès le début me paraît discutable, même pour les jeux. Mieux vaut faire rapidement un programme fiable (ce que permet le C++), ce qui laisse du temps pour tester le programme et repérer, pendant l'exécution, les goulots d'étranglement qu'il faudra effectivement optimiser.
Si tu ne l'as jamais fait, cela prouve que c'est une pratique peu courante. Si le C++ permet de faire du code aussi efficace que le C, je crois, qu'en pratique, on ne prend pas la peine de le faire.
Ce qui pourrait aussi être un signe qu'on n'en a pas réellement besoin.
Arnaud
Richard Delorme wrote:
Si tu ne l'as jamais fait, cela prouve que c'est une pratique peu courante.
Si le C++ permet de faire du code aussi efficace que le C, je crois, qu'en
pratique, on ne prend pas la peine de le faire.
Ce qui pourrait aussi être un signe qu'on n'en a pas réellement besoin.
Si tu ne l'as jamais fait, cela prouve que c'est une pratique peu courante. Si le C++ permet de faire du code aussi efficace que le C, je crois, qu'en pratique, on ne prend pas la peine de le faire.
Ce qui pourrait aussi être un signe qu'on n'en a pas réellement besoin.