Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.
La shoutbox n'est pas chargée par défaut pour des raisons de performances. Cliquez pour charger.

Forum Casio - Projets de programmation


Index du Forum » Projets de programmation » Bibliothèque standard pour GCC

Bibliothèque standard pour GCC

Posté le 01/06/2014 19:50

Comme vous l'avez peut-être remarqué, LePhenixNoir nous a gratifié d'un tuto accessible afin de mettre en place GCC et donc une nouvelle manière de compiler des add-ins pour nos Casios.

Afin d'ouvrir le développement au libre, une bibliothèque C standard à vu le jour et avance petit à petit.
Un dépôt git est disponible ici.
L'objectif est, au final, d'avoir une bibliothèque dont on connaisse le contenu, qui soit maintenable et qui remplisse le rôle d'une librairie C standard à l'échelle de nos calculatrices, compatible SH4 et SH3, enfin un truc bien quoi !

Le code étant écrit par des membres de PC, depuis rien, le choix de la licence est ouvert, de mon côté, comme pour LePhenixNoir, placer celui-ci dans le domaine publique paraît intéressant, reste à voir avec les autres (notamment Dark Storm pour le moment ).
Message initial
Cliquer pour enrouler
Seulement, si le support de l'architecture SuperH est relativment "natif" pour GCC, le support des librairies et des parties spécifique aux calculatrices Casio l'est beaucoup moins. Ainsi, si il est possible de récupérer les fonctions correspondants à "fxlib.h" dans un format utilisable par GCC, la librairie C standard fournie par casio dans le SDK ne semble pas aussi simple à récupérer (voire irrécupérable ? ).

Le plus simple est je pense de "réecrire" une bibliothèque standard C.
A mon avis, il pourrait aussi être intéressant d'essayer de s'affranchir de la bibliothèque "fxlib" fournie par Casio, toujours en la réecrivant (c'est à dire simplement refaire les appels de Syscalls pour la plupart des fonctions, "fxlib" étant majoritairement basée sur les Syscalls), mais en travaillant sur certains points et avoir d'emblée une compatibilité SH4 par exemple. On "enlèverait" aussi la plupart du code propriétaire de Casio (bien qu'il reste les syscalls, mais bon... ).
Ce qui concerne "fxlib" n'est que mon point de vue étant donné qu'on peut très bien conserver le fichier de Casio, j'amorce juste une réflexion à ce niveau là ;).

Quoi qu'il en soit, ce topic est là pour permettre de réfléchir sur le projet ,c'est à dire la réimplémentation d'une bibliothèque C à peu près standard (en s'appuyant sur les syscalls déjà existants, va faloir sortir la doc ) pour fonctionner sur GCC de manière correcte, voire plus intéressante que sur le SDK de Casio (pourquoi pas implémenter des fopen(...) par exemple, là encore, simple suggestion à cogiter ).
C'est aussi pour voir si il y a des gens qui seraient intéressés pour travailler là dessus, et voir vos idées sur la manière de travailler dessus.

Je pense qu'à la longue, un dépot git (ou autre) sur gitorious ou quelque chose du même style pourrait servir, qu'en dites vous ? Enfin, le projet semble intéressant, d'autant plus qu'un GCC bien fonctionnel pour compiler des add-ins, ça serait cool ! :D.
Donc n'hésitez pas à mettre vos idées pour commencer et avancer !
[/spoiler]


Précédente 1, 2, 3, 4, 5, 6, 7, 8 Suivante
Lephenixnoir Hors ligne Administrateur Points: 24145 Défis: 170 Message

Citer : Posté le 28/10/2014 15:19 | # | Fichier joint


M'étant lancé dans la réécriture complète des fonctions de la famille de printf() -- la version précédente je le rappelle, ne gérait pas toutes les notations, et pas le moindre flag ni précision --, je dois avouer que c'est plus compliqué de gérer tous ces flags et ces histoires de précision que je ne l'avais pensé !

J'ai quand même mis au point l'analyse de format (notez que je détecte toujours un format dès que je vois un '%', ce qui n'est pas le cas normalement, mais je ne me suis pas embarrassé du format... des formats), et l'écriture des valeurs de type %d et %i. Toutes les options sont gérées, exception faite de celles mentionnées dans le fichier.
Je devrais pouvoir faire %o, %u, %x et %X assez facilement, par contre je garantis rien pour tout ce qui est flottants. :3

J'ai testé sur mon ordinateur et je n'ai pas trouvé de cas dans lequel le résultat ne soit pas identique à celui du printf() de mon système, y compris lorsque la taille de la chaîne dans laquelle écrire est limitée.
Quelqu'un pourrait tester pour confirmer mes dires ? Je joins le fichier.
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)

Citer : Posté le 28/10/2014 21:39 | #


Je teste ceci le plus rapidement possible, ça à l'air d'être du gros boulot !

Le code compilé n'est pas trop lourd ? Enfin, je te fais un feed-back asap ;).
Lephenixnoir Hors ligne Administrateur Points: 24145 Défis: 170 Message

Citer : Posté le 28/10/2014 21:42 | #


Enfin, là je ne gère que les entiers décimaux, sur plus de 200 lignes de code. ^^' Pourtant c'est simple, sauf pour l'insertion des espaces qui se fait avant le signe si l'option '0' est désactivée, après le signe si elle l'est, et après les chiffres si l'option '-' est activée. Du coup j'ai la même boucle 3 fois. >_<

Sinon, le code compilé risque d'être lourd, si.
Enfin, ça a au moins l'avantage d'occulter la mémoire utilisée par le buffer global généralisé. :3

Ajouté le 29/10/2014 à 21:14 :
Qui aurait cru que pour 0 la fonction n'affichait rien ?
Comme quoi, rien ne vaut la pratique vu qu'à deux en faisant des tests exprès, on n'avait pas trouvé quelque chose d'aussi trivial.
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)
Dark storm En ligne Labélisateur Points: 11631 Défis: 176 Message

