Coverage for pygeodesy/constants.py: 98%
196 statements
« prev ^ index » next coverage.py v7.6.1, created at 2025-05-04 12:01 -0400
« prev ^ index » next coverage.py v7.6.1, created at 2025-05-04 12:01 -0400
2# -*- coding: utf-8 -*-
4u'''Single-instance C{float} and C{int} constants across C{pygeodesy} modules and
5related functions L{pygeodesy.float_}, L{pygeodesy.isclose}, L{pygeodesy.isfinite},
6L{pygeodesy.isinf}, L{pygeodesy.isint0}, L{pygeodesy.isnan}, L{pygeodesy.isnear0},
7L{pygeodesy.isnear1}, L{pygeodesy.isnear90}, L{pygeodesy.isneg0}, L{pygeodesy.isninf},
8L{pygeodesy.isnon0} and L{pygeodesy.remainder}.
9'''
10# make sure int/int division yields float quotient, see .basics
11from __future__ import division as _; del _ # PYCHOK semicolon
13from pygeodesy.basics import _copysign, isbool, iscomplex, isint
14from pygeodesy.errors import _xError, _xError2, _xkwds_get1, _xkwds_item2
15# from pygeodesy.fsums import _isFsum_2Tuple # _MODS
16from pygeodesy.internals import _0_0, _100_0, typename
17from pygeodesy.interns import _DMAIN_, _INF_, _NAN_
18from pygeodesy.lazily import _ALL_MODS as _MODS, _ALL_LAZY
19# from pygeodesy.streprs import Fmt # from .unitsBase
20from pygeodesy.unitsBase import Float, Int, Radius, Fmt
22from math import fabs, isinf, isnan, pi as _pi, sqrt
23try:
24 from math import inf as _inf, nan as _nan # PYCHOK Python 3+
25except ImportError: # Python 2-
26 _inf, _nan = float(_INF_), float(_NAN_)
28__all__ = _ALL_LAZY.constants
29__version__ = '25.04.14'
32def _copysign_0_0(y):
33 '''(INTERNAL) copysign(0.0, y), only C{float}.
34 '''
35 return _N_0_0 if y < 0 else _0_0
38def _copysign_1_0(y):
39 '''(INTERNAL) copysign(1.0, y), only C{float}.
40 '''
41 return _N_1_0 if y < 0 else _1_0
44def _copysignINF(y):
45 '''(INTERNAL) copysign(INF, y), only C{float}.
46 '''
47 return NINF if y < 0 else INF
50def _Float(**name_arg):
51 '''(INTERNAL) New named, cached C{Float}.
52 '''
53 n, arg = _xkwds_item2(name_arg)
54 return Float(_float(arg), name=n)
57def _Radius(**name_arg):
58 '''(INTERNAL) New named, cached C{Radius}.
59 '''
60 n, arg = _xkwds_item2(name_arg)
61 return Radius(_float(arg), name=n)
64def float_(*fs, **sets): # sets=False
65 '''Get scalars as C{float} or I{intern}'ed C{float}.
67 @arg fs: One more values (C{scalar}), all positional.
68 @kwarg sets: Use C{B{sets}=True} to C{intern} each
69 B{C{fs}}, otherwise don't C{intern}.
71 @return: A single C{float} if only one B{C{fs}} is
72 given, otherwise a tuple of C{float}s.
74 @raise TypeError: Some B{C{fs}} is not C{scalar}.
75 '''
76 fl = []
77 _a = fl.append
78 _f = _floats.setdefault if _xkwds_get1(sets, sets=False) else \
79 _floats.get
80 try:
81 for i, f in enumerate(fs):
82 f = float(f)
83 _a(_f(f, f))
84 except Exception as x:
85 E, t = _xError2(x)
86 fs_i = Fmt.SQUARE(fs=i)
87 raise E(fs_i, f, txt=t)
88 return fl[0] if len(fl) == 1 else tuple(fl)
91def _float(f): # in .datums, .ellipsoids, ...
92 '''(INTERNAL) Cache initial C{float}s.
93 '''
94 f = float(f)
95 return _floats.setdefault(f, f) # PYCHOK del _floats
98def float0_(*xs):
99 '''Yield C{B{x}s} as a non-NEG0 C{float}.
100 '''
101 for x in xs:
102 yield float(x) if x else _0_0
105def _float0(f): # in .auxilats.auxily, .resections, .vector3dBase, ...
106 '''(INTERNAL) Return C{float(B{f})} or C{INT0}.
107 '''
108 if f:
109 f = float(f)
110 f = _floats.get(f, f)
111 elif f is not INT0:
112 f = float(f) or _0_0 # force None, NN error
113 return f
116def _floatuple(*fs):
117 '''(INTERNAL) Cache a tuple of C{float}s.
118 '''
119 return tuple(map(_float, fs))
122try:
123 from math import log2 as _log2
124except ImportError: # Python 3.3-
125 from math import log as _log
127 def _log2(x): # in .rhumb.aux_, .auxilats.auxLat
128 return _log(x, 2)
131def _naninf(p, *xs):
132 '''(INTERNAL) Return C{NAN}, C{NINF} or C{INF}.
133 '''
134 for x in xs:
135 p *= x # fmath.fprod(xs)
136 return _copysignINF(p) if isfinite(p) else p
139def _over(p, q):
140 '''(INTERNAL) Return C{B{p} / B{q}} avoiding C{ZeroDivisionError} exceptions.
141 '''
142 try:
143 return (p / q) # if p else _copysign_0_0(q)
144 except ZeroDivisionError:
145 return (_copysignINF(p) if isfinite(p) else NAN) if p else p
148def _1_over(x):
149 '''(INTERNAL) Return reciprocal C{1 / B{x}} avoiding C{ZeroDivisionError} exceptions.
150 '''
151 try:
152 return _1_0 / float(x)
153 except ZeroDivisionError:
154 return NINF if isneg0(x) else INF
157_floats = {} # PYCHOK floats cache, in .__main__
158# _float = float # PYCHOK expected
159# del _floats # XXX zap floats cache never
161_0_0 = _float( _0_0) # PYCHOK expected
162_0_0_1T = _0_0, # PYCHOK 1-tuple
163_0_0_9T = _0_0_1T * 9 # PYCHOK 9-tuple
164_0_0001 = _float( 0.0001) # PYCHOK expected
165_0_001 = _float( 0.001) # PYCHOK expected
166_0_01 = _float( 0.01) # PYCHOK expected
167_0_1 = _float( 0.1) # PYCHOK expected
168_0_125 = _float( 0.125) # PYCHOK expected
169_0_25 = _float( 0.25) # PYCHOK expected
170_0_5 = _float( 0.5) # PYCHOK expected
171_1_0 = _float( 1) # PYCHOK expected
172_1_0_1T = _1_0, # PYCHOK 1-tuple
173_1_5 = _float( 1.5) # PYCHOK expected
174_1_75 = _float( 1.75) # PYCHOK expected
175_2_0 = _float( 2) # PYCHOK expected
176_3_0 = _float( 3) # PYCHOK expected
177_4_0 = _float( 4) # PYCHOK expected
178_5_0 = _float( 5) # PYCHOK expected
179_6_0 = _float( 6) # PYCHOK expected
180_8_0 = _float( 8) # PYCHOK expected
181_9_0 = _float( 9) # PYCHOK expected
182_10_0 = _float( 10) # PYCHOK expected
183_16_0 = _float( 16) # PYCHOK expected
184_32_0 = _float( 32) # PYCHOK expected
185_45_0 = _float( 45) # PYCHOK expected
186_60_0 = _float( 60) # PYCHOK expected
187_64_0 = _float( 64) # PYCHOK expected
188_90_0 = _float( 90) # PYCHOK expected
189_100_0 = _float(_100_0) # PYCHOK expected
190_180_0 = _float( 180) # PYCHOK expected
191_270_0 = _float( 270) # PYCHOK expected
192_360_0 = _float( 360) # PYCHOK expected
193_720_0 = _float( 720) # PYCHOK expected
194_1000_0 = _float(1000) # PYCHOK expected
195_3600_0 = _float(3600) # PYCHOK expected
197_N_0_0 = float( '-0.0') # PYCHOK NOT _float!
198_N_0_5 = _float( -_0_5) # PYCHOK expected
199_N_1_0 = _float( -_1_0) # PYCHOK expected
200_N_2_0 = _float( -_2_0) # PYCHOK expected
201_N_90_0 = _float( -_90_0) # PYCHOK expected
202_N_180_0 = _float(-_180_0) # PYCHOK expected
204_M_KM = _1000_0 # meter per Kilo meter, see .utily
205_M_NM = _float(1852.0) # meter per Nautical Mile, exactly
206_M_SM = _float(1609.344) # meter per Statute Mile
208try:
209 from sys import float_info as _f_i
210 # @see: <https://NumPy.org/doc/stable/reference/generated/numpy.finfo.html>
211 DIG = Int( DIG =_f_i.dig) # PYCHOK system's float decimal digits
212 EPS = _Float(EPS =_f_i.epsilon) # PYCHOK system's EPSilon
213 MANT_DIG = Int( MANT_DIG=_f_i.mant_dig) # PYCHOK system's float mantissa bits
214 MAX = _Float(MAX =_f_i.max) # PYCHOK system's MAX float 1.7976931348623157e+308
215 MAX_EXP = Int( MAX_EXP =_f_i.max_exp) # PYTHON system's max base 2 exponent
216 MIN = _Float(MIN =_f_i.min) # PYCHOK system's MIN float 2.2250738585072014e-308
217 MIN_EXP = Int( MIN_EXP =_f_i.min_exp) # PYTHON system's min base 2 exponent
218# RADIX = Int( RADIX =_f_i.radix) # PYTHON system's float base
219 del _f_i
220except ImportError: # PYCHOK no cover
221 DIG = Int( DIG =15) # PYCHOK system's 64-bit float decimal digits
222 EPS = _Float(EPS =2.220446049250313e-16) # PYCHOK EPSilon 2**-52, M{EPS +/- 1 != 1}
223 MANT_DIG = Int( MANT_DIG=53) # PYCHOK float mantissa bits ≈ 53 (C{int})
224 MAX = _Float(MAX =pow(_2_0, 1023) * (_2_0 - EPS)) # PYCHOK ≈ 10**308
225 MAX_EXP = Int( MAX_ESP =_log2(MAX)) # 308 base 10
226 MIN = _Float(MIN =pow(_2_0, -1021)) # PYCHOK ≈ 10**-308
227 MIN_EXP = Int(MIN_EXP =_log2(MIN)) # -307 base 10
228# RADIX = Int(Radix =2) # base
230EPS0 = _Float( EPS0 = EPS**2) # PYCHOK near-/non-zero comparison 4.930381e-32, or EPS or EPS_2
231EPS02 = _Float( EPS02 = EPS**4) # PYCHOK near-zero-squared comparison 2.430865e-63
232EPS_2 = _Float( EPS_2 = EPS / _2_0) # PYCHOK ≈ 1.110223024625e-16
233EPS1 = _Float( EPS1 =_1_0 - EPS) # PYCHOK ≈ 0.9999999999999998
234EPS2 = _Float( EPS2 = EPS * _2_0) # PYCHOK ≈ 4.440892098501e-16
235EPS4 = _Float( EPS4 = EPS * _4_0) # PYCHOK ≈ 8.881784197001e-16
236# _1EPS = _Float(_1EPS =_1_0 + EPS) # PYCHOK ≈ 1.0000000000000002
237_1_EPS = _Float(_1_EPS =_1_0 / EPS) # PYCHOK = 4503599627370496.0
238# _2_EPS = _Float(_2_EPS =_2_0 / EPS) # PYCHOK = 9007199254740992.0
239_EPS2e4 = _Float(_EPS2e4= EPS2 * 1.e4) # PYCHOK ≈ 4.440892098501e-12
240_EPS4e8 = _Float(_EPS4e8= EPS4 * 1.e8) # PYCHOK ≈ 8.881784197001e-08
241_EPSjam = _Float(_EPSjam= pow(EPS, 0.75)) # PYCHOK = 1.818989403546e-12
242_EPSmin = _Float(_EPSmin= sqrt(MIN)) # PYCHOK = 1.49166814624e-154
243_EPSqrt = _Float(_EPSqrt= sqrt(EPS)) # PYCHOK = 1.49011611938e5-08
244_EPStol = _Float(_EPStol=_EPSqrt * _0_1) # PYCHOK = 1.49011611938e5-09 == sqrt(EPS * _0_01)
246_89_999 = _Float(_89_999=_90_0 * EPS1) # just below 90.0
247# <https://Numbers.Computation.Free.FR/Constants/Miscellaneous/digits.html>
248_1__90 = _Float(_1__90 =_1_0 / _90_0) # PYCHOK = 0.011_111_111_111_111_111_111_111_111_111_111_111_111_111_111_11111
249_2__PI = _Float(_2__PI =_2_0 / _pi) # PYCHOK = 0.636_619_772_367_581_343_075_535_053_490_057_448_137_838_582_96182
251_1_16th = _Float(_1_16th=_1_0 / _16_0) # PYCHOK in .ellipsoids, .karney
252_1_3rd = _Float(_1_3rd =_1_0 / _3_0) # PYCHOK in .fmath
253_1_6th = _Float(_1_6th =_1_0 / _6_0) # PYCHOK in .fmath
255_K0_UTM = _Float(_K0_UTM = 0.9996) # PYCHOK in .etm, .ktm, .utm, UTM scale at central meridian
256# sqrt(2) <https://WikiPedia.org/wiki/Square_root_of_2>
257# 1.414213562373095_048_801_688_724_209_698_078_569_671_875_376_948_073_176_679_737_99
258# _1SQRT2= _Float(_1SQRT2 =sqrt(_2_0) + 1)
259# 0.707106781186547_524_400_844_362_104_849_039_284_835_937_688_474_036_588_339_868_99
260_SQRT2_2 = _Float(_SQRT2_2=sqrt(_0_5)) # PYCHOK = 0.707106781186547_5 == sqrt(2) / 2
262INF = Float(INF =_inf) # PYCHOK INFinity, see function L{isinf}, L{isfinite}, NOT _Float!
263INT0 = Int( INT0= 0) # PYCHOK unique int(0) instance, see .fsums, useZ=False
264NAN = Float(NAN =_nan) # PYCHOK Not-A-Number, see function L{isnan}, NOT _Float!
265NEG0 = Float(NEG0=_N_0_0) # PYCHOK NEGative 0.0, see function L{isneg0}, NOT _Float!
266NINF = Float(NINF=-INF) # PYCHOK Negative INFinity, NOT _Float!
268PI = _Float(PI =_pi) # 3.1415_9265_3589_7932_3846_2643_3832_795
269PI2 = _Float(PI2 =_pi * _2_0) # PYCHOK Two PI, M{PI * 2} aka I{Tau}
270PI_2 = _Float(PI_2 =_pi / _2_0) # PYCHOK Half PI, M{PI / 2}
271PI3 = _Float(PI3 =_pi * _3_0) # PYCHOK Three PI, M{PI * 3}
272PI3_2 = _Float(PI3_2=_pi * _1_5) # PYCHOK PI and a half, M{PI * 3 / 2}
273PI_3 = _Float(PI_3 =_pi / _3_0) # PYCHOK One third PI, M{PI / 3}
274PI4 = _Float(PI4 =_pi * _4_0) # PYCHOK Four PI, M{PI * 4}
275PI_4 = _Float(PI_4 =_pi / _4_0) # PYCHOK Quarter PI, M{PI / 4}
277R_MA = _Radius(R_MA=6378137.0) # PYCHOK equatorial earth radius (C{meter}), WGS84, EPSG:3785
278R_MB = _Radius(R_MB=6356752.3) # PYCHOK polar earth radius (C{meter}), WGS84, EPSG:3785
279R_M = _Radius(R_M =6371008.771415) # PYCHOK mean, spherical earth radius (C{meter})
280R_KM = _Radius(R_KM=R_M / _M_KM) # PYCHOK mean, spherical earth radius (C{KM}, Kilo meter)
281R_NM = _Radius(R_NM=R_M / _M_NM) # PYCHOK mean, spherical earth radius (C{NM}, nautical miles)
282R_SM = _Radius(R_SM=R_M / _M_SM) # PYCHOK mean, spherical earth radius (C{SM}, statute miles)
283# See <https://www.EdWilliams.org/avform.htm>, <https://www.DTIC.mil/dtic/tr/fulltext/u2/a216843.pdf>
284# and <https://GitHub.com/NASA/MultiDop/blob/master/src/share/man/man3/geog_lib.3> based on the
285# International Standard Nautical Mile of 1,852 meter (1' latitude)
286R_FM = _Radius(R_FM=6371000.0) # PYCHOK former FAI Sphere earth radius (C{meter})
287R_GM = _Radius(R_GM=6371230.0) # PYCHOK avg. radius, distance to geoid surface (C{meter})
288# <http://Wiki.GIS.com/wiki/index.php/Ellipsoidal_quadratic_mean_radius>
289R_QM = _Radius(R_QM=6372797.560856) # PYCHOK earth' quadratic mean radius (C{meter})
290# Rtri= _Radius(Rtri=6372797.5559594) # PYCHOK Rtriaxial quadratic mean radius (C{meter}), WGS84
291# Rbi = _Radius(Rbi =6367453.6345163) # PYCHOK Rbiaxial quadratic mean radius (C{meter}), WGS84
292R_VM = _Radius(R_VM=6366707.0194937) # PYCHOK aViation/naVigation earth radius (C{meter})
293# R_AU= Meter( R_AU=149597870700.0) # PYCHOK <https://WikiPedia.org/wiki/Astronomical_unit>
295_INF_NAN_NINF = INF, NAN, NINF
296_pos_self = _1_0.__pos__() is _1_0 # PYCHOK in .fsums, .vector3dBase
299def _0_0s(n):
300 '''(INTERNAL) Return an C{B{n}-tuple} of C{_0_0} zeros.
301 '''
302 return _0_0_9T[:n] if 0 <= n <= len(_0_0_9T) else (_0_0_1T * n)
305try:
306 from math import isclose as _isclose
307except ImportError: # Python 3.4-
309 def _isclose(a, b, rel_tol=1e-9, abs_tol=0):
310 '''Mimick Python 3.5+ C{math.isclose}.
311 '''
312 t, d = abs_tol, fabs(a - b)
313 if d > t:
314 r = max(fabs(a), fabs(b)) * rel_tol
315 t = max(r, t)
316 return d <= t
319def isclose(a, b, rel_tol=1e-12, abs_tol=EPS0):
320 '''Like C{math.isclose}, but with defaults such
321 that C{isclose(0, EPS0)} is C{True} by default.
322 '''
323 return _isclose(a, b, rel_tol=rel_tol, abs_tol=abs_tol)
326try:
327 from cmath import isfinite as _iscfinite
328except ImportError: # Python 3.1-
330 def _iscfinite(x): # PYCHOK not self?
331 '''Mimick Python 3.2+ C{cmath.isfinite}.
332 '''
333 return _isfinite(x.real) and _isfinite(x.imag)
335try:
336 from math import isfinite as _isfinite # in .ellipsoids, ...
337except ImportError: # Python 3.1-
339 def _isfinite(x): # PYCHOK not self?
340 '''Mimick Python 3.2+ C{math.isfinite}.
341 '''
342 return not (isinf(x) or isnan(x))
345def isfinite(obj):
346 '''Check a finite C{scalar}, C{complex}, ... value.
348 @arg obj: Value (C{scalar}, C{complex}, an L{Fsum} or
349 L{Fsum2Tuple}).
351 @return: C{False} if B{C{obj}} is C{INF}, C{NINF} or
352 C{NAN}, C{True} otherwise.
354 @raise TypeError: Non-scalar and non-complex B{C{obj}}.
355 '''
356 try:
357 return (obj not in _INF_NAN_NINF) and _isfinite(obj)
358 except Exception as x:
359 if iscomplex(obj): # _isfinite(complex) thows TypeError
360 return _iscfinite(obj)
361 if _MODS.fsums._isFsum_2Tuple(obj): # OverflowError
362 return obj.is_finite()
363 raise _xError(x, Fmt.PAREN(typename(isfinite), obj))
366def isint0(obj, both=False):
367 '''Check for L{INT0} or C{int(0)} value.
369 @arg obj: The object (any C{type}).
370 @kwarg both: If C{true}, also check C{float(0)} (C{bool}).
372 @return: C{True} if B{C{obj}} is L{INT0}, C{int(0)} or
373 C{float(0)}, C{False} otherwise.
374 '''
375 return (obj is INT0 or obj is int(0) or
376 bool(both and (not obj) and isint(obj, both=True))) and \
377 not isbool(obj)
380def isnear0(x, eps0=EPS0):
381 '''Is B{C{x}} near I{zero} within a tolerance?
383 @arg x: Value (C{scalar}).
384 @kwarg eps0: Near-I{zero} tolerance (C{EPS0}).
386 @return: C{True} if C{abs(B{x}) < B{eps0}},
387 C{False} otherwise.
389 @see: Function L{isnon0}.
390 '''
391 return bool(eps0 > x > -eps0)
394def isnear1(x, eps1=EPS0):
395 '''Is B{C{x}} near I{one} within a tolerance?
397 @arg x: Value (C{scalar}).
398 @kwarg eps1: Near-I{one} tolerance (C{EPS0}).
400 @return: C{isnear0(B{x} - 1, eps0=B{eps1})}.
402 @see: Function L{isnear0}.
403 '''
404 return bool(eps1 > (x - _1_0) > -eps1)
407def isnear90(x, eps90=EPS0):
408 '''Is B{C{x}} near I{90} within a tolerance?
410 @arg x: Value (C{scalar}).
411 @kwarg eps90: Near-I{90} tolerance (C{EPS0}).
413 @return: C{isnear0(B{x} - 90, eps0=eps90)}.
415 @see: Function L{isnear0}.
416 '''
417 return bool(eps90 > (x - _90_0) > -eps90)
420def isneg0(x):
421 '''Check for L{NEG0}, negative C{0.0}.
423 @arg x: Value (C{scalar}).
425 @return: C{True} if B{C{x}} is C{NEG0} or C{-0.0},
426 C{False} otherwise.
427 '''
428 return (not x) and _copysign(1, x) < 0
429# and str(x).startswith(_MINUS_)
432def isninf(x):
433 '''Check for L{NINF}, negative C{INF}.
435 @arg x: Value (C{scalar}).
437 @return: C{True} if B{C{x}} is C{NINF} or C{-inf},
438 C{False} otherwise.
439 '''
440 return x is NINF or (x < 0 and not isfinite(x))
443def isnon0(x, eps0=EPS0):
444 '''Is B{C{x}} non-zero with a tolerance?
446 @arg x: Value (C{scalar}).
447 @kwarg eps0: Non-zero tolerance (C{EPS0}).
449 @return: C{True} if C{abs(B{x}) > B{eps0}},
450 C{False} otherwise.
452 @see: Function L{isnear0}.
453 '''
454 return not bool(eps0 > x > -eps0) # not isnear0
457def _off90(lat):
458 '''(INTERNAL) Off 90.0 for .gars and .wgrs.
459 '''
460 return max(min(lat, _89_999), -_89_999)
463try:
464 from math import remainder
465except ImportError: # Python 3.6-
466 from math import fmod as _fmod
468 def remainder(x, y):
469 '''Mimick Python 3.7+ C{math.remainder}.
470 '''
471 if isnan(y):
472 x = NAN
473 elif x and not isnan(x):
474 y = fabs(y)
475 x = _fmod(x, y)
476 h = _0_5 * y
477 if x >= h:
478 x -= y
479 elif x < -h:
480 x += y
481 return x # keep signed 0.0
484def _umod_360(deg):
485 '''(INTERNAL) Non-negative C{deg} modulo 360, basic C{.utily.wrap360}.
486 '''
487 return (deg % _360_0) or _0_0
490def _umod_PI2(rad):
491 '''(INTERNAL) Non-negative C{rad} modulo PI2, basic C{.utily.wrapPI2}.
492 '''
493 return (rad % PI2) or _0_0
496if __name__ == _DMAIN_:
498 def _main(locals):
499 from pygeodesy import itemsorted, printf
500 from pygeodesy.interns import _DALL_, _UNDER_
502 t = n = v = []
503 for n, v in itemsorted(locals):
504 if isinstance(v, (Float, Int, Radius)):
505 printf('%9s: %r', n, v.toRepr(std=False))
506 if v.name != n:
507 raise AssertionError('%r != %r' % (n, v))
508 if v.name is not n:
509 raise AssertionError('%r is not %r' % (n, v))
510 if not n.startswith(_UNDER_):
511 t.append(n)
512 t.append(typename(float_))
513 printf('%s = %r', _DALL_, tuple(t))
515 _main(locals())
517# **) MIT License
518#
519# Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
520#
521# Permission is hereby granted, free of charge, to any person obtaining a
522# copy of this software and associated documentation files (the "Software"),
523# to deal in the Software without restriction, including without limitation
524# the rights to use, copy, modify, merge, publish, distribute, sublicense,
525# and/or sell copies of the Software, and to permit persons to whom the
526# Software is furnished to do so, subject to the following conditions:
527#
528# The above copyright notice and this permission notice shall be included
529# in all copies or substantial portions of the Software.
530#
531# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
532# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
533# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
534# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
535# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
536# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
537# OTHER DEALINGS IN THE SOFTWARE.