Numpy: np.left_shift et np.right_shift échouent sur les types scalaires np.uint64 (Trac # 1931)

Créé le 20 oct. 2012  ·  7Commentaires  ·  Source: numpy/numpy

_Billet original http://projects.scipy.org/numpy/ticket/1931 le 10/08/2011 par l'utilisateur trac tlatorre, attribué à 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

Commentaire le plus utile

La solution la plus simple consiste à utiliser un entier non signé pour l'équipe:

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

Comme @charris l'a mentionné ci-dessus, le problème réside dans la façon dont les dtypes sont uniformisés. Ce n'est pas si simple de corriger génériquement (voir aussi # 5668), bien que peut-être que les opérateurs de décalage puissent être à casse spéciale. (PR bienvenu, cependant, comme dit, ce n'est pas trivial, mais nécessite une bonne compréhension de la façon dont les boucles internes dans ufucs sont décidées ...).

Tous les 7 commentaires

_ @ charris écrit le

Cela est dû au fait que le numéro de décalage est converti en type signé et qu'il n'y a pas de type entier signé suffisamment grand pour contenir un uint64. Les opérateurs de décalage doivent avoir un boîtier spécial, ils peuvent également échouer sur Intel car le matériel masque les bits inutiles, c'est-à-dire que pour int32, seuls les 5 bits inférieurs sont examinés.

_trac user parejkoj rédigé le 2012-07-27_

J'ai pu coder autour de cela avec le lambda suivant:

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

Cela fonctionne, mais ce n'est pas idéal. Obtenir cela corrigé dans numpy serait très utile.

c'est cinq ans plus tard ... n'est-ce pas une question importante? les entiers non signés ne doivent avoir aucune ambiguïté sur les décalages.

La solution la plus simple consiste à utiliser un entier non signé pour l'équipe:

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

Comme @charris l'a mentionné ci-dessus, le problème réside dans la façon dont les dtypes sont uniformisés. Ce n'est pas si simple de corriger génériquement (voir aussi # 5668), bien que peut-être que les opérateurs de décalage puissent être à casse spéciale. (PR bienvenu, cependant, comme dit, ce n'est pas trivial, mais nécessite une bonne compréhension de la façon dont les boucles internes dans ufucs sont décidées ...).

La solution la plus simple consiste à utiliser un entier non signé pour l'équipe:

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

... qui fonctionne si vous savez que vous utilisez des entiers numpy, mais si vous utilisez du code générique (en particulier quelque chose qui a déjà été écrit dans un autre module et est hors de votre contrôle) comme

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

alors vous ne pouvez pas le faire fonctionner à la fois sur les entiers Python réguliers et les types np.uint64.

Je n'essaie pas de dire que c'est trivial (bien au-dessus de mes compétences) mais je pense que cela devrait être une priorité élevée.

@ jason-s - Je suis d'accord que le problème est très ennuyeux ... Malheureusement, il n'y a pas beaucoup d'entre nous qui connaissent assez bien le fonctionnement des ufuncs en interne ...

On pourrait peut-être au moins des scalaires de cas spéciaux pour le changement de méthode, au lieu de s'appuyer sur la machinerie générale ufunc. @charris : était-ce ce que vous aviez en tête (si vous vous en souvenez après 6 ans ;-).

Voir aussi # 8002.

Personnellement, si nous pouvions tout refaire, je préférerais refaire tout le casting / coercition pour que le casting numpy se comporte essentiellement comme un casting C, et suit l'esprit du casting C pour les cas qui n'existent pas en C.Le casting numpy les règles sont un peu bizarres et parfois déroutantes (par exemple, la conversion de uint64 + int64 en float64 ). Mais nous en avons beaucoup discuté sur la liste, cela semble difficile à changer.

Quand je rencontre des situations comme celle-ci (voir mon commentaire là-bas), j'emballe simplement chaque valeur dans np.uint64 .

Cette page vous a été utile?
0 / 5 - 0 notes