Citer : Posté le 29/10/2014 21:25 | #


Lephenixnoir a écrit :
Enfin, là je ne gère que les entiers décimaux

System error!

Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Lephenixnoir Hors ligne Administrateur Points: 24145 Défis: 170 Message

Citer : Posté le 29/10/2014 21:45 | #


entier décimal désigne entier écrit sous forme décimale, soit les formats d et i, implicitement signés donc.
Le tout en opposition aux formats, o, u, x et X qui sont traités dans une autre sous-routine.
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)
Dark storm En ligne Labélisateur Points: 11631 Défis: 176 Message

Citer : Posté le 29/10/2014 21:48 | #


Soit. Merci pour l'explication
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Lephenixnoir Hors ligne Administrateur Points: 24145 Défis: 170 Message

Citer : Posté le 01/11/2014 08:38 | #


En continuant à parcourir la liste des trucs à implémenter, je suis retombé sur des fonctions comme system() et getenv(). Dans notre cas particulier, l'implémentation est discutable.

→ Dans le cas de system() qui fait normalement appel au terminal attaché au processus, rien ne nous empêche de simuler son fonctionnement. Mais ce serait moche et je ne suis pas sûr qu'on ait vraiment besoin d'un shell POSIX dans nos applications. Je pense qu'il ne faut pas l'implémenter.

→ En revanche, getenv(), je pense plutôt que c'est une bonne idée, mais seulement si on a vraiment des données en variables d'environnement. Ça permettrait par ailleurs de faire des appels simplifiés entre les programmes.

De plus, pour l'implémentation de la locale, je vous propose :
char *decimal_point : Séparateur décimal.
char *thousands_sep : Séparateur de milliers.
char *grouping : Définition des séparations de milliers; Par exemple, "\2\3\1\1\c" (où '\c'=CHAR_MAX) peut donner 4463'7'4'638'43.
char *int_curr_symbol : Symbole de monnaie international, comme "USD".
char *currency_symbol : Symbole de monnaie, comme "$".

