Un petit billet pour présenter cette conférence de Daniel Fortier sur la mécanique quantique, particulièrement intéressante, qui ne requière que peu(pas?) de connaissances mathématique pour être abordé.

C'est un petit jeu de 12 vidéos, très agréable (si vous souhaitez vous détendre en soiré) :

http://www.youtube.com/watch?v=y9G9B3-q4xI
http://www.youtube.com/watch?v=dJEP0_w4Pfs
http://www.youtube.com/watch?v=6aczefi2XIk
http://www.youtube.com/watch?v=3NZCOwx6dSk
http://www.youtube.com/watch?v=ODM5ECaolgk
http://www.youtube.com/watch?v=Ysp74XJ7iSo
http://www.youtube.com/watch?v=n0sUBspLMj0
http://www.youtube.com/watch?v=s2rn8LBmKTY
http://www.youtube.com/watch?v=kmpKh-ZcxQ8
http://www.youtube.com/watch?v=yn1zvivbj0E
http://www.youtube.com/watch?v=BHxOWs3Rs4c
http://www.youtube.com/watch?v=ZD1lD-DL_OE

Sur ce, bonsoir.

 

Bonjour

Comme je l'avais laissé entendre dans le précédent billet, je travaillais sur un second document, relatif à l'informatique. À vrais dire, travailler est un bien grand mot. Il se trouve que je devais rédiger le dernier chapitre, mais souhaitant m'imposer de donner la priorité à mes études, j'ai reporté la rédaction de ce dernier après l'échéance du rendu du premier document (cf: billet précédent). Il s'est avéré que sa rédaction fut (beaucoup) plus rapide que je ne le prévoyais. Aussi, c'est la correction orthographique qui me prit tant de temps.

Un petit retour sur la rédaction

Je voudrais demander à mes lecteurs de ne pas être trop sévère quant à la rédaction ; il s'agit du second texte de cette envergure (une 40aine de pages) bien que sa "publication" ne vienne qu'après le troisième (qui n'est autre que mon TIPE). Les phrases ne sont pas toujours très élégantes, et parfois les mots mal choisis. Je ne me sentais pas le courage de reprendre tout le document. Il n'en est pas moins un document qui sauras surement se montrer utile à des étudiants qui souhaiterais découvrir et comprendre le mythique "Bruit de Perlin".

Le bruit de Perlin ?

Pour ceux qui ne connaitrais pas encore cette algorithme, le bruit de Perlin est un outil très prisé pour la génération de textures paramétriques. Plus que des mots, une simple image pour résumer :

Perlin Noise

Voici, sans plus attendre, le lien vers le document en question : Bruit de Perlin

Perlin Noise

 

Gnu Flex

Gnu Flex est un générateur d'Analyseurs Lexicaux. Pour résumé, ce sont des outils qui permettent de générer des parseurs(dans le cas présent, une fonction C capable de découper en morceaux un flux de caractères).

Grâce à cette outil, on peut développer rapidement des analyseurs lexicaux très puissants, pouvant être utilisé dans le cadre du développement d'un compilateur, ou plus modestement pour charger des fichiers de configuration.

Ainsi, je vous présente un article (terminé aux alentours de  février, la correction orthographique m'ayant pris """un peu""" de temps), aussi publié sur développez (au même format pour le moment) qui présente dans les moindres détailles le fonctionnement de Flex, basé sur la documentation et une observation du comportement de la dernière version.

Le lien, pour ne plus attendre : Introduction à Gnu FLEX

 

La recherche de racine pour des polynômes du 3ème degré

\( Delta = b^2 - 4ac \), voici une formule que la plupart d'entre vous on appris très jeunes, et dont la simple lecture ou écoute évoque immédiatement la résolution de polynômes du second degré.

Mais vous êtes vous déjà pausé la question de la résolution d'équations mettant en jeu des polynômes du troisième degré, ou pire, d'un degré encore plus élevé?

Sachez que pour les dégrées strictement supérieur à 4, les équations ne sont alors plus "soluble par radicaux". Ce que l'on pourrais résumer à "Finis les belles formules magiques au dessus du degré 4".

Dans cette article, nous nous intéresserons à la méthode de Tartaglia-Cardan, du nom de ces deux célèbres mathématiciens, respectivement a l'origine de la méthode et de sa publication. (Je vous invite a en apprendre plus sur nos deux protagoniste, ainsi que Ferrari - le secrétaire de cardan - à qui l'on dois la résolution des équations de degré 4 par radicaux.)

Nous chercherons à adapter la méthode "papier" pour une application informatique, affin d'obtenir une valeur réel avec une précision convenable. Nous ne chercherons donc pas la réponse "exacte" comme l'on peut la trouver avec un crayon et beaucoup de papier.

Sachez que résoudre des équations de degré 3 peut avoir de nombreuse applications, et que probablement certains de mes lecteurs souhaiteront la mettre en œuvre dans le cadre d'un raytracer d'ici la fin de l'année scolaire. Plus que de donner une implémentation, je souhaite ici détailler la logique qui en est à l'origine.

Étape 1 ) Changement de variable

