Skip to content

Commit

Permalink
Closes Bears-R-Us#4098: upgrade to numpy 2.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ajpotts committed Feb 21, 2025
1 parent 5437236 commit 3fc3251
Show file tree
Hide file tree
Showing 17 changed files with 3,207 additions and 278 deletions.
3 changes: 2 additions & 1 deletion arkouda-env-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ channels:
- defaults
dependencies:
- python>=3.9,<3.12.4 # minimum 3.9
- numpy>=1.24.1,<2.0
# - numpy>=1.24.1,<2.0
- numpy>=2.0
- pandas>=1.4.0,!=2.2.0
- pyzmq>=20.0.0
- tabulate
Expand Down
17 changes: 0 additions & 17 deletions arkouda/numpy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,14 @@
# flake8: noqa
from numpy import ( # noqa
NAN,
NINF,
NZERO,
PINF,
PZERO,
DataSource,
False_,
Inf,
Infinity,
NaN,
ScalarType,
True_,
base_repr,
binary_repr,
byte,
bytes_,
cdouble,
cfloat,
clongdouble,
clongfloat,
compat,
csingle,
datetime64,
Expand All @@ -28,30 +17,24 @@
euler_gamma,
finfo,
flexible,
float_,
floating,
format_float_positional,
format_float_scientific,
half,
iinfo,
inexact,
inf,
infty,
intc,
intp,
isscalar,
issctype,
issubdtype,
longdouble,
longfloat,
longlong,
maximum_sctype,
nan,
number,
pi,
promote_types,
sctypeDict,
sctypes,
short,
signedinteger,
single,
Expand Down
22 changes: 22 additions & 0 deletions arkouda/numpy/_numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,28 @@ def _merge_where(new_pda, where, ret):
return new_pda


def can_cast(from_, to) -> ak_bool:
from arkouda.util import is_int
from arkouda.numpy.dtypes import uint64 as ak_unit64
from arkouda.numpy.dtypes import _is_dtype_in_union
from arkouda.numpy.dtypes import isSupportedInt
from arkouda.numpy.dtypes import dtype as ak_dtype

if isSupportedInt(from_) and (from_ < 2**64) and (from_ >= 0) and (to == ak_dtype(ak_uint64)):
print("CASE 2")
return True

if (np.isscalar(from_) or _is_dtype_in_union(from_, numeric_scalars)) and not isinstance(
from_, (int, float, complex)
):
print("CASE1")
return np.can_cast(from_, to)

print("CASE3")

return False


@typechecked
def cast(
pda: Union[pdarray, Strings, Categorical], # type: ignore
Expand Down
31 changes: 26 additions & 5 deletions arkouda/numpy/dtypes/dtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,18 @@ def dtype(x):
return bigint()
if isinstance(x, str) and x in ["Strings"]:
return np.dtype(np.str_)
else:
return np.dtype(x)
if isinstance(x, int):
if 0 < x and x < 2**64:
return np.dtype(np.uint64)
elif x >= 2**64:
return bigint()
else:
return np.dtype(np.int64)
if isinstance(x, float):
return np.dtype(np.float64)
if isinstance(x, bool):
return np.dtype(np.bool)
return np.dtype(x)


def _is_dtype_in_union(dtype, union_type) -> builtins.bool:
Expand Down Expand Up @@ -284,7 +294,18 @@ def __repr__(self) -> str:
# missing full support for: float32, int32, int16, int8, uint32, uint16, complex64, complex128
# ARKOUDA_SUPPORTED_DTYPES = frozenset([member.value for _, member in DType.__members__.items()])
ARKOUDA_SUPPORTED_DTYPES = frozenset(
["bool_", "float", "float64", "int", "int64", "uint", "uint64", "uint8", "bigint", "str"]
[
"bool_",
"float",
"float64",
"int",
"int64",
"uint",
"uint64",
"uint8",
"bigint",
"str",
]
)

DTypes = frozenset([member.value for _, member in DType.__members__.items()])
Expand Down Expand Up @@ -347,9 +368,9 @@ def resolve_scalar_dtype(val: object) -> str:
else:
return "int64"
# Python float or np.float*
elif isinstance(val, float) or (hasattr(val, "dtype") and cast(np.float_, val).dtype.kind == "f"):
elif isinstance(val, float) or (hasattr(val, "dtype") and cast(np.float64, val).dtype.kind == "f"):
return "float64"
elif isinstance(val, complex) or (hasattr(val, "dtype") and cast(np.float_, val).dtype.kind == "c"):
elif isinstance(val, complex) or (hasattr(val, "dtype") and cast(np.float64, val).dtype.kind == "c"):
return "float64" # TODO: actually support complex values in the backend
elif isinstance(val, builtins.str) or isinstance(val, np.str_):
return "str"
Expand Down
4 changes: 2 additions & 2 deletions arkouda/numpy/exceptions/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from numpy import RankWarning, TooHardError
# from numpy import RankWarning, TooHardError

__all__ = ["RankWarning", "TooHardError"]
# __all__ = ["RankWarning", "TooHardError"]
28 changes: 14 additions & 14 deletions arkouda/numpy/lib/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# flake8: noqa
from numpy import (
RankWarning,
add_docstring,
add_newdoc,
deprecate,
deprecate_with_doc,
disp,
issubclass_,
# RankWarning,
# add_docstring,
# add_newdoc,
# deprecate,
# deprecate_with_doc,
# disp,
# issubclass_,
issubdtype,
polynomial,
typename,
Expand All @@ -16,14 +16,14 @@
from arkouda.numpy.lib.emath import *

__all__ = [
"RankWarning",
"add_docstring",
"add_newdoc",
"deprecate",
"deprecate_with_doc",
"disp",
# "RankWarning",
# "add_docstring",
# "add_newdoc",
# "deprecate",
# "deprecate_with_doc",
# "disp",
"emath",
"issubclass_",
# "issubclass_",
"issubdtype",
"polynomial",
"typename",
Expand Down
6 changes: 3 additions & 3 deletions arkouda/numpy/rec/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from numpy import format_parser

__all__ = ["format_parser"]
# from numpy import format_parser
#
# __all__ = ["format_parser"]
71 changes: 55 additions & 16 deletions arkouda/pdarrayclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from typeguard import typechecked

from arkouda.client import generic_msg
from arkouda.dtypes import uint64 as ak_uint64
from arkouda.infoclass import information, pretty_print_information
from arkouda.logger import getArkoudaLogger
from arkouda.numpy.dtypes import (
Expand All @@ -20,9 +21,15 @@
bigint,
)
from arkouda.numpy.dtypes import bool_ as akbool
from arkouda.numpy.dtypes import bool_scalars, dtype
from arkouda.numpy.dtypes import (
bool_scalars,
dtype,
)
from arkouda.numpy.dtypes import float64 as akfloat64
from arkouda.numpy.dtypes import get_byteorder, get_server_byteorder
from arkouda.numpy.dtypes import (
get_byteorder,
get_server_byteorder,
)
from arkouda.numpy.dtypes import int64 as akint64
from arkouda.numpy.dtypes import (
int_scalars,
Expand Down Expand Up @@ -166,6 +173,14 @@ def unescape(s):
if mydtype == akstr_:
# String value will always be surrounded with double quotes, so remove them
return mydtype.type(unescape(value[1:-1]))

if mydtype == ak_uint64:
if get_server_byteorder() == "little":
if value.startswith("-"):
value = value.strip("-")
uint_value = np.iinfo(np.uint64).max - ak_uint64(value) + 1
return mydtype.type(uint_value)
return mydtype.type(value)
return mydtype.type(value)
except Exception:
raise ValueError(f"unsupported value from server {mydtype.name} {value}")
Expand Down Expand Up @@ -571,11 +586,33 @@ def _binop(self, other: pdarray, op: str) -> pdarray:
# pdarray binop scalar
# If scalar cannot be safely cast, server will infer the return dtype
dt = resolve_scalar_dtype(other)
if self.dtype != bigint and np.can_cast(other, self.dtype):

from arkouda.numpy._numeric import can_cast as ak_can_cast

print("\n**\ndt: ", dt)
print("other: ", other)
print("self.dtype: ", self.dtype)
print(
"ak_can_cast(other, self.dtype): ",
ak_can_cast(other, self.dtype),
)

from arkouda.dtypes import int64 as ak_int64
from arkouda.dtypes import float64 as ak_float64

if self.dtype == ak_uint64 and dtype(other) == ak_int64:
dt = "float64"
other = ak_float64(other)
print("new dt: ", dt)
print("new other: ", other)
elif self.dtype != bigint and ak_can_cast(other, self.dtype):
# If scalar can be losslessly cast to array dtype,
# do the cast so that return array will have same dtype
dt = self.dtype.name
other = self.dtype.type(other)
print("new dt: ", dt)
print("new other: ", other)

if dt not in DTypes:
raise TypeError(f"Unhandled scalar type: {other} ({type(other)})")
repMsg = generic_msg(
Expand Down Expand Up @@ -616,7 +653,9 @@ def _r_binop(self, other: pdarray, op: str) -> pdarray:
# pdarray binop scalar
# If scalar cannot be safely cast, server will infer the return dtype
dt = resolve_scalar_dtype(other)
if self.dtype != bigint and np.can_cast(other, self.dtype):
from arkouda.numpy._numeric import can_cast as ak_can_cast

if self.dtype != bigint and ak_can_cast(other, self.dtype):
# If scalar can be losslessly cast to array dtype,
# do the cast so that return array will have same dtype
dt = self.dtype.name
Expand Down Expand Up @@ -894,6 +933,7 @@ def __iter__(self):
# overload a[] to treat like list
def __getitem__(self, key):
if self.ndim == 1 and np.isscalar(key) and (resolve_scalar_dtype(key) in ["int64", "uint64"]):
print("\n\nCASE1\n\n")
orig_key = key
if key < 0:
# Interpret negative key as offset from end of array
Expand Down Expand Up @@ -4131,31 +4171,30 @@ def fmod(dividend: Union[pdarray, numeric_scalars], divisor: Union[pdarray, nume
)
# TODO: handle shape broadcasting for multidimensional arrays

# The code below creates a command string for fmod2vv, fmod2vs or fmod2sv.

# The code below creates a command string for fmod2vv, fmod2vs or fmod2sv.

if isinstance(dividend, pdarray) and isinstance(divisor, pdarray) :
if isinstance(dividend, pdarray) and isinstance(divisor, pdarray):
cmdstring = f"fmod2vv<{dividend.dtype},{dividend.ndim},{divisor.dtype}>"

elif isinstance(dividend, pdarray) and not (isinstance(divisor, pdarray)) :
if resolve_scalar_dtype(divisor) in ['float64', 'int64', 'uint64', 'bool'] :
acmd = 'fmod2vs_'+resolve_scalar_dtype(divisor)
else : # this condition *should* be impossible because of the isSupportedNumber check
elif isinstance(dividend, pdarray) and not (isinstance(divisor, pdarray)):
if resolve_scalar_dtype(divisor) in ["float64", "int64", "uint64", "bool"]:
acmd = "fmod2vs_" + resolve_scalar_dtype(divisor)
else: # this condition *should* be impossible because of the isSupportedNumber check
raise TypeError(f"Scalar divisor type {resolve_scalar_dtype(divisor)} not allowed in fmod")
cmdstring = f"{acmd}<{dividend.dtype},{dividend.ndim}>"

elif not (isinstance(dividend, pdarray) and isinstance(divisor, pdarray)) :
if resolve_scalar_dtype(dividend) in ['float64', 'int64', 'uint64', 'bool'] :
acmd = 'fmod2sv_'+resolve_scalar_dtype(dividend)
else : # this condition *should* be impossible because of the isSupportedNumber check
elif not (isinstance(dividend, pdarray) and isinstance(divisor, pdarray)):
if resolve_scalar_dtype(dividend) in ["float64", "int64", "uint64", "bool"]:
acmd = "fmod2sv_" + resolve_scalar_dtype(dividend)
else: # this condition *should* be impossible because of the isSupportedNumber check
raise TypeError(f"Scalar dividend type {resolve_scalar_dtype(dividend)} not allowed in fmod")
cmdstring = f"{acmd}<{divisor.dtype},{divisor.ndim}>" # type: ignore[union-attr]

else:
m = mod(dividend, divisor)
return _create_scalar_array(m)

# We reach here if this was any case other than scalar & scalar
# We reach here if this was any case other than scalar & scalar

return create_pdarray(
cast(
Expand Down
13 changes: 12 additions & 1 deletion arkouda/pdarraycreation.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,10 @@ def array(
# early out if we would have more uint arrays than can fit in max_bits
early_out = (max_bits // 64) + (max_bits % 64 != 0) if max_bits != -1 else float("inf")
while any(a != 0) and len(uint_arrays) < early_out:
low, a = a % 2**64, a // 2**64
if isinstance(a, np.ndarray):
low, a = a.astype("O") % 2**64, a.astype("O") // 2**64
else:
low, a = a % 2**64, a // 2**64
uint_arrays.append(array(np.array(low, dtype=np.uint), dtype=akuint64))
return bigint_from_uint_arrays(uint_arrays[::-1], max_bits=max_bits)
except TypeError:
Expand All @@ -300,6 +303,14 @@ def array(
# than our numpy array we need to swap to match since the server expects
# native endian bytes
aview = _array_memview(a_)

if get_server_byteorder() == "big":
if a.dtype.byteorder == "<":
a = a.view(a.dtype.newbyteorder("S")).byteswap()
else:
if a.dtype.byteorder == ">":
a = a.view(a.dtype.newbyteorder("S")).byteswap()

rep_msg = generic_msg(
cmd=f"array<{a_.dtype.name},{ndim}>",
args={"dtype": a_.dtype.name, "shape": tuple(a_.shape), "seg_string": False},
Expand Down
2 changes: 1 addition & 1 deletion arkouda/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ def convert_bytes(nbytes, unit="B"):


def is_numeric(
arry: Union[pdarray, Strings, Categorical, "Series", "Index"] # noqa: F821
arry: Union[pdarray, Strings, Categorical, "Series", "Index"], # noqa: F821
) -> builtins.bool:
"""
Check if the dtype of the given array is numeric.
Expand Down
Loading

0 comments on commit 3fc3251

Please sign in to comment.