Il y a encore plein de trucs mais c'est pour le formatage de la monnaie, personne s'en sert et même si ça arrivait dans un jeu (ce qui rendrait d'ailleurs le code plus lisible), ce qu'on a là suffit largement.

Ah oui, et on virerait aussi l'influence de la locale sur les fonctions de ctype : isgraph(), tolower(), etc...

Ça vous convient ?

Ajouté le 13/11/2014 à 19:24 :
Je suis tombé sur une personne sur Stack Overflow qui dit, je cite : "I think that it's safe to say that C locales are universally recognized as a bad idea."

Du coup je me demande si c'est vraiment intelligent de les implémenter. Elles compliquent pas mal de fonctions, en ajoutent d'autres, et ne semblent pas apporter grand chose vu que personne ne les utilise.


Ajouté le 05/12/2014 à 20:03 :
Au fait, j'ai oublié de le dire mais j'ai trouvé un moyen de calculer cosinus, sinus et donc tangente sans table, en garantissant une erreur inférieure à 1e-8, c'est-à-dire que s'il n'y a pas de retenue impactée l'erreur ne se situe pas avant la huitième décimale !
Je propose qu'on fixe le plancher d'erreur à 1e-6, autrement dit 6 décimales exactes.
Je suis en train de chercher exponentielle et logarithme népérien, avec ces deux-là on pourra calculer pas mal de choses. En plus de la trigo ça nous donne :

→ trigonométrie, O(1) ;
→ trigonométrie inverse par dichotomie, O(ln n) ;
→ racines n-ième (n de R), O(1) ;
→ logarithmes en bases quelconques, O(1) ;
→ exposants, O(1) ;
→ trigonométrie hyperbolique, O(1) ;
→ trigonométrie hyperbolique inverse par dichotomie, O(ln n).

Si on arrive à implémenter tout ça on aura fait la majorité !
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)

Citer : Posté le 07/12/2014 18:21 | #


Super ! J'avoue être assez curieux de la méthode utilisée.

Sinon, si tu as le temps tu pourras publier (sur une nouvelle branche du repo, la branche principale si tu juges que c'est envisageable, ou même ailleurs si tu veux ) ce que tu avais bien avancé (notamment sur stdio) et aussi les fichiers récapitulant où ça en est, ce qu'il reste à faire... Car pour l'instant, on ne peut pas trop avancer (ou alors ça va un peu "tomber dans le vide") vu que tu as restructuré tout ce qui touche à la structure du projet en plus de ce que tu as avancé entre temps niveau code. Enfin, c'est toi qui vois bien sûr.

Mais sinon beau boulot, c'est cool que tu prenne du temps pour ça ! (Ce qui n'est pas tellement mon cas en fait je me rend compte :sry:...)
Lephenixnoir Hors ligne Administrateur Points: 24145 Défis: 170 Message

Citer : Posté le 07/12/2014 18:46 | #


La méthode utilisée ?
Très simple, c'est une approximation polynomiale par un développement en série.

sin(x) = x - x^3/3! + x^5/5! - x^7/7! + x^9/9!
et avec ça t'as déjà beaucoup plus de 6 décimales pour les angles proches de zéro.

L'avantage c'est que c'est bon pour le calcul direct, cos(x) facile à définir, bref, le tour est joué.
Au passage avec sinus et cosinus on peut aussi faire des exponentielles complexes !
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)

Citer : Posté le 07/12/2014 18:53 | #


D'accord je vois ^^. Effectivement du coup ça reste relativement aisé à implémenter, avec ce qui en découle !

Du coup pour l'exponentielle notamment, c'est le même "principe" je suppose que :
exp(x) = 1 + x + x^2/2! + x^3/3! + x^4/4! + ... (je ne sais pas "jusqu'où" aller pour avoir une précision intéressante)

peut être assez "rentable" aussi, à moins que tu aies eu en tête une autre approche.


Lephenixnoir Hors ligne Administrateur Points: 24145 Défis: 170 Message

Citer : Posté le 07/12/2014 19:09 | #


On a aussi la définition suivante :
e^x = lim(x→+∞)(1+1/x)^x

mais je pense que ça va moins vite.

Pour le sinus de 5 degrés par exemple, avec trois termes (dont x), tu as déjà 8 décimales !
Après sur 45 degrés, il faut monter à 5 termes pour une précision similaire.

À 90, c'est encore pire mais ça doit pouvoir se calculer. Avec une méthode sur [0;π/2] ça passe, et je crois que ça se fait aussi sur [0;π/4]... à voir.

