Après GNU Octave 4.0.0, Scilab 6.0.0 se prépare à sortir

GNU Octave 4.0.0 est en effet sorti le 29 mai 2015 :

Octave 4.0 est une nouvelle version majeure avec de nombreuses nouvelles fonctionnalités, dont une interface utilisateur graphique, la prise en charge de la programmation orientée objet (classdef), une meilleure compatibilité avec MATLAB, et de nombreuses fonctions nouvelles et améliorées .

      → List of important user-visible changes

Scilab 6.0.0 (alpha) est sorti le 30 juillet 2015 :

Cette version inclut une réécriture majeure du noyau interne de Scilab. Les modifications apportées aux aspects visibles du logiciel sont limitées.

Ces changements n’auront pas beaucoup d’impact pour les utilisateurs finaux, mais ils apportent des améliorations majeures à la plateforme Scilab, qui conduiront à de nouvelles améliorations futures, en termes de gestion de code, d’outils de développement (débogueur, analyseur …), ainsi que des améliorations de Xcos, qui ne seraient pas possibles sans cette version.

      → Sortie de Scilab 6.0.0-alpha 1

À noter que Scilab 6 est encore en version alpha :

Comme toute alpha, cette version n’est encore pas prête pour être utilisée en production. Si vous débutez sur Scilab, ou si vous êtes un simple utilisateur, vous devriez continuer à utiliser la version 5.5.2, et attendre une version bêta avant d’essayer la famille 6.

Liens :

Voici donc deux nouvelles versions majeures pour les principaux concurrents de MATLAB en 2015 !

Quand MATLAB et fprintf ne regardent pas dans la même direction…

La fonction fprintf de MATLAB est très utile pour contrôler l’écriture de données dans un fichier texte. Sa syntaxe est la suivante :

fprintf(fileid, format, A)

Le premier argument fileid est l’identifiant du fichier renvoyé par la fonction fopen. Le deuxième argument format gère le formatage de l’écriture. C’est l’argument le plus compliqué à maitriser et il faudra souvent se référer à la documentation pour savoir quel formatage utiliser. Le dernier argument A est le tableau de données à écrire dans le fichier.

Il y a une subtilité à connaitre, même pour des cas d’utilisation de fprintf relativement simple. C’est ce que je vais vous présenter maintenant.

Le problème

Ecrire dans un fichier texte le tableau suivant :

M = [1 2 ; 3 4 ; 5 6]

Soit :

M =

     1     2
     3     4
     5     6

Le contenu du fichier doit donc être le suivant :

1 2
3 4
5 6

Comme un fichier texte s’écrit ligne après ligne (en séparant chaque ligne avec un retour à la ligne), on serait tenté d’écrire le code suivant :

fid = fopen('test.txt', 'wt');
fprintf(fid, '%d %d\n', M);
fclose(fid);

concise-writer-calvin

%d signifie que la valeur à écrire sera un entier. On met deux fois ce format car le tableau a deux colonnes. Puis on demande à fprintf de passer à la ligne avec \n. fprintf répète ensuite ce motif tant qu’il y a des valeurs à écrire. En faisant cela, on ne tient pas compte du nombre de lignes du tableau. Ce qui est très pratique si ce nombre n’est pas constant entre deux appels à fprintf.

En exécutant le code ci-dessus, le fichier texte contient :

1 3
5 2
4 6

Aïe ! Cela ne correspond pas du tout au tableau initial. Les valeurs semblent mélangées.

Les raisons

Le code précédent est faux car il y a une différence fondamentale entre MATLAB et la fonction fprintf.

Le stockage en mémoire des tableaux par MATLAB est particulier. Les valeurs sont stockées dans un vecteur où elles sont toutes contiguës (il n’y a pas d’élément vide entre elles). MATLAB les stocke colonne par colonne (1ère colonne, 2ème colonne, 3ème colonne…). Lire à ce sujet : Stockage des matrices en mémoire.

Le tableau suivant :

M =

     1     2
     3     4
     5     6

est donc stocké comme ceci en mémoire :

     1 3 5 2 4 6

Pourquoi ce choix me direz-vous ? Eh bien parce que MATLAB était initialement écrit en Fortran. Et que les tableaux sont définis colonne par colonne dans ce langage. Donc fprintf prend ces valeurs dans cet ordre et il est alors normal de trouver le 1 et le 3 sur la première ligne du fichier, suivi du 5 et du 2 sur la deuxième ligne et pour finir, du 4 et du 6 sur la dernière.

D’accord, mais les concepteurs de MATLAB auraient facilement pu prendre ceci en compte et, sans tenir compte de l’ordre de stockage par MATLAB, créer une fonction fprintf respectant un passage du tableau sous sa forme naturelle.

Oui mais voila, en 1984, MATLAB a été réécris en langage C. La fonction fprintf de MATLAB repose donc directement sur la fonction homonyme en C (voir les références en bas de la documentation).

Et alors, pourquoi vous parler de Fortran et de C ? Eh bien parce que, en langage C, les tableaux sont définis ligne par ligne.

Si MATLAB utilisait la convention de stockage du C, le code suivant fonctionnerait donc :

fprintf(fid, '%d %d\n', M);

Or ce n’est pas le cas. La fonction fprintf n’a donc pas un comportement naturel pour l’écriture des tableaux de MATLAB.

Les solutions

