Numpy: np.left_shift y np.right_shift fallan en los tipos escalares np.uint64 (Trac # 1931)

Creado en 20 oct. 2012  ·  7Comentarios  ·  Fuente: numpy/numpy

_ Ticket original http://projects.scipy.org/numpy/ticket/1931 el 2011-08-10 por el usuario de trac tlatorre, asignado a unknown._

>>> np.uint64(5) << 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: ufunc 'left_shift' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule 'safe'
>>> np.uint64(5) >> 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: ufunc 'right_shift' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule 'safe'
00 - Bug numpy.core

Comentario más útil

La solución alternativa más sencilla es utilizar un número entero sin signo para el turno:

np.uint64(5) << np.uint64(1)

Como @charris mencionó anteriormente, el problema está en la forma en que los dtypes se uniforman. No es tan trivial arreglarlo genéricamente (ver también # 5668), aunque quizás los operadores de turno pueden ser especiales. (PR bienvenido, aunque, como se dijo, esto no es trivial, pero requiere una comprensión justa de cómo se deciden los bucles internos en ufucs ...).

Todos 7 comentarios

_ @ charris escribió el

Esto se debe a que el número de turno se convierte como un tipo con signo y no hay un tipo de entero con signo lo suficientemente grande como para contener un uint64. Los operadores de turno deben estar en mayúsculas especiales, también pueden fallar en Intel porque el hardware enmascara los bits innecesarios, es decir, para int32 solo se miran los 5 bits inferiores.

_trac usuario parejkoj escribió el 2012-07-27_

Pude codificar esto con la siguiente lambda:

lshift = lambda x,s: np.uint64(x)*np.uint64(2**s)

Esto funciona, pero no es ideal. Resolver esto en numpy sería muy útil.

Han pasado cinco años ... ¿no es este un tema importante? los enteros sin signo no deben tener ambigüedad sobre los cambios.

La solución alternativa más sencilla es utilizar un número entero sin signo para el turno:

np.uint64(5) << np.uint64(1)

Como @charris mencionó anteriormente, el problema está en la forma en que los dtypes se uniforman. No es tan trivial arreglarlo genéricamente (ver también # 5668), aunque quizás los operadores de turno pueden ser especiales. (PR bienvenido, aunque, como se dijo, esto no es trivial, pero requiere una comprensión justa de cómo se deciden los bucles internos en ufucs ...).

La solución alternativa más sencilla es utilizar un número entero sin signo para el turno:

np.uint64 (5) << np.uint64 (1)

... que funciona si sabe que está operando con números enteros, pero si está usando código genérico (especialmente algo que ya se ha escrito en otro módulo y está fuera de su control) como

def f(x):
    return x | (x >> 1)

entonces no puede hacer que funcione tanto en enteros regulares de Python como en tipos np.uint64.

No estoy tratando de decir que esto es trivial (muy por encima de mi conjunto de habilidades), pero creo que debería ser una alta prioridad.

@ jason-s - Estoy de acuerdo en que el problema es muy molesto ... Lamentablemente, no muchos de nosotros somos lo suficientemente versados ​​en cómo funcionan internamente los ufuncs ...

Quizás se podrían al menos escalares de casos especiales para el cambio en el método, sin embargo, en lugar de depender de la maquinaria ufunc general. @charris : era esto lo que tenías en mente (si puedes recordar eso después de 6 años ;-).

Vea también # 8002.

Personalmente, si pudiéramos hacer todo de nuevo, preferiría rehacer todo el casting / coerción para que el casting numpy se comporte esencialmente como casting C, y siga el espíritu del casting C para casos que no existen en C. las reglas son un poco raras ya veces confusas (por ejemplo, la conversión de uint64 + int64 a float64 ). Pero hemos hablado mucho de esto en la lista, parece difícil de cambiar.

Cuando me encuentro con situaciones como esta (vea mi comentario allí), simplemente envuelvo cada valor en np.uint64 .

¿Fue útil esta página
0 / 5 - 0 calificaciones