Pour ln(x), c'est tout aussi facile :
ln(x) = x - x^2/2 + x^3/3 - x^4/4 + x^5/5 + ...

Après j'ai aussi un programme qui donne des approximations polynomiales qui me permettent d'assurer au moins 6 décimales sur un polynôme de degré 7, qui s'éloigne plus lentement quand les valeurs augmentent.

Ajouté le 22/02/2015 à 15:20 :
Bon, et ben on dirait que finalement on n'aurai pas grand-chose à coder...

Liste non exhaustive des fonctions théoriquement existantes en builtin avec gcc :
→ Trigonométrie et réciproque, hyperbolique ;
→ vsnprintf() donc toute la famille associée ;
→ vsscanf() donc toute la famille associée ;
→ Plus de logarithmes qu'on ne peut en imaginer, les exponentielles, les gamma et j'en passe ;
→ La quasi-totalité des fonctions d'entrée/sortie (à voir si on ne devra pas implémenter les bases) ;
→ exit(), abort() et gettext() au passage ;
→ Toutes les foncitons de ctype, de string et même plus.

Bref, vous aurez compris que si tout existe pour notre target précise ça va couler carrément tout seul.
Ce qui sera le plus intéressant sera je pense d'implémenter la partie spécifique à la calculatrice.

Faudra voir mais si le code builtin de gcc est moins optimisé que le notre autant utiliser le notre.
Il nous faudra une application pour tester la vitesse des fonctions.
Au passage, vous vous souvenez que les fonctions de l'OS étaient plus rapides que celles des programmes utilisateur en toutes circonstances ? Je crois que j'ai trouvé un moyen de régler ce problème.

Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)
-florian66- Hors ligne Ancien rédacteur Points: 2383 Défis: 20 Message

Citer : Posté le 22/02/2015 17:17 | #


Il existe math.lua de vebveb qui code toute les fonctions trigo Il faudrait donc essayé de transposer en C
In Arch, I trust ! And you ?
Lephenixnoir Hors ligne Administrateur Points: 24145 Défis: 170 Message

Citer : Posté le 22/02/2015 17:26 | #


-florian66- a écrit :
Il existe math.lua de vebveb qui code toute les fonctions trigo Il faudrait donc essayé de transposer en C

Mais non, pourquoi est-ce qu'on irait chercher au plus haut niveau ? >_<
Soit le Lua utilise la fonction de fxlib, soit il la définit lui-même, mais dans un cas comme d'en l'autre on a à la fois les fonctions builtins de gcc, les approximations polynomiales, les développements limités dont les séries de mac laurin, on n'a plus besoin de chercher comment l'implémenter
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)
Kristaba Hors ligne Membre Points: 614 Défis: 22 Message

Citer : Posté le 23/02/2015 00:34 | #


Bon, je veux pas casser l'ambiance, mais les builtin GCC ne vont pas faire le boulot à la place de la lib C, les gars.

J'imagine que tu te réfères à cette page de la doc de GCC par exemple, mais il n'est précisé nul part que ces builtins sont les implémentations complètes des fonctions!
C'est simplement des pseudo-fonctions qui peuvent être optimisées à la compilation pour simplifier les choses dans certaines situations (par exemple, remplacer 'printf("Hello\n");' par 'puts("Hello\n");', par ce que printf sans autre paramètres que le format est équivalent à puts).

Enfin, y'a probalement quelques builtins qui sont remplacée uniquement par du code machine, sur sh3, dans toutes les situations, mais ce n'est qu'une toute petite partie des fonctions qui sont indiquées... Dans tous les cas, aucune fonction très complexe n'est substituée par un builtin, ce n'est simplement pas approprié (le compilateur ne s'amuse pas à générer à la volée le code qui permet de faire des racines carrées, à moins qu'il y ait un FPU qui le fasse en 3 instructions sur votre architecture).
Il était vraiment temps que je change cette signature...
Lephenixnoir Hors ligne Administrateur Points: 24145 Défis: 170 Message

Citer : Posté le 23/02/2015 06:18 | #


