Tiene esta aplicación de frexp cualquier comportamiento indefinido?

votos
0

He construido una versión personalizada de frexp:

auto frexp(float f) noexcept
{
    static_assert(std::numeric_limits<float>::is_iec559);

    uint32_t u;
    std::memcpy(&u, &f, sizeof(float)); // well defined bit transformation from float to int

    int exp = ((u >> 23) & 0xff) - 126; // extract the 8 bits of the exponent (it has an offset of 126)

    // divide by 2^exp (leaving mantissa intact while placing 0 into the exponent)
    u &= ~(0xff << 23); // zero out the exponent bits
    u |= 126 << 23; // place 126 into exponent bits (representing 0)

    std::memcpy(&f, &u, sizeof(float)); // copy back to f
    return std::make_pair(exp, f);
}

Al marcar is_iec559me estoy asegurando de que floatfulfills

los requisitos de la norma IEC 559 (754 IEEE) estándar.

Mi pregunta es: ¿Esto significa que las operaciones de bits que estoy haciendo están bien definidos y hacen lo que yo quiero? Si no es así, ¿hay alguna manera de solucionarlo?

Lo probé por algunos valores aleatorios y parece ser correcta, al menos en Windows 10 compilado con msvc y en wandbox . Tenga en cuenta sin embargo, que (a propósito) yo no estoy manejando los casos extremos de 0, NaNy inf.

Si alguien se pregunta por qué estoy haciendo esto: En los puntos de referencia que encontré que esta versión de frexpes hasta 15 veces más rápido que std::frexpen Windows 10. No he probado otras plataformas todavía. Pero yo quiero estar seguro de que esto no sólo trabaja por coincidentes y frenos puedan en el futuro.

Publicado el 09/10/2019 a las 17:58
fuente por usuario
En otros idiomas...                            


1 respuestas

votos
0

"¿Significa esto que las operaciones de bits que estoy haciendo están bien definidos ..."

El TL; DR ;, por la definición estricta de "bien definido": no .

Sus suposiciones son probablemente correcta , pero no bien definido , porque no hay garantías sobre la anchura de bits, o la ejecución de float. Desde § 3.9.1:

hay tres tipos de punto flotante: float, double y long double. El tipo doble proporciona al menos tanta precisión como flotador, y el tipo proporciona una larga doble al menos tanta precisión como doble. El conjunto de valores del flotador tipo es un subconjunto del conjunto de valores del tipo doble; el conjunto de valores del tipo es el doble de un subconjunto del conjunto de valores del tipo de largo doble. La representación de valores de tipos de punto flotante es definido por la implementación.

La is_iec559cláusula solamente califica con:

Verdadero si y sólo si se adhiere el tipo a la norma IEC 559

Si un genio literal que escribió un terrible compilador, e hizo float= binary16 , double= binary32 , y long double= binary64 , e hizo is_iec559cierto para todos los tipos, todavía se adherirá a la norma.

¿Eso significa que puedo extraer exponente y mantisa de una manera bien definida?

El TL; DR ;, por las garantías limitadas del C ++ estándar: no .

Supongamos que usted utiliza float32_ty is_iec559es verdadera, y lógicamente deducidas de todas las reglas que sólo podría ser binary32 con ninguna representación trampa, y argumentó correctamente que memcpyes un bien definido para la conversión entre tipos aritméticas de la misma anchura, y no se romperá estricta aliasing. Incluso con todos esos supuestos, el comportamiento podría ser bien definido , pero es sólo probable y no garantiza que se puede extraer la mantisa de esta manera.

El estándar IEEE 754 y de 2 complemento respecto codificaciones cadena de bits , y el comportamiento de los memcpyque se describe el uso de bytes . Si bien es plausible suponer la cadena de bits de uint32_ty float32_tse codifica de la misma manera (por ejemplo mismo orden de bits), no hay garantía en la norma para eso. Si las cadenas de bits se almacenan de manera diferente y que cambian y enmascaran la representación entera copiado para obtener la mantisa, la respuesta será incorrecta, a pesar de memcpyser un comportamiento bien definido.

Como se mencionó en los comentarios, endianess podría ser un problema. ¿Alguien sabe?

Al menos un par de arquitecturas han utilizado diferentes endianness de registros de coma flotante y registros enteros. El mismo enlace dice que a excepción de pequeños procesadores integrados, esto no es una preocupación. Confío en Wikipedia en su totalidad para todos los temas y se niegan a hacer ninguna investigación ulterior.

Respondida el 16/12/2019 a las 22:55
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more