La méthode de cardan ne s'applique qu'à des polynômes de la forme \( Z^3 + pZ + q = 0 \) et nous cherchons une solution pour tout polynôme de la forme \( aX^3 + bX^2 + cX + d = 0 \)

On considéreras donc deux cas : Notre polynôme a son coefficient du second degré nulle, et dans ce cas on n'effectue pas de changement de variable, on le rend juste unitaire(diviser par a). Dans le cas contraire, on pauseras \( X = Z - \frac{b}{3a} \), ce qui nous amène a calculer à calculer \( p = - \frac{b^2}{3a^2} + \frac{c}{a} \) et \( q = \frac{b}{27a}\left(\frac{2b^2}{a^2}-\frac{9c}{a}\right)+\frac{d}{a} \) (en développant le polynôme \( a(Z - \frac{b}{3a})^3 + b(Z - \frac{b}{3a})^2 + c(Z - \frac{b}{3a}) + d = 0 \)) , et par la suite ajouter \( \frac{b}{3a} \) a nos solutions.

Voici le code c correspondant :

int cardan(float a, float b, float c, float d, float resultat[3])
// -> resultat est notre tableau de solutions
//Retourne le nombre de racines trouvé
{
  //Nos coefs
  float p;
  float q;
  //Ce que nous ajouterons a nos solution, si le changement de variable a eu lieu
  float correction = 0;
 
  //Si il n'y a pas besoin de changement de variable
  if (b == 0)
  {
    p = c / a;
    q = d / a;
  }
  //Sinon
  else
  {
    p = (-b * b / (3 * a) + c) / a;
    q = (b/(27 * a) * (2 * b * b / a - 9 * c) + d) / a;
    correction = -b/(3 * a);
  }
  //... see next block

Étape 2 ) Système solution