Kristaba a écrit :
Bon, je veux pas casser l'ambiance, mais les builtin GCC ne vont pas faire le boulot à la place de la lib C, les gars.

Bien au contraire, bien au contraire...

Kristaba a écrit :
J'imagine que tu te réfères à cette page de la doc de GCC par exemple, mais il n'est précisé nul part que ces builtins sont les implémentations complètes des fonctions!
C'est simplement des pseudo-fonctions qui peuvent être optimisées à la compilation pour simplifier les choses dans certaines situations (par exemple, remplacer 'printf("Hello\n");' par 'puts("Hello\n");', par ce que printf sans autre paramètres que le format est équivalent à puts).

Oui mais ça veut dire que l'implémentation de puts() est complète, sinon il ne pourrait pas l'utiliser... non ?

Kristaba a écrit :
Enfin, y'a probalement quelques builtins qui sont remplacée uniquement par du code machine, sur sh3, dans toutes les situations, mais ce n'est qu'une toute petite partie des fonctions qui sont indiquées...

Oui, alors je me doutais que pour notre cible précise on n'aura qu'une partie des fonctions indiquées. Enfin, il me semblait que les fonctions presque tout à fait indépendants de l'architecture (math, string) pourraient exister.

Kristaba a écrit :
Dans tous les cas, aucune fonction très complexe n'est substituée par un builtin, ce n'est simplement pas approprié

Alors pourquoi ces fonction existent-elles ?

Kristaba a écrit :
(le compilateur ne s'amuse pas à générer à la volée le code qui permet de faire des racines carrées, à moins qu'il y ait un FPU qui le fasse en 3 instructions sur votre architecture).

Il y a un FPU et il le fait en 13 instructions, mais pendant ce temps-là le CPU continue de tourner.
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)
Kristaba Hors ligne Membre Points: 614 Défis: 22 Message

Citer : Posté le 23/02/2015 13:00 | #


Ecoute, je te propose quelques pistes pour que l'on soit d'accord.
1) Fait donc un test, essaie de compiler, avec "gcc -nostdlib main.c -lgcc" les exemples que tu veux, tu vas bien voir que seul quelques builtins sont toujours implémentés par des instructions, le reste du temps tu auras quelques problèmes d'édition des liens (et encore je te propose avec libgcc, qui supporte pas mal de choses au niveau des opérations sur les chaines, mais c'est déjà plus tout à fait des 'builtins').

2) Cherche dans les sources de GCC où sont implémentés tes builtins : builtins.c
Y'a bien du code arch-specific un peu partout, mais globalement c'est juste des optimisations de l'AST en cas d'opérations superflues, si y'a de la vraie complexité algorithmique c'est remplacé par l'émission d'un appel à une routine de la libc.

3) Demande-toi pourquoi les mecs qui maintiennent la glibc, par exemple, se font chier à "réimplémenter" tout ce qui semble être implémenté en tant que builtin dans GCC. Oui, ça pourrait être pour le fun, ou pour supporter des compilos qui ne sont pas très efficaces. Ou alors c'est par ce que les builtins sont souvent remplacés par l'émission d'appels aux fonctions qui doivent bien être implémentées quelque part?

Lephenixnoir a écrit :
Oui mais ça veut dire que l'implémentation de puts() est complète, sinon il ne pourrait pas l'utiliser... non ?