La première solution consiste à prendre en compte ce problème dès la conception du code et à créer le tableau suivant :

M = [1 3 5 ; 2 4 6];

Soit :

M =

     1     3     5
     2     4     6

Il n’est malheureusement pas toujours envisageable de créer le tableau de cette manière.

La deuxième solution consiste alors à transposer le tableau passé à fprintf. C’est à dire à permuter les lignes et les colonnes du tableau :

M = [1 2 ; 3 4 ; 5 6];
M = M.';

Le tableau devient donc :

M =

     1     3     5
     2     4     6

On peut ensuite faire :

fprintf(fid, '%d %d\n', M);

Ou directement avec le tableau d’origine :

fprintf(fid, '%d %d\n', M.');

La fonction fprintf écrira donc d’abord les valeurs 1 et 2 sur une ligne du fichier, puis 3 et 4 sur une autre, pour finir avec 5 et 6 sur la dernière.

Conclusion

Vous savez maintenant comment écrire correctement un tableau dans un fichier texte avec un seul appel à fprintf depuis MATLAB.

fprintf reste une fonction difficile à manipuler. N’hésitez pas à me poser des questions ou à me soumettre des suggestions à propos de cette fonction en commentaire. Je pourrai toujours faire d’autres billets au sujet de cette fonction.

Utiliser Automation depuis Scilab sur Windows (2)

Dans un précédent billet, J’ai présenté une méthode permettant de faire communiquer Scilab et différent processus sur Windows : Utiliser Automation depuis Scilab sur Windows.

Avant de pouvoir utiliser le module « ole », il faut compiler des codes C++. Malheureusement, la compilation ne fonctionne pas avec les versions récentes de Visual Studio, notamment la version 12 (2013).

Compilation du module « ole »

Les étapes de la compilation sont résumées dans mon précédent billet  : Utiliser Automation depuis Scilab sur Windows.

Compilation réussie… ou pas ?

Pour savoir si le module « ole », a bien été correctement compilé, il faut vérifier deux choses.

D’une part, un nouveau dossier « bin » doit être créé. Il contient trois fichiers :

  • automation.dll
  • automation.exp
  • automation.lib

D’autre part, des fichiers avec l’extension « .bin » ont été créés dans le sous-dossier « macros »

Si c’est bien le cas, vous pouvez maintenant charger le module dans Scilab avec :

-->exec loader.sce;

Si vous obtenez le message :

!'VCExpress.exe' n'est pas reconnu en tant que commande interne   !
!                                                                 !
!ou externe, un programme exécutable ou un fichier de commandes.  !

Consultez le billet  : Utiliser Automation depuis Scilab sur Windows.

Si aucune erreur n’apparait et que les deux conditions énumérées précédemment ne sont pas vérifiées, il va falloir chercher où se situe le problème.

Échec de la compilation

Cherchez un fichier « automation.log » dans le sous-dossier « src\Release », ouvrez-le et cherchez le mot « error ». Vous avez maintenant un début de piste…

Si ce fichier « automation.log » n’existe pas ou que l’erreur ne correspond pas à celle décrite ci-dessous, ouvrez une nouvelle discussion dans le forum Scilab.

Erreur à l’inclusion de xtgmath.h

Avec Visual Studio 2013, une erreur apparait à la compilation de sci_ole_get.cpp (entre autres) :

1>C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xtgmath.h(206): error C2059: syntax error : '('
1>C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xtgmath.h(206): error C2062: type 'double' unexpected
1>C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xtgmath.h(206): error C2059: syntax error : ')'
1>C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xtgmath.h(206): error C2027: use of undefined type 'std::enable_if'
                 C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xtr1common(67) : see declaration of 'std::enable_if'
1>C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xtgmath.h(206): warning C4346: 'std::is_integral::value' : dependent name is not a type
                 prefix with 'typename' to indicate a type
1>C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xtgmath.h(206): error C2062: type 'int' unexpected
1>C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xtgmath.h(206): error C2146: syntax error : missing ')' before identifier '_Left'
1>C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xtgmath.h(206): error C2146: syntax error : missing ';' before identifier '_Left'
1>C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xtgmath.h(206): error C2143: syntax error : missing ';' before '+'

La ligne 206 de « xtgmath.h » :

_GENERIC_MATH1(round, _CRTSPECIAL)

Rien d’anormal à première vue, sauf que « round » est une macro définie précédemment dans le fichier « core_math.h » de Scilab :

#define     round(a)    (int)(((a)<0.0)?(a)-.5:(a)+.5)

scilab-visual-studio-xtgmath
Solution rapide :

  • mettre en commentaire la ligne n°206 dans le fichier « xtgmath.h ». Le fichier est en lecture seule, vous devrez donc modifier ses propriétés directement depuis l’explorateur de Windows.
  • lancer à nouveau la compilation du module « ole » depuis Scilab
  • rétablir la ligne n°206 dans le fichier « xtgmath.h »

Ce n’est certes ni la solution la plus élégante, ni la solution la plus robuste, mais elle est relativement simple à mettre en œuvre.

Conclusion

J’espère que ces deux billets de blog vous permettront d’utiliser Automation depuis Scilab.

Si, malgré les solutions proposées, vous avez toujours des problèmes de compilation du module « ole », n’hésitez pas à ouvrir une nouvelle discussion dans le forum Scilab. Pensez à joindre le fichier « automation.log » si possible.