Nous entrons enfin dans le vif du sujet. Comment allons nous maintenant trouver les racines de notre polynôme? Pour commencer, nous savons qu'il existe au moins une racine réel (Un polynôme de degré impaire admet toujours au moins une racine réel) que l'on peut écrire sous la forme v + u, v et u deux réels. (Car, évidemment, rien ne nous empêche d'écrire 3 comme 2+1, ou 3+0!)

A ce stade, si nous développons notre polynôme avec u+v, nous obtenons \( v^3+u^3+(3uv+p)(u+v)+q=0 \) (modulo une factorisation par (u+v) ).
Puisque nous pouvons "répartir" notre solution "un peut dans u, le reste dans v" comme nous le souhaitons, rien ne nous empêche de fixer \( 3uv+p = 0 \) (ou encore \( uv = \frac{-p}{3u} \)

On remarque alors que notre polynôme se simplifie, laissant apparaitre \( u^3 + v^3= -q \)

En d'autres termes, notre solution est donc solution du système \( \begin{cases}u^3+v^3&=-q\\ u^3v^3&=-\frac{p^3}{27}\end{cases} \) (et doivent respecter en plus la condition \( 3uv+p = 0 \)).

Vous remarquerez alors que connaissant le produit et la somme de deux nombres a et b, nous pouvons nous servir du polynôme du second dégrée \( x^2 -(a + b)X + ab = 0 \) qui a pour racines a et b. Appliquons ceci à \( u^3 \) et \( v^3 \)

On résout donc \( X^2+qX-\frac{p^3}{27}=0 \). Attention, les solutions sont soit complexe, soit réels, soit réels double (u = v). Dans le cas de solutions pour u et v réels, leur racine cubique est un réel unique et nous aurons donc l'unique racine du polynôme. Dans le cas de solutions complexe(non nulle) pour u et v, nous aurons alors 3 racines cubiques pour u et 3 pour v. Nous verrons dans le paragraphe suivant comment calculer ces racines et trouver les bonnes combinaisons.

Voici l'implémentation pour les racines réels :

  // ... next block :
  float delta = q*q + 4 * p*p*p / 27; //On applique delta = b^2+4ac où b=q, a=1, c = -p^3/27
  // Racine double réel => 3 solutions réels, dont une double
  if (delta == 0)
  {
    //En grattant beaucoup de papier, on parvient à calculer directement
    // les racines sans utiliser pow. Nous en profitons donc :
    float z1 = 3.f * q / p;
    float z2 = -3.f / 2.f * q / p;
    resultat[0] = z1 + correction;
    resultat[1] = z2 + correction;
    resultat[2] = resultat[1];
    //Finalement, ce polynôme a 3 racines :
    return 3;
  }
  // Une unique solution réel
  else if (delta > 0)
  {
    //La racine carré de delta :
    delta = sqrt(delta);
    //Nos solutions u et v :
    float u = (-q - delta) / 2.f;
    float v = (-q + delta) / 2.f;
    //On calcule alors leur racine cubique :
    u = pow(u, 1.f/3.f);
    v = pow(v, 1.f/3.f);
    // notre racine est donc u + v + correction
    resultat[0] = u + v + correction;
    //Finalement, ce polynôme n'a qu'une racine :
    return 1;
  }
  else
  {
    //to be continue

Étape 3 ) Racines complexe : un peu de géométrie

Multiplier un complexe a par un complexe b, c'est obtenir un complexe c dont la norme est le produit de |a| et |b|, et l'argument la somme de arg(a) et arg(b). D'un point de vue géométrique, le produit de a par b est une rotation de a d'angle arg(b) dans le sens trigonométrique, et une homothétie par le scalaire |b|. Où cela nous conduit-il? A la définition d'une racine cubique d'un complexe. Soit \( a = |a|e^{arg(a)} \) le complexe d'argument arg(a) et de norme |a|, on a pour racine cubique : \( z_1 = \sqrt[3]{|a|}e^{arg(a)} \) \( z_2 = \sqrt[3]{|a|}e^{arg(a)/3 + 2\pi/3} \) \( z_3 = \sqrt[3]{|a|}e^{arg(a)/3 + 4\pi/3} \)

De façon générale, les racines nièmes d'un complexe d'argument arg(a) et de norme |a| est la rotation de \( \frac{arg(a)}{n} \) et homothétie de scalaire \( \sqrt[3]{|a|} \) des racines nième complexe de 1 (pouvant elles même être considéré comme un polygone...)

Bref, de belles façons d'interpréter les choses, mais en quoi cela nous aide-il?

Et bien, si nous pouvions connaitre l'argument d'un complexe et son module, nous pourrions calculer numériquement l'argument et le module de ses racines, et ainsi trouver les valeurs possible pour u et v. Considérons donc nos solutions complexe comme les points d'un plan. Le module et l'argument forment alors leur coordonnées polaire. Nous avons le système suivant qui lit les coordonnées cartésiennes d'un point à ses coordonnées polaire : \( \begin{cases}x&=r cos(alpha)\\ y&=r sin(alpha)\end{cases} \) De plus, nous pouvons calculer r, en appliquant le théorème de Pythagore. Si l'on fait alors le quotient de x par y, on obtient \( tan(alpha) \). En fait, en étudiant le signe de x et de y, on peut connaitre le signe de alpha et donc utiliser atan (la réciproque de tangente, modulo le bonne ensemble de définition). (Pour se simplifier la tache en C, on peut utiliser la fonction tan2(x, y) qui effectue le quotient et tien compte des signes.)

Encore un dernier détaille, et nous avons terminé. Les solutions que nous trouverons pour u et v peuvent se classer par paire de conjugué (les racines de u et v correspondant a la même racine cubique de 1). On remarque alors que les solutions seront toute bien réel. (La partie imaginaire de chacun des conjugué s'annulant.) Bien, passons à l'implémentation :

  // ... last block :
    //On commence par prendre la valeur absolue de delta
    //Par la suite, on suppose delta > 0.
    delta = -delta;
    //Petit rappelle, nos solutions sont de la forme : -q/2 +- i sqrt(delta)/2
    //Donc, de module au carré r^2 = (-q/2)^2 + (sqrt(delta)/2)^2 = q^2/4 + (delta)/4
    //FInalement r = sqrt(q^2 + delta) / sqrt(4)
    //Calculons le module :
    float r = sqrt(q*q + delta) / 2;
    //Maintenant, l'argument de nos complexe. Si deux complexe sont des conjugué, alors
    // ils on simplement leur argument de signe opposé. Comme on peux indifféremment inverser u et v, nous n'avons
    // pas besoin de tan2.
    // En simplifiant y / x, on trouve +-sqrt (delta) / q
    float alpha = atan(sqrt(delta) / q);
    // Nous calculons l'argument et le module d'une des racine complexe
    // (Celle au plus petit argument, c'est a dire Theta + 0PI/3)
    // Par la suite, alpha = theta et r = r^(1/3)
    r = pow(r, 1.f/3.f);
    alpha = alpha / 3.f;
    //Nous pouvons donc calculer nos trois racines réels, en passant de coordonnée polaire à des coordonnées cartésiennes.
    //De plus, nous simplifions et ne calculons pas la partie imaginaire, qui comme expliqué précédemment est nulle
    resultat[0] = 2 * r * cos(alpha) + correction; //nous avons effectivement r*cos(alpha) + r*cos(alpha)
    resultat[1] = 2 * r * cos(alpha + 2*PI/3) + correction;
    resultat[2] = 2 * r * cos(alpha + 4*PI/3) + correction;
    return 3;
  }
}
//Ouf! C'est terminé!

Pour conclure, un petit coup de wikipedia vous montreras que l'on peut simplifier le calcule du module, et n'utiliser qu'une simple racine carrée. Pensez aussi que si vous pouvez éviter de calculer deux fois la même chose, vous gagnerez en performance. Pensez a factoriser les expression de manière a ce que les produits/quotient soient résolut à la compilation et cherchez a minimiser les produits/quotient.

Notez que celons le contexte, on préfèreras considérer une racine double qu'une seule fois, affin d'éviter la redondance des calcules.

Sur papier?

Sachez que la méthode papier consiste à effectuer le même raisonnement que j'ai mené jusqu'au calcule du discriminant du polynôme qui nous permet de trouver a et b. Dans le cas delta >= 0, on calculeras la racine cubique et on factoriseras le polynôme pour faire apparaitre les racines. Dans le cas de complexes, on pourras être amener a chercher les racines d'un nouveau polynôme du 3ème degré pour simplifier l'expression des racines. Bien que la méthode de Tartaglia-Cardan soit une méthode qui fonctionne parfaitement, il n'est pas toujours facile de calculer les racines d'un polynôme de degré 3.

 

Bonsoir,

Vous vous demandez peut-être pourquoi plus un seul article n'a fleuris sur ce blog le long de ce dernier moi? Et bien, c'est tout simplement que j'ai commencer la rédaction d'un long - très long.... trop long! - document relatif au fonctionnement de la couche VFS de linux. Actuellement, je suis bien loin d'avoir rédiger la moitier de ce document, cherchant a illustrer mes dires de schéma et de code, à vérifier l'exactitude des informations que j'ai pus recueillir, la simple introduction que constituent les chapitres 1 et 2 m'ont prit énormément de temps. J'espère que toute fois ils vous paraitrons aussi claire qu'ils le sont pour moi, et que les multiples illustrations vous seront utile pour mieux visualiser les mécanismes mis en jeux.

Mais qu'est ce que VFS?

Peut-être que certains d'entre vous ont manquer mon engouement récent à l'écriture d'un file-système et les articles relatifs, aussi je me dois au moins d'expliquer succinctement ce dont il est ici question.

VFS, pour Virtual File System(Système de fichier Virtuel) est une couche d'abstraction fournis par le kernel linux affin de développer aisément des drivers qui ont a manipuler des fichier. C'est en fait très dépendant de l'architecture "tout fichier" de linux. Via vfs, il est en effet possible avec un simple éditeur de texte de modifier des données stoker sur un disque, mais aussi de modifier la configuration du processeur (il est ici question du fameux file-système /proc, qui ne correspond a aucun fichier physique, et que l'on qualifie donc de virtuel).

Ce document présente donc les bases de VFS nécessaire au développement d'un driver de filesystème, qu'il soit virtuel ou bien associer a un driver de block.

Les chapitres 1 et 2

En fait, les seuls chapitre présent sont une introduction à ce qu'est VFS et quelques détailles sur des mécanismes qui ne sont pas directement lier a son utilisation. Ainsi, le cœur du problème (manipulation des ad-spaces, structures de pointeurs de fonctions, impémentation de lookup et readdir, etc...) n'y figure pas. Ne soyez donc pas trop exigent de ces premiers chapitre et soyez sur que le contenue deviendras plus technique et ciblé dans les chapitres suivant.

Sur ce,

Je vous laisse le lien vers ces premiers chapitres : vfs_01.pdf

© 2012 Zenol's Blog Suffusion theme by Sayontan Sinha