Numpy: np.left_shift и np.right_shift не работают на скалярных типах np.uint64 (Trac # 1931)

Созданный на 20 окт. 2012  ·  7Комментарии  ·  Источник: numpy/numpy

_Оригинальный билет http://projects.scipy.org/numpy/ticket/1931 от 10 августа 2011 г. пользователем trac tlatorre, назначен 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

Самый полезный комментарий

Более простой способ - использовать для сдвига целое число без знака:

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

Как упоминалось выше в @charris , проблема в том, как dtypes унифицированы. Это не так просто исправить в общем (см. Также # 5668), хотя, возможно, операторы сдвига могут быть в специальном регистре. (PR приветствуется, хотя, как уже было сказано, это не тривиально, но требует четкого понимания того, как определяются внутренние циклы в ufucs ...).

Все 7 Комментарий

_ @ charris написал (а) 2011-08-13_

Это связано с тем, что номер смены преобразуется как знаковый тип, и нет целочисленного типа со знаком, достаточно большого для хранения uint64. Операторы сдвига должны иметь специальный корпус, они также могут давать сбой на Intel, потому что оборудование маскирует ненужные биты, то есть для int32 проверяются только младшие 5 бит.

Пользователь _trac parejkoj написал (а) 2012-07-27_

Мне удалось обойти это с помощью следующей лямбды:

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

Это работает, но не идеально. Исправить это в numpy было бы очень полезно.

это пять лет спустя ... разве это не важный вопрос? Целые числа без знака не должны иметь двусмысленности в отношении сдвигов.

Более простой способ - использовать для сдвига целое число без знака:

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

Как упоминалось выше в @charris , проблема в том, как dtypes унифицированы. Это не так просто исправить в общем (см. Также # 5668), хотя, возможно, операторы сдвига могут быть в специальном регистре. (PR приветствуется, хотя, как уже было сказано, это не тривиально, но требует четкого понимания того, как определяются внутренние циклы в ufucs ...).

Более простой способ - использовать для сдвига целое число без знака:

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

... который работает, если вы знаете, что работаете с numpy целыми числами, но если вы используете общий код (особенно то, что уже было написано в другом модуле и находится вне вашего контроля), например

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

тогда вы не сможете заставить его работать как с обычными целыми числами Python, так и с типами np.uint64.

Я не пытаюсь утверждать, что это тривиально (намного выше моих навыков), но я считаю, что это должно быть приоритетом.

@ jason-s - Я согласен, что проблема очень раздражает ... К сожалению, не многие из нас достаточно хорошо разбираются в том, как работают внутренние функции ufunc ...

Возможно, можно было бы, по крайней мере, использовать скаляры для особого случая для сдвига в методе, вместо того, чтобы полагаться на общий механизм ufunc. @charris : это то, что ты имел в виду (если ты помнишь это через 6 лет ;-).

См. Также # 8002.

Лично, если бы мы могли сделать все заново, я бы предпочел переделать все приведение / принуждение, чтобы приведение numpy по существу вело себя как приведение C и следовало духу C-приведения для случаев, которых нет в C. правила довольно странные и иногда запутанные (например, преобразование uint64 + int64 в float64 ). Но мы много обсуждали это в списке, это сложно изменить.

Когда я сталкиваюсь с подобными ситуациями (см. Мой комментарий), я просто заключаю каждое значение в np.uint64 .

Была ли эта страница полезной?
0 / 5 - 0 рейтинги