float
IntelDataHandler::readFloat(
istream& source ) const
{
unsigned char tmp[ 4 ] ;
if ( ! source.read( reinterpret_cast< char* >( tmp ), 4) ) {
// Erreur...
}
float result
= ((tmp[ 2 ] & 0x7F) << 16) | (tmp[ 1 ] << 8) | tmp[ 0 ] ;
int dummy ;
result = ldexp( frexp( result, &dummy ),
tmp[ 2 ] >> 7 | tmp[ 3 ] << 1 ) ;
return (tmp[ 3 ] & 0x80) != 0
? - result
: result ;
}
float
IntelDataHandler::readFloat(
istream& source ) const
{
unsigned char tmp[ 4 ] ;
if ( ! source.read( reinterpret_cast< char* >( tmp ), 4) ) {
// Erreur...
}
float result
= ((tmp[ 2 ] & 0x7F) << 16) | (tmp[ 1 ] << 8) | tmp[ 0 ] ;
int dummy ;
result = ldexp( frexp( result, &dummy ),
tmp[ 2 ] >> 7 | tmp[ 3 ] << 1 ) ;
return (tmp[ 3 ] & 0x80) != 0
? - result
: result ;
}
float
IntelDataHandler::readFloat(
istream& source ) const
{
unsigned char tmp[ 4 ] ;
if ( ! source.read( reinterpret_cast< char* >( tmp ), 4) ) {
// Erreur...
}
float result
= ((tmp[ 2 ] & 0x7F) << 16) | (tmp[ 1 ] << 8) | tmp[ 0 ] ;
int dummy ;
result = ldexp( frexp( result, &dummy ),
tmp[ 2 ] >> 7 | tmp[ 3 ] << 1 ) ;
return (tmp[ 3 ] & 0x80) != 0
? - result
: result ;
}
class DataHandler
{
public:
virtual ~DataHandler() {}
virtual short readShort( istream& source ) const = 0 ;
virtual float readFloat( istream& source ) const = 0 ;
} ;
Ce sont les instances concrètes de cette classe où ça se corse.
Pour un IntelDataHandler, par exemple, ça serait quelque chose
comme :
short
IntelDataHandler::readShort(
istream& source ) const
{
unsigned char tmp[ 2 ] ;
if ( ! source.read( reinterpret_cast< char* >( tmp ), 2 ) ) {
// Erreur...
}
// Je suppose ici que la machine cible utilise une
// représentation complément à deux, et gère la
// conversion unsigned -> signed de la façon classique.
return (tmp[ 1 ] << 8) | tmp[ 0 ] ;
}
float
IntelDataHandler::readFloat(
istream& source ) const
{
unsigned char tmp[ 4 ] ;
if ( ! source.read( reinterpret_cast< char* >( tmp ), 4) ) {
// Erreur...
}
float result
= ((tmp[ 2 ] & 0x7F) << 16) | (tmp[ 1 ] << 8) | tmp[ 0 ] ;
int dummy ;
result = ldexp( frexp( result, &dummy ),
tmp[ 2 ] >> 7 | tmp[ 3 ] << 1 ) ;
return (tmp[ 3 ] & 0x80) != 0
? - result
: result ;
}
Quelles seraient les implémentations des classes permettant de
lire des short ou des floats pour des représentations DEC ou
MIPS?
Je ne connais absolument rien à ce pan de la programmation...
class DataHandler
{
public:
virtual ~DataHandler() {}
virtual short readShort( istream& source ) const = 0 ;
virtual float readFloat( istream& source ) const = 0 ;
} ;
Ce sont les instances concrètes de cette classe où ça se corse.
Pour un IntelDataHandler, par exemple, ça serait quelque chose
comme :
short
IntelDataHandler::readShort(
istream& source ) const
{
unsigned char tmp[ 2 ] ;
if ( ! source.read( reinterpret_cast< char* >( tmp ), 2 ) ) {
// Erreur...
}
// Je suppose ici que la machine cible utilise une
// représentation complément à deux, et gère la
// conversion unsigned -> signed de la façon classique.
return (tmp[ 1 ] << 8) | tmp[ 0 ] ;
}
float
IntelDataHandler::readFloat(
istream& source ) const
{
unsigned char tmp[ 4 ] ;
if ( ! source.read( reinterpret_cast< char* >( tmp ), 4) ) {
// Erreur...
}
float result
= ((tmp[ 2 ] & 0x7F) << 16) | (tmp[ 1 ] << 8) | tmp[ 0 ] ;
int dummy ;
result = ldexp( frexp( result, &dummy ),
tmp[ 2 ] >> 7 | tmp[ 3 ] << 1 ) ;
return (tmp[ 3 ] & 0x80) != 0
? - result
: result ;
}
Quelles seraient les implémentations des classes permettant de
lire des short ou des floats pour des représentations DEC ou
MIPS?
Je ne connais absolument rien à ce pan de la programmation...
class DataHandler
{
public:
virtual ~DataHandler() {}
virtual short readShort( istream& source ) const = 0 ;
virtual float readFloat( istream& source ) const = 0 ;
} ;
Ce sont les instances concrètes de cette classe où ça se corse.
Pour un IntelDataHandler, par exemple, ça serait quelque chose
comme :
short
IntelDataHandler::readShort(
istream& source ) const
{
unsigned char tmp[ 2 ] ;
if ( ! source.read( reinterpret_cast< char* >( tmp ), 2 ) ) {
// Erreur...
}
// Je suppose ici que la machine cible utilise une
// représentation complément à deux, et gère la
// conversion unsigned -> signed de la façon classique.
return (tmp[ 1 ] << 8) | tmp[ 0 ] ;
}
float
IntelDataHandler::readFloat(
istream& source ) const
{
unsigned char tmp[ 4 ] ;
if ( ! source.read( reinterpret_cast< char* >( tmp ), 4) ) {
// Erreur...
}
float result
= ((tmp[ 2 ] & 0x7F) << 16) | (tmp[ 1 ] << 8) | tmp[ 0 ] ;
int dummy ;
result = ldexp( frexp( result, &dummy ),
tmp[ 2 ] >> 7 | tmp[ 3 ] << 1 ) ;
return (tmp[ 3 ] & 0x80) != 0
? - result
: result ;
}
Quelles seraient les implémentations des classes permettant de
lire des short ou des floats pour des représentations DEC ou
MIPS?
Je ne connais absolument rien à ce pan de la programmation...
"kanze" wrote in news:1140691900.559197.28400
@z34g2000cwc.googlegroups.com:float
IntelDataHandler::readFloat(
istream& source ) const
{
unsigned char tmp[ 4 ] ;
if ( ! source.read( reinterpret_cast< char* >( tmp ), 4) ) {
// Erreur...
}
float result
= ((tmp[ 2 ] & 0x7F) << 16) | (tmp[ 1 ] << 8) | tmp[ 0 ] ;
int dummy ;
result = ldexp( frexp( result, &dummy ),
tmp[ 2 ] >> 7 | tmp[ 3 ] << 1 ) ;
return (tmp[ 3 ] & 0x80) != 0
? - result
: result ;
}
J'ai une erreur à l'éxécution sur la dernière ligne:
Débordement en virgule flottante
sur :
return (tmp[ 3 ] & 0x80) != 0 ? - result : result;
De où ça vient?
Question subsidiaire: avez-vous des liens qui pourraient me
permettre de comprendre le code ci-dessus, qui pour moi est du
chinois le plus complet?
"kanze" <kanze@gabi-soft.fr> wrote in news:1140691900.559197.28400
@z34g2000cwc.googlegroups.com:
float
IntelDataHandler::readFloat(
istream& source ) const
{
unsigned char tmp[ 4 ] ;
if ( ! source.read( reinterpret_cast< char* >( tmp ), 4) ) {
// Erreur...
}
float result
= ((tmp[ 2 ] & 0x7F) << 16) | (tmp[ 1 ] << 8) | tmp[ 0 ] ;
int dummy ;
result = ldexp( frexp( result, &dummy ),
tmp[ 2 ] >> 7 | tmp[ 3 ] << 1 ) ;
return (tmp[ 3 ] & 0x80) != 0
? - result
: result ;
}
J'ai une erreur à l'éxécution sur la dernière ligne:
Débordement en virgule flottante
sur :
return (tmp[ 3 ] & 0x80) != 0 ? - result : result;
De où ça vient?
Question subsidiaire: avez-vous des liens qui pourraient me
permettre de comprendre le code ci-dessus, qui pour moi est du
chinois le plus complet?
"kanze" wrote in news:1140691900.559197.28400
@z34g2000cwc.googlegroups.com:float
IntelDataHandler::readFloat(
istream& source ) const
{
unsigned char tmp[ 4 ] ;
if ( ! source.read( reinterpret_cast< char* >( tmp ), 4) ) {
// Erreur...
}
float result
= ((tmp[ 2 ] & 0x7F) << 16) | (tmp[ 1 ] << 8) | tmp[ 0 ] ;
int dummy ;
result = ldexp( frexp( result, &dummy ),
tmp[ 2 ] >> 7 | tmp[ 3 ] << 1 ) ;
return (tmp[ 3 ] & 0x80) != 0
? - result
: result ;
}
J'ai une erreur à l'éxécution sur la dernière ligne:
Débordement en virgule flottante
sur :
return (tmp[ 3 ] & 0x80) != 0 ? - result : result;
De où ça vient?
Question subsidiaire: avez-vous des liens qui pourraient me
permettre de comprendre le code ci-dessus, qui pour moi est du
chinois le plus complet?
IntelDataHandler::readFloat(
istream& source ) const
{
unsigned char tmp[ 4 ] ;
if ( ! source.read( reinterpret_cast< char* >( tmp ), 4) ) {
// Erreur...
}
float result
= (((tmp[ 2 ] & 0x7F) << 16 | 0x800000)) | (tmp[ 1 ] << 8)
| tmp[ 0 ] ;
int dummy ;
result = ldexp( frexp( result, &dummy ),
(tmp[ 2 ] >> 7 | tmp[ 3 ] << 1) - 126 ) ;
return (tmp[ 3 ] & 0x80) != 0
? - result
: result ;
}
IntelDataHandler::readFloat(
istream& source ) const
{
unsigned char tmp[ 4 ] ;
if ( ! source.read( reinterpret_cast< char* >( tmp ), 4) ) {
// Erreur...
}
float result
= (((tmp[ 2 ] & 0x7F) << 16 | 0x800000)) | (tmp[ 1 ] << 8)
| tmp[ 0 ] ;
int dummy ;
result = ldexp( frexp( result, &dummy ),
(tmp[ 2 ] >> 7 | tmp[ 3 ] << 1) - 126 ) ;
return (tmp[ 3 ] & 0x80) != 0
? - result
: result ;
}
IntelDataHandler::readFloat(
istream& source ) const
{
unsigned char tmp[ 4 ] ;
if ( ! source.read( reinterpret_cast< char* >( tmp ), 4) ) {
// Erreur...
}
float result
= (((tmp[ 2 ] & 0x7F) << 16 | 0x800000)) | (tmp[ 1 ] << 8)
| tmp[ 0 ] ;
int dummy ;
result = ldexp( frexp( result, &dummy ),
(tmp[ 2 ] >> 7 | tmp[ 3 ] << 1) - 126 ) ;
return (tmp[ 3 ] & 0x80) != 0
? - result
: result ;
}
Les short dans la représentation DEC, c'est identique aux short
Intel -- je crois (sans être 100% certain) que pour le MIPS, il
faut inverser le 1 et le 0 dans le return.
Quant aux floats... Il faudrait trouver de la documentation
quelque part sur leur format sur ces machines. Je ne le connais
pas. (J'ai lu quelque part que le format DEC -- c-à-d le format
PDP-11, je suppose, parce que DEC a fabriqué d'autres machines,
avec d'autres formats aussi -- est très proche du IEEE qui
utilise Intel. Reste à savoir aussi si l'ordre des octets est
1234, comme chez Intel, ou 3412, comme étaient les long, si mes
souvenirs sont exacts.)
Les short dans la représentation DEC, c'est identique aux short
Intel -- je crois (sans être 100% certain) que pour le MIPS, il
faut inverser le 1 et le 0 dans le return.
Quant aux floats... Il faudrait trouver de la documentation
quelque part sur leur format sur ces machines. Je ne le connais
pas. (J'ai lu quelque part que le format DEC -- c-à-d le format
PDP-11, je suppose, parce que DEC a fabriqué d'autres machines,
avec d'autres formats aussi -- est très proche du IEEE qui
utilise Intel. Reste à savoir aussi si l'ordre des octets est
1234, comme chez Intel, ou 3412, comme étaient les long, si mes
souvenirs sont exacts.)
Les short dans la représentation DEC, c'est identique aux short
Intel -- je crois (sans être 100% certain) que pour le MIPS, il
faut inverser le 1 et le 0 dans le return.
Quant aux floats... Il faudrait trouver de la documentation
quelque part sur leur format sur ces machines. Je ne le connais
pas. (J'ai lu quelque part que le format DEC -- c-à-d le format
PDP-11, je suppose, parce que DEC a fabriqué d'autres machines,
avec d'autres formats aussi -- est très proche du IEEE qui
utilise Intel. Reste à savoir aussi si l'ordre des octets est
1234, comme chez Intel, ou 3412, comme étaient les long, si mes
souvenirs sont exacts.)
J'ai tenté d'utiliser le code C que j'ai donné avant, et ça
marche pour les représentations Intel et DEC, que ce soit pour
les short ou les float...
J'ai ça du coup:
//-----------------------------------------------------------------------
--
short DECDataHandler::readShort(std::ifstream & source ) const
{
unsigned char tmp[ 2 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),2))
throw Exception("Impossible de lire le fichier");
return (tmp[ 1 ] << 8) | tmp[ 0 ] ;
}
//-----------------------------------------------------------------------
--
float DECDataHandler::readFloat(std::ifstream & source ) const
{
unsigned char tmp[ 4 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),4))
throw Exception("Impossible de lire le fichier");
long mantis = (tmp[2] & 0xff) + ((tmp[3] & 0xffl) << 8) + (((tmp[0] &
0x7fl) | 0x80) << 16);
short exp = (tmp[1] & 0x7f) * 2 + ((tmp[0] & 0x80) ? 1 : 0);
if (tmp[1] & 0x80)
mantis = -mantis;
float flt = (mantis || exp) ? ((float) ldexp (mantis, (exp - 128 - 24)))
: 0;
return flt;
}
et
short IntelDataHandler::readShort(std::ifstream & source ) const
{
unsigned char tmp[ 2 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),2))
throw Exception("Impossible de lire le fichier");
// Je suppose ici que la machine cible utilise une
// représentation complément à deux, et gère la
// conversion unsigned -> signed de la façon classique.
return (tmp[ 1 ] << 8) | tmp[ 0 ] ;
}
//-----------------------------------------------------------------------
//! Retourne un float
float IntelDataHandler::readFloat(std::ifstream & source ) const
{
unsigned char tmp[ 4 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),4))
throw Exception("Impossible de lire le fichier");
float * f = (float *)tmp;
float flt = *f;
//float result = (((tmp[ 2 ] & 0x7F) << 16 | 0x800000)) | (tmp[ 1 ] << 8)
| tmp[ 0 ] ;
//int dummy;
//result = ldexp( frexp( result, &dummy ), (tmp[ 2 ] >> 7 | tmp[ 3 ] <<
1) - 126 );
//return (tmp[ 3 ] & 0x80) != 0
// ? - result
// : result ;
return flt;
}
Et j'ai bien les bonnes valeurs...
J'ai tenté d'utiliser le code C que j'ai donné avant, et ça
marche pour les représentations Intel et DEC, que ce soit pour
les short ou les float...
J'ai ça du coup:
//-----------------------------------------------------------------------
--
short DECDataHandler::readShort(std::ifstream & source ) const
{
unsigned char tmp[ 2 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),2))
throw Exception("Impossible de lire le fichier");
return (tmp[ 1 ] << 8) | tmp[ 0 ] ;
}
//-----------------------------------------------------------------------
--
float DECDataHandler::readFloat(std::ifstream & source ) const
{
unsigned char tmp[ 4 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),4))
throw Exception("Impossible de lire le fichier");
long mantis = (tmp[2] & 0xff) + ((tmp[3] & 0xffl) << 8) + (((tmp[0] &
0x7fl) | 0x80) << 16);
short exp = (tmp[1] & 0x7f) * 2 + ((tmp[0] & 0x80) ? 1 : 0);
if (tmp[1] & 0x80)
mantis = -mantis;
float flt = (mantis || exp) ? ((float) ldexp (mantis, (exp - 128 - 24)))
: 0;
return flt;
}
et
short IntelDataHandler::readShort(std::ifstream & source ) const
{
unsigned char tmp[ 2 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),2))
throw Exception("Impossible de lire le fichier");
// Je suppose ici que la machine cible utilise une
// représentation complément à deux, et gère la
// conversion unsigned -> signed de la façon classique.
return (tmp[ 1 ] << 8) | tmp[ 0 ] ;
}
//-----------------------------------------------------------------------
//! Retourne un float
float IntelDataHandler::readFloat(std::ifstream & source ) const
{
unsigned char tmp[ 4 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),4))
throw Exception("Impossible de lire le fichier");
float * f = (float *)tmp;
float flt = *f;
//float result = (((tmp[ 2 ] & 0x7F) << 16 | 0x800000)) | (tmp[ 1 ] << 8)
| tmp[ 0 ] ;
//int dummy;
//result = ldexp( frexp( result, &dummy ), (tmp[ 2 ] >> 7 | tmp[ 3 ] <<
1) - 126 );
//return (tmp[ 3 ] & 0x80) != 0
// ? - result
// : result ;
return flt;
}
Et j'ai bien les bonnes valeurs...
J'ai tenté d'utiliser le code C que j'ai donné avant, et ça
marche pour les représentations Intel et DEC, que ce soit pour
les short ou les float...
J'ai ça du coup:
//-----------------------------------------------------------------------
--
short DECDataHandler::readShort(std::ifstream & source ) const
{
unsigned char tmp[ 2 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),2))
throw Exception("Impossible de lire le fichier");
return (tmp[ 1 ] << 8) | tmp[ 0 ] ;
}
//-----------------------------------------------------------------------
--
float DECDataHandler::readFloat(std::ifstream & source ) const
{
unsigned char tmp[ 4 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),4))
throw Exception("Impossible de lire le fichier");
long mantis = (tmp[2] & 0xff) + ((tmp[3] & 0xffl) << 8) + (((tmp[0] &
0x7fl) | 0x80) << 16);
short exp = (tmp[1] & 0x7f) * 2 + ((tmp[0] & 0x80) ? 1 : 0);
if (tmp[1] & 0x80)
mantis = -mantis;
float flt = (mantis || exp) ? ((float) ldexp (mantis, (exp - 128 - 24)))
: 0;
return flt;
}
et
short IntelDataHandler::readShort(std::ifstream & source ) const
{
unsigned char tmp[ 2 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),2))
throw Exception("Impossible de lire le fichier");
// Je suppose ici que la machine cible utilise une
// représentation complément à deux, et gère la
// conversion unsigned -> signed de la façon classique.
return (tmp[ 1 ] << 8) | tmp[ 0 ] ;
}
//-----------------------------------------------------------------------
//! Retourne un float
float IntelDataHandler::readFloat(std::ifstream & source ) const
{
unsigned char tmp[ 4 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),4))
throw Exception("Impossible de lire le fichier");
float * f = (float *)tmp;
float flt = *f;
//float result = (((tmp[ 2 ] & 0x7F) << 16 | 0x800000)) | (tmp[ 1 ] << 8)
| tmp[ 0 ] ;
//int dummy;
//result = ldexp( frexp( result, &dummy ), (tmp[ 2 ] >> 7 | tmp[ 3 ] <<
1) - 126 );
//return (tmp[ 3 ] & 0x80) != 0
// ? - result
// : result ;
return flt;
}
Et j'ai bien les bonnes valeurs...
Dans tous les cas ?
Je sais que le format des short est identique entre Intel et
DEC. Je crois aussi que le format des float (mais non des
doubles) est très semblable aussi. En revanche, je ne crois pas
que le format DEC supporte les dénormalisés, et je ne sais pas
en ce qui concerne les Inf et les NaN. Mais il se peut que ce ne
soit pas important -- que de telles valeurs ne t'intéressent
pas. (Aussi, si DEC ne supporte pas les dénormalisés, ça veut
dire simplement qu'ils n'apparaîtront pas.)
En ce qui concerne le troisième format : il y a tout à parier
qu'il suffit d'inverser les octets par rapport au format Intel.
En somme, c'est à peu près IEEE sur un long avec l'ordre des
octets 3412. Et l'exposant est excès 128, plutôt que excès 126.
On pourrait prèsqu'en faire une classe templatée.
float IntelDataHandler::readFloat(std::ifstream & source ) const
{
unsigned char tmp[ 4 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),4))
throw Exception("Impossible de lire le fichier");
float * f = (float *)tmp;
float flt = *f;
Attention ici. Ce que tu as fait dépend beaucoup de la machine.
(J'en conclus, d'ailleurs, que tu travaille sur un Intel. Ça ne
marcherait pas sur un Sparc.)
Essaie d'utiliser la même stratégie pour les flottants Intel que
pour les flottants DEC, puis inverser l'ordre des octets, et tu
dois pouvoir traiter le troisième format aussi.
Au fond, je crois qu'effectivement, on s'en tire très bien avec
des templates :
template< int byteOrder, int exponentExcess >
struct FloatConverter
{
int i0() const { return byteOrder / 1000 % 10
-
1 ; }
int i1() const { return byteOrder / 100 % 10 -
1 ; }
int i2() const { return byteOrder / 10 % 10 -
1
; }
int i3() const { return byteOrder % 10 - 1 ; }
float operator()( unsigned char bytes[ 4 ] )
const
{
float result = 0.0 ;
int exp = ((bytes[ i3() ] & 0x7F) << 1)
| (bytes[ i2() ] >> 7) ;
uint_least32_t mantisse = bytes[ i0() ]
| (bytes[ i1() ] << 8)
| ((bytes[ i2() ] & 0x7F) << 16)
;
if ( exp == 0 && mantisse != 0 ) {
// dénormalisé...
} else if ( exp == 0xFF ) {
// NaN, Inf...
} else {
result = ldexp( mantisse | 0x800000, exp -
exponentExcess - 24) ;
}
return (bytes[ i3() ] & 0x80) == 0
? result
: - result ;
}
} ;
template< int byteOrder >
struct ShortConverter
{
int i0() const { return byteOrder / 10 % 10 -
1
; }
int i1() const { return byteOrder % 10 - 1 ; }
short operator()( unsigned char bytes[ 2 ] )
const
{
return bytes[ i0() ] | (bytes[ i1() ] << 8) ;
}
} ;
avec des typedef's :
typedef ShortConverter< 12 >
IntelShortCvt ;
typedef FloatConverter< 1234, 126 >
IntelFloatCvt ;
typedef ShortConverter< 12 >
DECShortCvt ;
typedef FloatConverter< 3412, 128 >
DECFloatCvt ;
typedef ShortConverter< 21 >
MIPSShortCvt ;
typedef FloatConverter< 4321, 126 >
MIPSFloatCvt ;
Cette fois-ci, j'ai testé mon code pour le format Intel -- en
lisant sur un Sparc, qui n'a pas le même ordre d'octets. Pour
DEC, je me base sur le code que tu as posté, et pour MIPS, je
dévine un peu -- mais vu l'époque où est sorti le processeur,
IEEE me semble probable, et j'ai lu quelque part que c'était
grand-boutien.
Heureusement qu'il n'y a pas de double, ni un format IBM:-).
Dans tous les cas ?
Je sais que le format des short est identique entre Intel et
DEC. Je crois aussi que le format des float (mais non des
doubles) est très semblable aussi. En revanche, je ne crois pas
que le format DEC supporte les dénormalisés, et je ne sais pas
en ce qui concerne les Inf et les NaN. Mais il se peut que ce ne
soit pas important -- que de telles valeurs ne t'intéressent
pas. (Aussi, si DEC ne supporte pas les dénormalisés, ça veut
dire simplement qu'ils n'apparaîtront pas.)
En ce qui concerne le troisième format : il y a tout à parier
qu'il suffit d'inverser les octets par rapport au format Intel.
En somme, c'est à peu près IEEE sur un long avec l'ordre des
octets 3412. Et l'exposant est excès 128, plutôt que excès 126.
On pourrait prèsqu'en faire une classe templatée.
float IntelDataHandler::readFloat(std::ifstream & source ) const
{
unsigned char tmp[ 4 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),4))
throw Exception("Impossible de lire le fichier");
float * f = (float *)tmp;
float flt = *f;
Attention ici. Ce que tu as fait dépend beaucoup de la machine.
(J'en conclus, d'ailleurs, que tu travaille sur un Intel. Ça ne
marcherait pas sur un Sparc.)
Essaie d'utiliser la même stratégie pour les flottants Intel que
pour les flottants DEC, puis inverser l'ordre des octets, et tu
dois pouvoir traiter le troisième format aussi.
Au fond, je crois qu'effectivement, on s'en tire très bien avec
des templates :
template< int byteOrder, int exponentExcess >
struct FloatConverter
{
int i0() const { return byteOrder / 1000 % 10
-
1 ; }
int i1() const { return byteOrder / 100 % 10 -
1 ; }
int i2() const { return byteOrder / 10 % 10 -
1
; }
int i3() const { return byteOrder % 10 - 1 ; }
float operator()( unsigned char bytes[ 4 ] )
const
{
float result = 0.0 ;
int exp = ((bytes[ i3() ] & 0x7F) << 1)
| (bytes[ i2() ] >> 7) ;
uint_least32_t mantisse = bytes[ i0() ]
| (bytes[ i1() ] << 8)
| ((bytes[ i2() ] & 0x7F) << 16)
;
if ( exp == 0 && mantisse != 0 ) {
// dénormalisé...
} else if ( exp == 0xFF ) {
// NaN, Inf...
} else {
result = ldexp( mantisse | 0x800000, exp -
exponentExcess - 24) ;
}
return (bytes[ i3() ] & 0x80) == 0
? result
: - result ;
}
} ;
template< int byteOrder >
struct ShortConverter
{
int i0() const { return byteOrder / 10 % 10 -
1
; }
int i1() const { return byteOrder % 10 - 1 ; }
short operator()( unsigned char bytes[ 2 ] )
const
{
return bytes[ i0() ] | (bytes[ i1() ] << 8) ;
}
} ;
avec des typedef's :
typedef ShortConverter< 12 >
IntelShortCvt ;
typedef FloatConverter< 1234, 126 >
IntelFloatCvt ;
typedef ShortConverter< 12 >
DECShortCvt ;
typedef FloatConverter< 3412, 128 >
DECFloatCvt ;
typedef ShortConverter< 21 >
MIPSShortCvt ;
typedef FloatConverter< 4321, 126 >
MIPSFloatCvt ;
Cette fois-ci, j'ai testé mon code pour le format Intel -- en
lisant sur un Sparc, qui n'a pas le même ordre d'octets. Pour
DEC, je me base sur le code que tu as posté, et pour MIPS, je
dévine un peu -- mais vu l'époque où est sorti le processeur,
IEEE me semble probable, et j'ai lu quelque part que c'était
grand-boutien.
Heureusement qu'il n'y a pas de double, ni un format IBM:-).
Dans tous les cas ?
Je sais que le format des short est identique entre Intel et
DEC. Je crois aussi que le format des float (mais non des
doubles) est très semblable aussi. En revanche, je ne crois pas
que le format DEC supporte les dénormalisés, et je ne sais pas
en ce qui concerne les Inf et les NaN. Mais il se peut que ce ne
soit pas important -- que de telles valeurs ne t'intéressent
pas. (Aussi, si DEC ne supporte pas les dénormalisés, ça veut
dire simplement qu'ils n'apparaîtront pas.)
En ce qui concerne le troisième format : il y a tout à parier
qu'il suffit d'inverser les octets par rapport au format Intel.
En somme, c'est à peu près IEEE sur un long avec l'ordre des
octets 3412. Et l'exposant est excès 128, plutôt que excès 126.
On pourrait prèsqu'en faire une classe templatée.
float IntelDataHandler::readFloat(std::ifstream & source ) const
{
unsigned char tmp[ 4 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),4))
throw Exception("Impossible de lire le fichier");
float * f = (float *)tmp;
float flt = *f;
Attention ici. Ce que tu as fait dépend beaucoup de la machine.
(J'en conclus, d'ailleurs, que tu travaille sur un Intel. Ça ne
marcherait pas sur un Sparc.)
Essaie d'utiliser la même stratégie pour les flottants Intel que
pour les flottants DEC, puis inverser l'ordre des octets, et tu
dois pouvoir traiter le troisième format aussi.
Au fond, je crois qu'effectivement, on s'en tire très bien avec
des templates :
template< int byteOrder, int exponentExcess >
struct FloatConverter
{
int i0() const { return byteOrder / 1000 % 10
-
1 ; }
int i1() const { return byteOrder / 100 % 10 -
1 ; }
int i2() const { return byteOrder / 10 % 10 -
1
; }
int i3() const { return byteOrder % 10 - 1 ; }
float operator()( unsigned char bytes[ 4 ] )
const
{
float result = 0.0 ;
int exp = ((bytes[ i3() ] & 0x7F) << 1)
| (bytes[ i2() ] >> 7) ;
uint_least32_t mantisse = bytes[ i0() ]
| (bytes[ i1() ] << 8)
| ((bytes[ i2() ] & 0x7F) << 16)
;
if ( exp == 0 && mantisse != 0 ) {
// dénormalisé...
} else if ( exp == 0xFF ) {
// NaN, Inf...
} else {
result = ldexp( mantisse | 0x800000, exp -
exponentExcess - 24) ;
}
return (bytes[ i3() ] & 0x80) == 0
? result
: - result ;
}
} ;
template< int byteOrder >
struct ShortConverter
{
int i0() const { return byteOrder / 10 % 10 -
1
; }
int i1() const { return byteOrder % 10 - 1 ; }
short operator()( unsigned char bytes[ 2 ] )
const
{
return bytes[ i0() ] | (bytes[ i1() ] << 8) ;
}
} ;
avec des typedef's :
typedef ShortConverter< 12 >
IntelShortCvt ;
typedef FloatConverter< 1234, 126 >
IntelFloatCvt ;
typedef ShortConverter< 12 >
DECShortCvt ;
typedef FloatConverter< 3412, 128 >
DECFloatCvt ;
typedef ShortConverter< 21 >
MIPSShortCvt ;
typedef FloatConverter< 4321, 126 >
MIPSFloatCvt ;
Cette fois-ci, j'ai testé mon code pour le format Intel -- en
lisant sur un Sparc, qui n'a pas le même ordre d'octets. Pour
DEC, je me base sur le code que tu as posté, et pour MIPS, je
dévine un peu -- mais vu l'époque où est sorti le processeur,
IEEE me semble probable, et j'ai lu quelque part que c'était
grand-boutien.
Heureusement qu'il n'y a pas de double, ni un format IBM:-).
Dans tous les cas ?
J'ai deux fichiers de test, un écrit avec des flottants DEC et
l'autre avec des flottants Intel. Les deux fonctionnent.
Je sais que le format des short est identique entre Intel et
DEC. Je crois aussi que le format des float (mais non des
doubles) est très semblable aussi. En revanche, je ne crois
pas que le format DEC supporte les dénormalisés, et je ne
sais pas en ce qui concerne les Inf et les NaN. Mais il se
peut que ce ne soit pas important -- que de telles valeurs
ne t'intéressent pas. (Aussi, si DEC ne supporte pas les
dénormalisés, ça veut dire simplement qu'ils n'apparaîtront
pas.)
Que veut dire dénormalisé? Inf? Nan?
En ce qui concerne le troisième format : il y a tout à
parier qu'il suffit d'inverser les octets par rapport au
format Intel.
Comment on inverse les octets?
En somme, c'est à peu près IEEE sur un long avec l'ordre des
octets 3412. Et l'exposant est excès 128, plutôt que excès
126. On pourrait prèsqu'en faire une classe templatée.
A quoi correspond l'excès?
float IntelDataHandler::readFloat(std::ifstream & source ) const
{
unsigned char tmp[ 4 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),4))
throw Exception("Impossible de lire le fichier");
float * f = (float *)tmp;
float flt = *f;
Attention ici. Ce que tu as fait dépend beaucoup de la machine.
(J'en conclus, d'ailleurs, que tu travaille sur un Intel. Ça ne
marcherait pas sur un Sparc.)
Oui, je suis sur PC... J'imagine qu'AMD == Intel, c'est
l'architecture x86 qui détermine je suppose?
Cette fois-ci, j'ai testé mon code pour le format Intel --
en lisant sur un Sparc, qui n'a pas le même ordre d'octets.
Pour DEC, je me base sur le code que tu as posté, et pour
MIPS, je dévine un peu -- mais vu l'époque où est sorti le
processeur, IEEE me semble probable, et j'ai lu quelque part
que c'était grand-boutien.
Ca veut dire quoi grand-boutien?
Dans tous les cas ?
J'ai deux fichiers de test, un écrit avec des flottants DEC et
l'autre avec des flottants Intel. Les deux fonctionnent.
Je sais que le format des short est identique entre Intel et
DEC. Je crois aussi que le format des float (mais non des
doubles) est très semblable aussi. En revanche, je ne crois
pas que le format DEC supporte les dénormalisés, et je ne
sais pas en ce qui concerne les Inf et les NaN. Mais il se
peut que ce ne soit pas important -- que de telles valeurs
ne t'intéressent pas. (Aussi, si DEC ne supporte pas les
dénormalisés, ça veut dire simplement qu'ils n'apparaîtront
pas.)
Que veut dire dénormalisé? Inf? Nan?
En ce qui concerne le troisième format : il y a tout à
parier qu'il suffit d'inverser les octets par rapport au
format Intel.
Comment on inverse les octets?
En somme, c'est à peu près IEEE sur un long avec l'ordre des
octets 3412. Et l'exposant est excès 128, plutôt que excès
126. On pourrait prèsqu'en faire une classe templatée.
A quoi correspond l'excès?
float IntelDataHandler::readFloat(std::ifstream & source ) const
{
unsigned char tmp[ 4 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),4))
throw Exception("Impossible de lire le fichier");
float * f = (float *)tmp;
float flt = *f;
Attention ici. Ce que tu as fait dépend beaucoup de la machine.
(J'en conclus, d'ailleurs, que tu travaille sur un Intel. Ça ne
marcherait pas sur un Sparc.)
Oui, je suis sur PC... J'imagine qu'AMD == Intel, c'est
l'architecture x86 qui détermine je suppose?
Cette fois-ci, j'ai testé mon code pour le format Intel --
en lisant sur un Sparc, qui n'a pas le même ordre d'octets.
Pour DEC, je me base sur le code que tu as posté, et pour
MIPS, je dévine un peu -- mais vu l'époque où est sorti le
processeur, IEEE me semble probable, et j'ai lu quelque part
que c'était grand-boutien.
Ca veut dire quoi grand-boutien?
Dans tous les cas ?
J'ai deux fichiers de test, un écrit avec des flottants DEC et
l'autre avec des flottants Intel. Les deux fonctionnent.
Je sais que le format des short est identique entre Intel et
DEC. Je crois aussi que le format des float (mais non des
doubles) est très semblable aussi. En revanche, je ne crois
pas que le format DEC supporte les dénormalisés, et je ne
sais pas en ce qui concerne les Inf et les NaN. Mais il se
peut que ce ne soit pas important -- que de telles valeurs
ne t'intéressent pas. (Aussi, si DEC ne supporte pas les
dénormalisés, ça veut dire simplement qu'ils n'apparaîtront
pas.)
Que veut dire dénormalisé? Inf? Nan?
En ce qui concerne le troisième format : il y a tout à
parier qu'il suffit d'inverser les octets par rapport au
format Intel.
Comment on inverse les octets?
En somme, c'est à peu près IEEE sur un long avec l'ordre des
octets 3412. Et l'exposant est excès 128, plutôt que excès
126. On pourrait prèsqu'en faire une classe templatée.
A quoi correspond l'excès?
float IntelDataHandler::readFloat(std::ifstream & source ) const
{
unsigned char tmp[ 4 ] ;
if (!source.read(reinterpret_cast<char*>(tmp),4))
throw Exception("Impossible de lire le fichier");
float * f = (float *)tmp;
float flt = *f;
Attention ici. Ce que tu as fait dépend beaucoup de la machine.
(J'en conclus, d'ailleurs, que tu travaille sur un Intel. Ça ne
marcherait pas sur un Sparc.)
Oui, je suis sur PC... J'imagine qu'AMD == Intel, c'est
l'architecture x86 qui détermine je suppose?
Cette fois-ci, j'ai testé mon code pour le format Intel --
en lisant sur un Sparc, qui n'a pas le même ordre d'octets.
Pour DEC, je me base sur le code que tu as posté, et pour
MIPS, je dévine un peu -- mais vu l'époque où est sorti le
processeur, IEEE me semble probable, et j'ai lu quelque part
que c'était grand-boutien.
Ca veut dire quoi grand-boutien?
Aujourd'hui, les architectures à une multiple de 8 bits, avec
les entiers négatifs en compléments à deux et les flottants en
format IEEE dominent -- autant que je sache, il n'y a plus que
l'Unisys 2200, et les gros IBM pour les flottants, qui s'en
écartent. Mais historiquement, ce n'était pas le cas. Surtout
pour les représentations flottantes. La représentation DEC ici
en est un exemple. (Encore que je me démande... Les VAX ont
répris le format des PDP-11, je crois ; est-ce que les Alpha ont
répris le format des VAX ?)
Sur un Intel, tu verras apparaître "1234", sur un Sparc
"4321", et sur un PDP-11 (si tu arrives à en trouver un)
"3412".
Aujourd'hui, les architectures à une multiple de 8 bits, avec
les entiers négatifs en compléments à deux et les flottants en
format IEEE dominent -- autant que je sache, il n'y a plus que
l'Unisys 2200, et les gros IBM pour les flottants, qui s'en
écartent. Mais historiquement, ce n'était pas le cas. Surtout
pour les représentations flottantes. La représentation DEC ici
en est un exemple. (Encore que je me démande... Les VAX ont
répris le format des PDP-11, je crois ; est-ce que les Alpha ont
répris le format des VAX ?)
Sur un Intel, tu verras apparaître "1234", sur un Sparc
"4321", et sur un PDP-11 (si tu arrives à en trouver un)
"3412".
Aujourd'hui, les architectures à une multiple de 8 bits, avec
les entiers négatifs en compléments à deux et les flottants en
format IEEE dominent -- autant que je sache, il n'y a plus que
l'Unisys 2200, et les gros IBM pour les flottants, qui s'en
écartent. Mais historiquement, ce n'était pas le cas. Surtout
pour les représentations flottantes. La représentation DEC ici
en est un exemple. (Encore que je me démande... Les VAX ont
répris le format des PDP-11, je crois ; est-ce que les Alpha ont
répris le format des VAX ?)
Sur un Intel, tu verras apparaître "1234", sur un Sparc
"4321", et sur un PDP-11 (si tu arrives à en trouver un)
"3412".