From e8be519527a96fb8b116787c3312363a4d29daf1 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Mon, 27 Jun 2022 13:24:08 +0200 Subject: [PATCH] Implement a more robust rounding algorithm (no magic number) I have checked this on large designs and found this to work more robustly. --- phidl/device_layout.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/phidl/device_layout.py b/phidl/device_layout.py index 5ed7af7e..b41499ba 100644 --- a/phidl/device_layout.py +++ b/phidl/device_layout.py @@ -36,6 +36,7 @@ import hashlib +import math import warnings from copy import deepcopy as _deepcopy @@ -1856,18 +1857,12 @@ def hash_geometry(self, precision=1e-4): layers = np.array(list(polygons_by_spec.keys())) sorted_layers = layers[np.lexsort((layers[:, 0], layers[:, 1]))] - # A random offset which fixes common rounding errors intrinsic - # to floating point math. Example: with a precision of 0.1, the - # floating points 7.049999 and 7.050001 round to different values - # (7.0 and 7.1), but offset values (7.220485 and 7.220487) don't - magic_offset = 0.17048614 - final_hash = hashlib.sha1() for layer in sorted_layers: layer_hash = hashlib.sha1(layer.astype(np.int64)).digest() polygons = polygons_by_spec[tuple(layer)] polygons = [ - np.ascontiguousarray((p / precision) + magic_offset, dtype=np.int64) + _rnd(p, precision) for p in polygons ] polygon_hashes = np.sort([hashlib.sha1(p).digest() for p in polygons]) @@ -1878,6 +1873,12 @@ def hash_geometry(self, precision=1e-4): return final_hash.hexdigest() +def _rnd(arr, precision=1e-4): + arr = np.ascontiguousarray(arr) + ndigits = round(-math.log10(precision)) + return np.ascontiguousarray(arr.round(ndigits) / precision, dtype=np.int64) + + class DeviceReference(gdspy.CellReference, _GeometryHelper): """Simple reference to an existing Device.