haliax 1.4.dev322__tar.gz → 1.4.dev324__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {haliax-1.4.dev322 → haliax-1.4.dev324}/PKG-INFO +1 -2
- haliax-1.4.dev324/src/haliax/__about__.py +1 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/_src/state_dict.py +45 -29
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/core.py +3 -1
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/jax_utils.py +1 -1
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/nn/scan.py +6 -3
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/state_dict.py +16 -1
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/types.py +12 -1
- haliax-1.4.dev322/src/haliax/__about__.py +0 -1
- {haliax-1.4.dev322 → haliax-1.4.dev324}/.coveragerc +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/.flake8 +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/.github/workflows/publish_dev.yaml +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/.github/workflows/run_pre_commit.yaml +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/.github/workflows/run_quick_levanter_tests.yaml +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/.github/workflows/run_tests.yaml +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/.gitignore +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/.pre-commit-config.yaml +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/.readthedocs.yaml +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/CONTRIBUTING.md +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/LICENSE +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/README.md +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/api.md +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/broadcasting.md +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/cheatsheet.md +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/css/material.css +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/css/mkdocstrings.css +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/faq.md +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/figures/data_parallel_mesh.png +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/figures/data_parallel_mesh_replicated.png +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/figures/device_mesh_1d.png +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/figures/device_mesh_1d_zero.png +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/figures/device_mesh_2d.png +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/figures/device_mesh_2d_batch_partitioned.png +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/figures/device_mesh_2d_data_replicated.png +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/figures/device_mesh_2d_data_replicated_mlp_partitioned.png +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/figures/device_mesh_2d_intermediate_fully_partitioned.png +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/figures/device_mesh_2d_zero.png +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/fp8.md +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/hof.md +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/index.md +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/indexing.md +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/matmul.md +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/nn.md +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/partitioning.md +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/rearrange.ipynb +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/rearrange.md +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/requirements.txt +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/state-dict.md +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/docs/tutorial.md +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/mkdocs.yml +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/pyproject.toml +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/__init__.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/_src/__init__.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/_src/compile_utils.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/_src/dot.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/_src/einsum.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/_src/fp8.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/_src/parsing.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/_src/rearrange.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/_src/util.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/axis.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/debug.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/hof.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/nn/__init__.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/nn/activations.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/nn/attention.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/nn/conv.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/nn/dropout.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/nn/embedding.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/nn/linear.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/nn/loss.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/nn/mlp.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/nn/normalization.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/nn/pool.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/ops.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/partitioning.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/quantization.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/random.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/specialized_fns.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/tree_util.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/util.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/src/haliax/wrap.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/core_test.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_attention.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_axis.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_conv.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_debug.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_dot.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_einsum.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_fp8.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_hof.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_nn.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_ops.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_parsing.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_partitioning.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_pool.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_random.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_rearrange.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_scan.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_specialized_fns.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_state_dict.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_tree_util.py +0 -0
- {haliax-1.4.dev322 → haliax-1.4.dev324}/tests/test_utils.py +0 -0
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: haliax
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.dev324
|
|
4
4
|
Summary: Named Tensors for Legible Deep Learning in JAX
|
|
5
5
|
Project-URL: Homepage, https://github.com/stanford-crfm/haliax
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/stanford-crfm/haliax/issues/
|
|
7
7
|
Project-URL: Documentation, https://haliax.readthedocs.io/en/latest/
|
|
8
8
|
Author-email: David Hall <dlwh@cs.stanford.edu>
|
|
9
|
-
License-File: LICENSE
|
|
10
9
|
Classifier: Development Status :: 4 - Beta
|
|
11
10
|
Classifier: Intended Audience :: Science/Research
|
|
12
11
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.4.dev324"
|
|
@@ -16,7 +16,7 @@ from jaxtyping import PyTree
|
|
|
16
16
|
import haliax.partitioning as partitioning
|
|
17
17
|
from haliax._src.util import index_where
|
|
18
18
|
from haliax.core import NamedArray, named
|
|
19
|
-
from haliax.jax_utils import is_jax_array_like
|
|
19
|
+
from haliax.jax_utils import is_jax_array_like, is_scalarish
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
try:
|
|
@@ -166,7 +166,9 @@ def to_state_dict(tree: PyTree, prefix: Optional[str] = None) -> StateDict:
|
|
|
166
166
|
Returns:
|
|
167
167
|
The state dict representation of the input tree.
|
|
168
168
|
"""
|
|
169
|
-
if
|
|
169
|
+
if tree is None:
|
|
170
|
+
return {}
|
|
171
|
+
elif isinstance(tree, eqx.Module):
|
|
170
172
|
if hasattr(tree, "to_state_dict"):
|
|
171
173
|
state_dict = tree.to_state_dict(prefix)
|
|
172
174
|
else:
|
|
@@ -198,6 +200,11 @@ def to_state_dict(tree: PyTree, prefix: Optional[str] = None) -> StateDict:
|
|
|
198
200
|
state_dict = {}
|
|
199
201
|
else:
|
|
200
202
|
raise ValueError("Cannot convert a leaf value to a state dict without a prefix")
|
|
203
|
+
elif is_scalarish(tree):
|
|
204
|
+
if prefix is not None:
|
|
205
|
+
state_dict = {prefix: tree}
|
|
206
|
+
else:
|
|
207
|
+
raise ValueError("Cannot convert a leaf value to a state dict without a prefix")
|
|
201
208
|
else:
|
|
202
209
|
raise ValueError(f"Unsupported type {type(tree)}")
|
|
203
210
|
|
|
@@ -291,37 +298,46 @@ def to_numpy_state_dict(model, prefix: Optional[str] = None) -> StateDict:
|
|
|
291
298
|
with jax.default_device(jax.local_devices(backend="cpu")[0]):
|
|
292
299
|
|
|
293
300
|
def get_to_cpu(arr):
|
|
294
|
-
if
|
|
301
|
+
if is_scalarish(arr):
|
|
302
|
+
return arr
|
|
303
|
+
elif not is_jax_array_like(arr):
|
|
295
304
|
return arr
|
|
296
305
|
elif isinstance(arr, np.ndarray):
|
|
297
306
|
return arr
|
|
298
|
-
elif arr
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
try:
|
|
315
|
-
axis_to_shard = index_where(
|
|
316
|
-
lambda axis_size: axis_size % process_mesh.devices.size == 0, arr.shape
|
|
307
|
+
elif is_jax_array_like(arr):
|
|
308
|
+
if arr.is_fully_addressable:
|
|
309
|
+
r = np.array(arr)
|
|
310
|
+
return r
|
|
311
|
+
else:
|
|
312
|
+
# unfortunately, jax's allgather seems to replicate to every device rather than every host
|
|
313
|
+
# which doesn't work for ~7B parameter models on TPU (assuming we also have optimizer state)
|
|
314
|
+
# this approach limits us to <64B parameters, but that's good enough for now
|
|
315
|
+
# we're going to do something a bit fancy, where we shard the model into a (process, device) mesh,
|
|
316
|
+
# then look for some axis along which we can shard the array, and then we'll do an allgather
|
|
317
|
+
# via pjit. If we can't find one, we'll just fully replicate since it probably isn't that big.
|
|
318
|
+
# TODO: ensure that this mesh arranges devices correctly
|
|
319
|
+
# (jax seems to do this internally itself, so we should be fine?)
|
|
320
|
+
process_mesh = Mesh(
|
|
321
|
+
np.array(jax.devices()).reshape((jax.process_count(), -1)), ("process", "device")
|
|
317
322
|
)
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
323
|
+
# now we need to find an axis along which we can shard the array.
|
|
324
|
+
# for this, we need to find an axis s.t. size(axis) % local_devices == 0
|
|
325
|
+
|
|
326
|
+
try:
|
|
327
|
+
axis_to_shard = index_where(
|
|
328
|
+
lambda axis_size: axis_size % process_mesh.devices.size == 0, arr.shape
|
|
329
|
+
)
|
|
330
|
+
except ValueError:
|
|
331
|
+
return np.array(arr)
|
|
332
|
+
|
|
333
|
+
shardings = [None if i != axis_to_shard else "device" for i in range(len(arr.shape))]
|
|
334
|
+
sharding = NamedSharding(process_mesh, PartitionSpec(*shardings))
|
|
335
|
+
out = jax.jit(lambda x: x, out_shardings=sharding)(arr)
|
|
336
|
+
return np.array(out)
|
|
337
|
+
elif is_scalarish(arr):
|
|
338
|
+
return np.asarray(arr)
|
|
339
|
+
else:
|
|
340
|
+
raise ValueError(f"Unsupported type {type(arr)}")
|
|
325
341
|
|
|
326
342
|
# need to make sure the model is on *this machine* and *this machine's CPU* before saving
|
|
327
343
|
model = jax.tree.map(lambda arr: get_to_cpu(arr), model)
|
|
@@ -246,7 +246,9 @@ class NamedArray:
|
|
|
246
246
|
try:
|
|
247
247
|
axis_index = index_where(lambda a: a.name == ax_name, self.axes)
|
|
248
248
|
if axis_index >= 0:
|
|
249
|
-
|
|
249
|
+
raise RuntimeError(
|
|
250
|
+
f"Found axis with same name but different size: {axis} vs {self.axes[axis_index]}"
|
|
251
|
+
)
|
|
250
252
|
return axis_index
|
|
251
253
|
except ValueError:
|
|
252
254
|
return None
|
|
@@ -8,7 +8,8 @@ from jax import numpy as jnp
|
|
|
8
8
|
|
|
9
9
|
import haliax
|
|
10
10
|
import haliax.util
|
|
11
|
-
from haliax.jax_utils import filter_checkpoint
|
|
11
|
+
from haliax.jax_utils import filter_checkpoint, is_jax_array_like
|
|
12
|
+
from haliax.util import is_jax_or_hax_array_like
|
|
12
13
|
|
|
13
14
|
from .._src.state_dict import ModuleWithStateDictSerialization, StateDict, with_prefix
|
|
14
15
|
from ..axis import Axis
|
|
@@ -167,7 +168,9 @@ class BlockSeq(ModuleWithStateDictSerialization, Generic[M]):
|
|
|
167
168
|
state_dict: StateDict = {}
|
|
168
169
|
for i, block in enumerate(self.blocks):
|
|
169
170
|
my_prefix = with_prefix(prefix, str(i))
|
|
170
|
-
|
|
171
|
+
# we can't assume to_state_dict is implemented, so we have to do it manually
|
|
172
|
+
block_dict = haliax.state_dict.to_state_dict(block, my_prefix)
|
|
173
|
+
state_dict.update(block_dict)
|
|
171
174
|
|
|
172
175
|
return state_dict
|
|
173
176
|
|
|
@@ -413,7 +416,7 @@ def _unstack_state_dict(state_dict: StateDict, prefix: Optional[str] = None) ->
|
|
|
413
416
|
assert prefix is not None
|
|
414
417
|
|
|
415
418
|
for k, v in state_dict.items():
|
|
416
|
-
if k.startswith(prefix) and v
|
|
419
|
+
if k.startswith(prefix) and is_jax_or_hax_array_like(v):
|
|
417
420
|
for i, v_i in enumerate(v):
|
|
418
421
|
new_dict[f"{prefix}{i}.{k[len(prefix):]}"] = v_i
|
|
419
422
|
else:
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
from typing import Optional, TypeVar
|
|
2
2
|
|
|
3
|
+
import equinox
|
|
4
|
+
|
|
5
|
+
from haliax.jax_utils import is_jax_array_like
|
|
6
|
+
from haliax.types import FilterSpec
|
|
7
|
+
|
|
3
8
|
from ._src.state_dict import (
|
|
4
9
|
ModuleWithStateDictSerialization,
|
|
5
10
|
StateDict,
|
|
@@ -18,12 +23,22 @@ from ._src.state_dict import (
|
|
|
18
23
|
T = TypeVar("T")
|
|
19
24
|
|
|
20
25
|
|
|
21
|
-
def to_torch_compatible_state_dict(
|
|
26
|
+
def to_torch_compatible_state_dict(
|
|
27
|
+
t: T, *, flatten_linear: bool = True, prefix: Optional[str] = None, filter: FilterSpec = is_jax_array_like
|
|
28
|
+
) -> StateDict:
|
|
22
29
|
"""
|
|
23
30
|
Convert a tree to a state dict that is compatible with torch-style state dicts.
|
|
24
31
|
|
|
25
32
|
This applies [haliax.state_dict.flatten_linear_layers][] followed by [haliax.state_dict.to_state_dict][]
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
t: The tree to convert
|
|
36
|
+
flatten_linear: Whether to flatten linear layers
|
|
37
|
+
prefix: The prefix to use for the state dict keys
|
|
38
|
+
filter: The filter to use for selecting which nodes to include in the state dict. By default, this includes only
|
|
39
|
+
array-like objects (e.g. JAX and NumPy arrays).
|
|
26
40
|
"""
|
|
41
|
+
t = equinox.filter(t, filter)
|
|
27
42
|
if flatten_linear:
|
|
28
43
|
t = flatten_linear_layers(t)
|
|
29
44
|
return to_numpy_state_dict(t, prefix=prefix)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
from typing import Any, Literal, Protocol, Tuple, TypeAlias, Union
|
|
1
|
+
from typing import Any, Callable, Literal, Protocol, Tuple, TypeAlias, Union
|
|
2
2
|
|
|
3
3
|
import jax.numpy as jnp
|
|
4
4
|
import numpy as np
|
|
5
5
|
from jax.lax import Precision
|
|
6
|
+
from jaxtyping import PyTree
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
DType: TypeAlias = np.dtype
|
|
@@ -30,3 +31,13 @@ IntScalar = Union[int, jnp.ndarray]
|
|
|
30
31
|
PrecisionLike = Union[None, str, Precision, Tuple[str, str], Tuple[Precision, Precision]]
|
|
31
32
|
|
|
32
33
|
GatherScatterModeStr = Literal["promise_in_bounds", "clip", "drop", "fill"]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
FilterSpec = Union[bool, Callable[[Any], bool]]
|
|
37
|
+
"""
|
|
38
|
+
A filter specification. Typically used on a pytree to filter out certain subtrees. Boolean values are
|
|
39
|
+
treated as-is, while callables are called on each element of the pytree. If the callable returns True, the element
|
|
40
|
+
is kept, otherwise it is filtered out.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
FilterTree = FilterSpec | PyTree[FilterSpec]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.4.dev322"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|