Skip to content

Commit

Permalink
Merge pull request #1624 from braingram/eslavich-simpler-integer-type
Browse files Browse the repository at this point in the history
Eslavich simpler integer type
  • Loading branch information
braingram authored Sep 29, 2023
2 parents a722099 + 68a2577 commit 1201a46
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 70 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ The ASDF Standard is at v1.6.0
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- Add support for python 3.12 [#1641]
- Move IntegerType to converter and drop cache of converted values. [#1527]

2.15.1 (2023-08-07)
-------------------
Expand Down
20 changes: 0 additions & 20 deletions asdf/_tests/tags/core/tests/test_integer.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,26 +58,6 @@ def test_integer_storage(tmpdir, inline):
assert rf.tree["integer"]["string"] == str(value)


def test_integer_storage_duplication(tmpdir):
tmpfile = str(tmpdir.join("integer.asdf"))

random.seed(0)
value = random.getrandbits(1000)
tree = {"integer1": IntegerType(value), "integer2": IntegerType(value)}

with asdf.AsdfFile(tree) as af:
af.write_to(tmpfile)

with asdf.open(tmpfile, _force_raw_types=True) as rf:
assert len(rf._blocks.blocks) == 1
assert rf.tree["integer1"]["words"]["source"] == 0
assert rf.tree["integer2"]["words"]["source"] == 0

with asdf.open(tmpfile) as aa:
assert aa.tree["integer1"] == value
assert aa.tree["integer2"] == value


def test_integer_conversion():
random.seed(0)
value = random.getrandbits(1000)
Expand Down
45 changes: 45 additions & 0 deletions asdf/core/_converters/integer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import numpy as np

from asdf.extension import Converter


class IntegerConverter(Converter):
tags = [
"tag:stsci.edu:asdf/core/integer-1.0.0",
"tag:stsci.edu:asdf/core/integer-1.1.0",
]

types = ["asdf.tags.core.integer.IntegerType"]

def to_yaml_tree(self, obj, tag, ctx):
abs_value = int(np.abs(obj._value))

# pack integer value into 32-bit words
words = []
value = abs_value
while value > 0:
words.append(value & 0xFFFFFFFF)
value >>= 32

array = np.array(words, dtype=np.uint32)

tree = {}
ctx.set_array_storage(array, obj._storage)
tree["words"] = array
tree["sign"] = obj._sign
tree["string"] = str(int(obj._value))

return tree

def from_yaml_tree(self, node, tag, ctx):
from asdf.tags.core.integer import IntegerType

value = 0
for x in node["words"][::-1]:
value <<= 32
value |= int(x)

if node["sign"] == "-":
value = -value

return IntegerType(value)
2 changes: 2 additions & 0 deletions asdf/core/_extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from ._converters.complex import ComplexConverter
from ._converters.constant import ConstantConverter
from ._converters.external_reference import ExternalArrayReferenceConverter
from ._converters.integer import IntegerConverter
from ._converters.ndarray import NDArrayConverter
from ._converters.reference import ReferenceConverter
from ._converters.tree import (
Expand All @@ -21,6 +22,7 @@
AsdfObjectConverter(),
ExtensionMetadataConverter(),
HistoryEntryConverter(),
IntegerConverter(),
SoftwareConverter(),
SubclassMetadataConverter(),
ReferenceConverter(),
Expand Down
51 changes: 1 addition & 50 deletions asdf/tags/core/integer.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
from numbers import Integral

import numpy as np

from asdf import _types


class IntegerType(_types._AsdfType):
class IntegerType:
"""
Enables the storage of arbitrarily large integer values
Expand Down Expand Up @@ -42,12 +38,6 @@ class IntegerType(_types._AsdfType):
... assert aa['largeval'] == largeval
"""

name = "core/integer"
version = "1.0.0"
supported_versions = {"1.0.0", "1.1.0"}

_value_cache = {}

def __init__(self, value, storage_type="internal"):
if storage_type not in ["internal", "inline"]:
msg = f"storage_type '{storage_type}' is not a recognized storage type"
Expand All @@ -56,45 +46,6 @@ def __init__(self, value, storage_type="internal"):
self._sign = "-" if value < 0 else "+"
self._storage = storage_type

@classmethod
def to_tree(cls, node, ctx):
abs_value = int(np.abs(node._value))

# If the same value has already been stored, reuse the array
if abs_value in cls._value_cache:
array = cls._value_cache[abs_value]
else:
# pack integer value into 32-bit words
words = []
value = abs_value
while value > 0:
words.append(value & 0xFFFFFFFF)
value >>= 32

array = np.array(words, dtype=np.uint32)
if node._storage == "internal":
cls._value_cache[abs_value] = array

tree = {}
ctx.set_array_storage(array, node._storage)
tree["words"] = array
tree["sign"] = node._sign
tree["string"] = str(int(node._value))

return tree

@classmethod
def from_tree(cls, tree, ctx):
value = 0
for x in tree["words"][::-1]:
value <<= 32
value |= int(x)

if tree["sign"] == "-":
value = -value

return cls(value)

def __int__(self):
return int(self._value)

Expand Down

0 comments on commit 1201a46

Please sign in to comment.