Non, ça veut dire qu'il émet un appel à un symbole externe nommé '_puts'. Si ton symbole existe pas, c'est que tu n'est pas dans un environnement ISO C, donc que soit tu aurais dû donner l'option -ffreestanding (qui implique -fno-builtin), soit que tu as oublié de linker ta lib ISO C.
Autrement dit, GCC fait des optimisations qui sont valides seulement si tu es en ISO C (puisqu'il infère sur le sens de ton code à partir de cette norme), mais c'est pas pour ça qu'il implémente la norme.

Lephenixnoir a écrit :
Alors pourquoi ces fonction existent-elles ?

Déjà c'est pas tout à fait des fonctions, ce n'a pas du tout la même sémantique pour le compilateur. Ce sont des sortes de hooks qui donnent une chance à GCC d'analyser et parfois d'optimiser du code.
Et cette optimisation potentielle dépend de la fonction que le builtin remplace, de ce que le compilo sait à la compilation au moment où il analyse ce builtin, de ce que dit la norme que tu as dit à GCC de suivre (gnu99 si tu ne dis rien), et finalement de ton architecture...
Bref, c'est pas que ce soit pas ultra-puissant, mais faut se dire que c'est plus de la magie noire de GCC qu'une implémentation de toutes les fonctions correspondantes. Je ne dit pas que tu ne dois pas les utiliser pour votre libc, mais en théorie c'est exactement l'inverse : ta libc contient toute la norme C, et GCC, si il se sent capable pour une raison ou pour une autre, d'optimiser un appel à une fonction de ta lib, va le faire (soit en appelant d'autres fonctions de ta lib, soit en émettant directement des instructions pour ton proco).
Il était vraiment temps que je change cette signature...
Lephenixnoir Hors ligne Administrateur Points: 24145 Défis: 170 Message

Citer : Posté le 23/02/2015 21:56 | #


Ah, ben merci pour les explications hein.

Bon en soi y'a rien dont qu'on ne puisse vraiment pas implémenter mais c'est vrai que ç'aurait été pratiques si on avait eu quelques fonctions précompilées. Enfin, on peut tout à fait se débrouiller sans, de toute façon j'aurai tout essayé une fois ou l'autre pour essayer d'optimiser.

Au fait, je voulais savoir : le code standard est chargé à 0x00300000, donc en P0. Y a-t-il des limites à pouvoir le déplacer en P1 par exemple, comme les exceptions handlers ?

Ajouté le 20/04/2015 à 22:25 :
Bon, je me suis replongé dans l'affaire un bon coup. J'ai clarifié, synthétisé et repris ce qu'il fallait implémenter. J'ai aussi récupéré la liste des code d'errno de mon système et je l'ai simplifié au maximum pour notre cas, jusqu'à obtenir une trentaine de code au lieu de plus de cent vingt initialement.

Par contre j'ai un gros problème avec les implémentations de exp() et log(). Il m'était naturellement venu à l'idée d'utiliser les séries de mac laurin (développement limité autour de 0), mais ça va très vite perdre en précision sur ces fonctions. En cherchant un peu, j'ai pu trouver quelque chose concernant exp() :
Eric Postpischil (stack overflow) a écrit :
Implementing the exp() function is complicated [...]. An implementation typically involves:

- Testing the input for various special cases, such as NaNs.
- Multiplying the input by a specially prepared representation of log2(e), to transform the problem from e^x to 2^y, where y = x * log2e.
- Moving the integer part of y into the exponent field of a floating-point encoding.
- Evaluating the exponential of the fractional part of y with a minimax polynomial.
- Combining the two results above.

L'astuce est carrément bien trouvée, puisqu'en effet pour avoir 2^y il suffit d'écrire y dans le champ exposant de la variable. Comme tout est détaillé dans la doc du FPU, y'a pas de problème.

Pour la partie fractionnaire, je ne connais pas du tout la méthode utilisée et encore une fois, impossible d'utiliser une approximation polynomiale (vous voyez tous la tête que ça a). Encore que, je ne suis pas sûr que la solution proposée n'en soit pas une. >_<

Pour le calcul de log(), faut que je voie si on peut pas faire un truc semblable. Ceci dit, ça aide déjà pas mal !

Ajouté le 21/04/2015 à 09:45 :
J'ai trouvé comment réaliser le calcul de ln() !
Je vous mets vite fait la démonstration, ça ira plus vite.

∀ x ∈ [1;+∞[, ∃ k ∈ N* tq b = x*2^-k ∈ ]1;2]
soit ln(x) = k*ln(2) + ln(b)

∀ x ∈ ]0;1], ∃ k ∈ N* tq b = x*2^k ∈ [2^-n;1[
soit ln(x) = ln(b) - k*ln(2)

Le ln(2) est immédiat et sur les intervalles restants on peut faire des approximations polynomiales.

On peut faire varier n pour augmenter la précision de l'approximation polynomiale utilisée. Au passage j'ai pris le facteur 2 mais on peut utiliser n'importe quel autre, la valeur sera pré-calculée et plus elle sera grande et plus le calcul sera rapide !

On peut aussi faire varier la borne supérieure pour le premier cas, après c'est à voir !

Edit : du coup on a une complexité en O(log(n)) pour le calcul de k, si on peut l'obtenir immédiatement ça nous fera O(1)

Ajouté le 21/04/2015 à 14:06 :
Yosh, j'ai trouvé comment implémenter exit() ! C'est pas sorcier mais j'étais un peu inquiet finalement.

Il suffit de sauter à un morceau de code dans crt0.s qui arrête le programme, en pensant bien à restaurer l'adresse de la pile préalablement sauvegardée au début de l'exécution, après toutes les opérations standard nécessaires. La libération de la mémoire est simplement gérée par les fonctions laissées à atexit() !

Pour ce qui est syscalls, on peut se baser dessus puisqu'on n'en distribue pas le code, qui est dans l'OS et pas dans le g1a

Au passage, je ne vois que malloc() et free() qu'on doive utiliser pour l'instant, tout le reste me semble possible à implémenter manuellement.
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)
Intelligide Hors ligne Membre de CreativeCalc Points: 49 Défis: 5 Message

Citer : Posté le 21/04/2015 14:18 | #


va falloir bouger le repo, gitorious va fermer

Ajouté le 22/04/2015 à 07:58 :
au fait, est ce qu'un système de console va être mis en place avec printf, etc?
Lephenixnoir Hors ligne Administrateur Points: 24145 Défis: 170 Message

Citer : Posté le 22/04/2015 08:58 | #


Intelligide a écrit :
au fait, est ce qu'un système de console va être mis en place avec printf, etc?

Oui, il y en aura un. Typiquement, un programme prend en charge l'affichage à l'écran assez simplement (c'est lié à stdout/stderr) et bloque plus ou moins les possibilités de l'utilisateur de dessiner.

Il ne sera pas possible d'empêcher au sens propre l'utilisateur de dessiner par dessus, encore que je pense qu'on pourra se passer de quelques libs : du coup on aura soit un projet console, soit un projet graphique, et les projets console pourront être plus légers

Mais sous gcc, hein. Ça va très certainement se baser encore sur l'interrupt handler, donc à mon avis ce ne sera pas applicable au SDK de base (quoique probablement au winsdk).

À ce sujet, tu comptes intégrer la lib standard au winsdk ?

Ajouté le 22/04/2015 à 14:07 :
Bon, j'ai deux mauvaises nouvelles.
La première et la moins problématique, c'est que la division fait chier. On n'a pas une instruction qui divise, mais bien une qui calcule un bit. Donc il faut l'appeler 32 fois tout en décalant le dividende d'un bit vers la droite entre chaque opération, soit un total d'au moins 64 cycles, plus une instruction d'initialisation. La libgcc a un symbole pour faire ça, je crois que je vais faire pareil.

Et la deuxième, bien plus gênante, c'est que contrairement à ce que je pensais, on n'a pas de FPU pour le calcul flottant. Donc tout est bordélique. Il faut gérer le format flottant manuellement. On peut faire appel aux symboles de gcc de ce côté-là, mais je trouve pas ça spécialement intéressant. Mais on est obligés de respecter le format utilisé par gcc si on veut garder la compatibilité entre nos fonctions et ses opérations de base (additions, etc.).

Pour donner un exemples, prenons le code suivant :
double f(double x)
{
    return x+1;
}

Il est compilé en ceci avec -09 :
_f:
    mov.l    .L3,r0 // fonction __adddf3()
    mov.l    .L4,r6 // 1072693248 en troisieme argument
    sts.l    pr,@-r15 // sauvegarde du procedure register
    jsr    @r0 // appel de la fonction (delayed)
    mov    #0,r7 // 0 en quatrieme argument
    lds.l    @r15+,pr // restauration de pr
    rts
    nop
.L5:
    .align 2
.L3:
    .long    ___adddf3
.L4:
    .long    1072693248

Autrement dit pour calculer x+1 gcc réalise cet appel :
__adddf3(x, <r5?>, 1072693248, 0);

Super.

Autre exemple, pour le calcul de 2*x :
__addfx3(x, <r5?>, x, <r5?>);

Je me demande vraiment comme ça peut fonctionner alors que la valeur de r5 n'est déterminée dans aucun des deux cas puisqu'il n'y a qu'un argument.

Comme c'est le bordel complet, je me suis demandé si c'était vraiment utile d'intégrer ça à la bibliothèque standard. Ben oui, on avait décidé qu'on stoppait tous les calculs flottants à 6 décimales parce que notre implémentation de math ne permettait pas une précision optimale !

Et puis j'ai pensé aux fixed de Kristaba. Et du coup, voilà ce que je propose : on implémente une bibliothèque standard qui utilise les fixed. Le calcul flottant est laissé à la charge du compilateur et lorsque le programme utilisateur voudra interfacer avec la libc il aura les conversions par macro.

Je ne sais pas si ça vous branche (en particulier Nemhardy, Dark Storm, avec qui je bosse initialement dessus -- faut que je vous file le code d'ailleurs ), mais dans ce cas je propose qu'on révise le nombre de décimales à 3 ou 4 parce que sinon notre plage de valeurs est trop faible, de -2'147.483'647 à +2'147.483'647 avec 6 décimales.

Avec 4 décimales, on a une plage plus large qui nous permet de monter jusqu'à deux cents mille. Je serais partant pour quatre décimales, après tout je ne pense pas qu'on veuille faire de mathématiques de principe (on va pas réinventer l'application RUN), même si on veut faire de la précision quatre décimales me semblent correctes.

Au pire après on peut toujours s'arranger, quitte à avoir un type de fixed3/fixed4 et un type de fixed6, bref, tous les aménagements sont possibles.

Qu'est-ce que vous en pensez ?
Mon graphe (24 Mars): (gint#27 ; (Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; ...) || (shoutbox v5 ; v5)
Intelligide Hors ligne Membre de CreativeCalc Points: 49 Défis: 5 Message

Citer : Posté le 22/04/2015 17:08 | #


bien sûr que je l'integrerai au winsdk , enfin si c'est libre

Citer : Posté le 22/04/2015 17:56 | #


Beau boulot d'investigation !
Les flottants ne sont-ils pas stockés sur deux registres "contigus" (ou alors au moins lorsque passés en arguments) ? Ça me dit quelque chose et ça expliquerait pourquoi ça fonctionne alors que r5 (ni r7 d'ailleurs, surtout que la fonction ne demande que 2 floats en argument) n'est jamais déterminé. Enfin, je vais relire la doc de ce côté là, je t'avouerai que ça fait un petit moment que je me suis pas plongé dans de l'asm...

Sinon, au niveau de la précision, je ne pense pas que ça soit un gros problème de se limiter à 3 ou 4 décimales, car en plus d’accélérer potentiellement certaines opérations, je ne vois pas trop de cas où ça poserait un sérieux problème (côté dev casio j'entends). Le tout c'est que les utilisateurs soient au courant.
Du coup, par rapport aux fixed, ils interviendraient uniquement en interne de la libC suivant ce que tu proposes ?

Je veux dire que si l'utilisateur a quelque part :

float a = 2.5;
a /= 0.7;


Là c'est le compilo qui se charge de gérer ça (je vois pas trop comment on pourrait faire autrement sans toucher au compilateur lui même d'ailleurs ), mais lorsqu'il appellera cos ou exp ou une fonction de la libC qui a besoin de (en interne ou en argument)/ retourne un flottant, ce qu'on reverrai c'est en fait un fixed passé par la macro de conversion pour en faire un float c'est ça ? Et du coup ce qui est implémenté bosse avec le fixed ? C'est ce qu'il me semble avoir compris mais je suis pas très sûr...

Edit : ah oui et au niveau des syscalls : effectivement malloc et free font partie de ceux qu'on pourra bien utiliser, en comptant peut être aussi ceux qui opèrent sur les fichiers, je ne crois pas qu'on ait d'alternatives fiable et assez générale pour l'instant non ?
Précédente 1, 2, 3, 4, 5, 6, 7, 8 Suivante

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2024 | Il y a 74 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd