<div dir="ltr"><div class="markdown-here-wrapper" style="font-size:1em;font-family:Helvetica,arial,freesans,clean,sans-serif;color:rgb(34,34,34);background-color:rgb(255,255,255);border:none;line-height:1.2"><p style="margin:1em 0px">You make a bunch of good points refuting reproducible research as an argument for not changing the random number streams.</p>
<p style="margin:1em 0px">However, there’s a second use-case you don’t address - unit tests. For better or worse, downstream, or <a href="https://github.com/numpy/numpy/blob/c4813a9/numpy/core/tests/test_multiarray.py#L5093-L5108" style="color:rgb(51,51,238);text-decoration:none">even our own</a>, unit tests use a seeded random number generator as a shorthand to produce some arbirary array, and then hard-code the expected output in their tests. Breaking stream compatibility will break these tests.</p>
<p style="margin:1em 0px">I don’t think writing tests in this way is particularly good idea, but unfortunately they do still exist.</p>
<p style="margin:1em 0px">It would be good to address this use case in the NEP, even if the conclusion is just “changing the stream will break tests of this form”</p>
<p style="margin:1em 0px">Eric</p>
<p style="margin:1em 0px">On Sat, 2 Jun 2018 at 12:05 Robert Kern <a href="http://mailto:robert.kern@gmail.com" style="color:rgb(51,51,238);text-decoration:none">robert.kern@gmail.com</a> wrote:</p>
<p style="margin:1em 0px"></p><div class="markdown-here-exclude"><p></p><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">As promised distressingly many months ago, I have written up a NEP about relaxing the stream-compatibility policy that we currently have.<div><br></div><div><a href="https://github.com/numpy/numpy/pull/11229" target="_blank">https://github.com/numpy/numpy/pull/11229</a><br></div><div><a href="https://github.com/rkern/numpy/blob/nep/rng/doc/neps/nep-0019-rng-policy.rst" target="_blank">https://github.com/rkern/numpy/blob/nep/rng/doc/neps/nep-0019-rng-policy.rst</a><br></div><div><br></div><div>I particularly invite comment on the two lists of methods that we still would make strict compatibility guarantees for.</div><div><br></div><div>---</div><div><br></div><div><div>==============================</div><div>Random Number Generator Policy</div><div>==============================</div><div><br></div><div>:Author: Robert Kern <<a href="mailto:robert.kern@gmail.com" target="_blank">robert.kern@gmail.com</a>></div><div>:Status: Draft</div><div>:Type: Standards Track</div><div>:Created: 2018-05-24</div><div><br></div><div><br></div><div>Abstract</div><div>--------</div><div><br></div><div>For the past decade, NumPy has had a strict backwards compatibility policy for</div><div>the number stream of all of its random number distributions.  Unlike other</div><div>numerical components in ``numpy``, which are usually allowed to return</div><div>different when results when they are modified if they remain correct, we have</div><div>obligated the random number distributions to always produce the exact same</div><div>numbers in every version.  The objective of our stream-compatibility guarantee</div><div>was to provide exact reproducibility for simulations across numpy versions in</div><div>order to promote reproducible research.  However, this policy has made it very</div><div>difficult to enhance any of the distributions with faster or more accurate</div><div>algorithms.  After a decade of experience and improvements in the surrounding</div><div>ecosystem of scientific software, we believe that there are now better ways to</div><div>achieve these objectives.  We propose relaxing our strict stream-compatibility</div><div>policy to remove the obstacles that are in the way of accepting contributions</div><div>to our random number generation capabilities.</div><div><br></div><div><br></div><div>The Status Quo</div><div>--------------</div><div><br></div><div>Our current policy, in full:</div><div><br></div><div>    A fixed seed and a fixed series of calls to ``RandomState`` methods using the</div><div>    same parameters will always produce the same results up to roundoff error</div><div>    except when the values were incorrect.  Incorrect values will be fixed and</div><div>    the NumPy version in which the fix was made will be noted in the relevant</div><div>    docstring.  Extension of existing parameter ranges and the addition of new</div><div>    parameters is allowed as long the previous behavior remains unchanged.</div><div><br></div><div>This policy was first instated in Nov 2008 (in essence; the full set of weasel</div><div>words grew over time) in response to a user wanting to be sure that the</div><div>simulations that formed the basis of their scientific publication could be</div><div>reproduced years later, exactly, with whatever version of ``numpy`` that was</div><div>current at the time.  We were keen to support reproducible research, and it was</div><div>still early in the life of ``numpy.random``.  We had not seen much cause to</div><div>change the distribution methods all that much.</div><div><br></div><div>We also had not thought very thoroughly about the limits of what we really</div><div>could promise (and by “we” in this section, we really mean Robert Kern, let’s</div><div>be honest).  Despite all of the weasel words, our policy overpromises</div><div>compatibility.  The same version of ``numpy`` built on different platforms, or</div><div>just in a different way could cause changes in the stream, with varying degrees</div><div>of rarity.  The biggest is that the ``.multivariate_normal()`` method relies on</div><div>``numpy.linalg`` functions.  Even on the same platform, if one links ``numpy``</div><div>with a different LAPACK, ``.multivariate_normal()`` may well return completely</div><div>different results.  More rarely, building on a different OS or CPU can cause</div><div>differences in the stream.  We use C ``long`` integers internally for integer</div><div>distribution (it seemed like a good idea at the time), and those can vary in</div><div>size depending on the platform.  Distribution methods can overflow their</div><div>internal C ``longs`` at different breakpoints depending on the platform and</div><div>cause all of the random variate draws that follow to be different.</div><div><br></div><div>And even if all of that is controlled, our policy still does not provide exact</div><div>guarantees across versions.  We still do apply bug fixes when correctness is at</div><div>stake.  And even if we didn’t do that, any nontrivial program does more than</div><div>just draw random numbers.  They do computations on those numbers, transform</div><div>those with numerical algorithms from the rest of ``numpy``, which is not</div><div>subject to so strict a policy.  Trying to maintain stream-compatibility for our</div><div>random number distributions does not help reproducible research for these</div><div>reasons.</div><div><br></div><div>The standard practice now for bit-for-bit reproducible research is to pin all</div><div>of the versions of code of your software stack, possibly down to the OS itself.</div><div>The landscape for accomplishing this is much easier today than it was in 2008.</div><div>We now have ``pip``.  We now have virtual machines.  Those who need to</div><div>reproduce simulations exactly now can (and ought to) do so by using the exact</div><div>same version of ``numpy``.  We do not need to maintain stream-compatibility</div><div>across ``numpy`` versions to help them.</div><div><br></div><div>Our stream-compatibility guarantee has hindered our ability to make</div><div>improvements to ``numpy.random``.  Several first-time contributors have</div><div>submitted PRs to improve the distributions, usually by implementing a faster,</div><div>or more accurate algorithm than the one that is currently there.</div><div>Unfortunately, most of them would have required breaking the stream to do so.</div><div>Blocked by our policy, and our inability to work around that policy, many of</div><div>those contributors simply walked away.</div><div><br></div><div><br></div><div>Implementation</div><div>--------------</div><div><br></div><div>We propose first freezing ``RandomState`` as it is and developing a new RNG</div><div>subsystem alongside it.  This allows anyone who has been relying on our old</div><div>stream-compatibility guarantee to have plenty of time to migrate.</div><div>``RandomState`` will be considered deprecated, but with a long deprecation</div><div>cycle, at least a few years.  Deprecation warnings will start silent but become</div><div>increasingly noisy over time.  Bugs in the current state of the code will *not*</div><div>be fixed if fixing them would impact the stream.  However, if changes in the</div><div>rest of ``numpy`` would break something in the ``RandomState`` code, we will</div><div>fix ``RandomState`` to continue working (for example, some change in the</div><div>C API).  No new features will be added to ``RandomState``.  Users should</div><div>migrate to the new subsystem as they are able to.</div><div><br></div><div>Work on a proposed `new PRNG subsystem</div><div><<a href="https://github.com/bashtage/randomgen" target="_blank">https://github.com/bashtage/randomgen</a>>`_ is already underway.  The specifics</div><div>of the new design are out of scope for this NEP and up for much discussion, but</div><div>we will discuss general policies that will guide the evolution of whatever code</div><div>is adopted.</div><div><br></div><div>First, we will maintain API source compatibility just as we do with the rest of</div><div>``numpy``.  If we *must* make a breaking change, we will only do so with an</div><div>appropriate deprecation period and warnings.</div><div><br></div><div>Second, breaking stream-compatibility in order to introduce new features or</div><div>improve performance will be *allowed* with *caution*.  Such changes will be</div><div>considered features, and as such will be no faster than the standard release</div><div>cadence of features (i.e. on ``X.Y`` releases, never ``X.Y.Z``).  Slowness is</div><div>not a bug.  Correctness bug fixes that break stream-compatibility can happen on</div><div>bugfix releases, per usual, but developers should consider if they can wait</div><div>until the next feature release.  We encourage developers to strongly weight</div><div>user’s pain from the break in stream-compatibility against the improvements.</div><div>One example of a worthwhile improvement would be to change algorithms for</div><div>a significant increase in performance, for example, moving from the `Box-Muller</div><div>transform <<a href="https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform" target="_blank">https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform</a>>`_ method</div><div>of Gaussian variate generation to the faster `Ziggurat algorithm</div><div><<a href="https://en.wikipedia.org/wiki/Ziggurat_algorithm" target="_blank">https://en.wikipedia.org/wiki/Ziggurat_algorithm</a>>`_.  An example of an</div><div>unworthy improvement would be tweaking the Ziggurat tables just a little bit.</div><div><br></div><div>Any new design for the RNG subsystem will provide a choice of different core</div><div>uniform PRNG algorithms.  We will be more strict about a select subset of</div><div>methods on these core PRNG objects.  They MUST guarantee stream-compatibility</div><div>for a minimal, specified set of methods which are chosen to make it easier to</div><div>compose them to build other distributions.  Namely,</div><div><br></div><div>    * ``.bytes()``</div><div>    * ``.random_uintegers()``</div><div>    * ``.random_sample()``</div><div><br></div><div>Furthermore, the new design should also provide one generator class (we shall</div><div>call it ``StableRandom`` for discussion purposes) that provides a slightly</div><div>broader subset of distribution methods for which stream-compatibility is</div><div>*guaranteed*.  The point of ``StableRandom`` is to provide something that can</div><div>be used in unit tests so projects that currently have tests which rely on the</div><div>precise stream can be migrated off of ``RandomState``.  For the best</div><div>transition, ``StableRandom`` should use as its core uniform PRNG the current</div><div>MT19937 algorithm.  As best as possible, the API for the distribution methods</div><div>that are provided on ``StableRandom`` should match their counterparts on</div><div>``RandomState``.  They should provide the same stream that the current version</div><div>of ``RandomState`` does.  Because their intended use is for unit tests, we do</div><div>not need the performance improvements from the new algorithms that will be</div><div>introduced by the new subsystem.</div><div><br></div><div>The list of ``StableRandom`` methods should be chosen to support unit tests:</div><div><br></div><div>    * ``.randint()``</div><div>    * ``.uniform()``</div><div>    * ``.normal()``</div><div>    * ``.standard_normal()``</div><div>    * ``.choice()``</div><div>    * ``.shuffle()``</div><div>    * ``.permutation()``</div><div><br></div><div><br></div><div>Not Versioning</div><div>--------------</div><div><br></div><div>For a long time, we considered that the way to allow algorithmic improvements</div><div>while maintaining the stream was to apply some form of versioning.  That is,</div><div>every time we make a stream change in one of the distributions, we increment</div><div>some version number somewhere.  ``numpy.random`` would keep all past versions</div><div>of the code, and there would be a way to get the old versions.  Proposals of</div><div>how to do this exactly varied widely, but we will not exhaustively list them</div><div>here.  We spent years going back and forth on these designs and were not able</div><div>to find one that sufficed.  Let that time lost, and more importantly, the</div><div>contributors that we lost while we dithered, serve as evidence against the</div><div>notion.</div><div><br></div><div>Concretely, adding in versioning makes maintenance of ``numpy.random``</div><div>difficult.  Necessarily, we would be keeping lots of versions of the same code</div><div>around.  Adding a new algorithm safely would still be quite hard.</div><div><br></div><div>But most importantly, versioning is fundamentally difficult to *use* correctly.</div><div>We want to make it easy and straightforward to get the latest, fastest, best</div><div>versions of the distribution algorithms; otherwise, what's the point?  The way</div><div>to make that easy is to make the latest the default.  But the default will</div><div>necessarily change from release to release, so the user’s code would need to be</div><div>altered anyway to specify the specific version that one wants to replicate.</div><div><br></div><div>Adding in versioning to maintain stream-compatibility would still only provide</div><div>the same level of stream-compatibility that we currently do, with all of the</div><div>limitations described earlier.  Given that the standard practice for such needs</div><div>is to pin the release of ``numpy`` as a whole, versioning ``RandomState`` alone</div><div>is superfluous.</div><div><br></div><div><br></div><div>Discussion</div><div>----------</div><div><br></div><div>- <a href="https://mail.python.org/pipermail/numpy-discussion/2018-January/077608.html" target="_blank">https://mail.python.org/pipermail/numpy-discussion/2018-January/077608.html</a></div><div>- <a href="https://github.com/numpy/numpy/pull/10124#issuecomment-350876221" target="_blank">https://github.com/numpy/numpy/pull/10124#issuecomment-350876221</a></div><div><br></div><div><br></div><div>Copyright</div><div>---------</div><div><br></div><div>This document has been placed in the public domain.</div><div><br></div><div><br></div>-- <br><div dir="ltr" class="m_5522089087272890492gmail_signature">Robert Kern</div></div></div>
_______________________________________________<br>
NumPy-Discussion mailing list<br>
<a href="mailto:NumPy-Discussion@python.org" target="_blank">NumPy-Discussion@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/numpy-discussion</a><br>
</blockquote><p></p></div><p style="margin:1em 0px"></p>
<div title="MDH:WW91IG1ha2UgYSBidW5jaCBvZiBnb29kIHBvaW50cyByZWZ1dGluZyByZXByb2R1Y2libGUgcmVz
ZWFyY2ggYXMgYW4gYXJndW1lbnQgZm9yIG5vdCBjaGFuZ2luZyB0aGUgcmFuZG9tIG51bWJlciBz
dHJlYW1zLjxkaXY+PGJyPjwvZGl2PjxkaXY+SG93ZXZlciwgdGhlcmUncyBhIHNlY29uZCB1c2Ut
Y2FzZSB5b3UgZG9uJ3QgYWRkcmVzcyAtIHVuaXQgdGVzdHMuIEZvciBiZXR0ZXIgb3Igd29yc2Us
IGRvd25zdHJlYW0sIG9yIFtldmVuIG91ciBvd25dKDxhIGhyZWY9Imh0dHBzOi8vZ2l0aHViLmNv
bS9udW1weS9udW1weS9ibG9iL2M0ODEzYTkvbnVtcHkvY29yZS90ZXN0cy90ZXN0X211bHRpYXJy
YXkucHkjTDUwOTMtTDUxMDgiPmh0dHBzOi8vZ2l0aHViLmNvbS9udW1weS9udW1weS9ibG9iL2M0
ODEzYTkvbnVtcHkvY29yZS90ZXN0cy90ZXN0X211bHRpYXJyYXkucHkjTDUwOTMtTDUxMDg8L2E+
KSwgdW5pdCB0ZXN0cyB1c2UgYSBzZWVkZWQgcmFuZG9tIG51bWJlciBnZW5lcmF0b3IgYXMgYSBz
aG9ydGhhbmQgdG8gcHJvZHVjZSBzb21lIGFyYmlyYXJ5IGFycmF5LCBhbmQgdGhlbiBoYXJkLWNv
ZGUgdGhlIGV4cGVjdGVkIG91dHB1dCBpbiB0aGVpciB0ZXN0cy4gQnJlYWtpbmcgc3RyZWFtIGNv
bXBhdGliaWxpdHkgd2lsbCBicmVhayB0aGVzZSB0ZXN0cy48L2Rpdj48ZGl2Pjxicj48L2Rpdj48
ZGl2PkkgZG9uJ3QgdGhpbmsgd3JpdGluZyB0ZXN0cyBpbiB0aGlzIHdheSBpcyBwYXJ0aWN1bGFy
bHkgZ29vZCBpZGVhLCBidXQgdW5mb3J0dW5hdGVseSB0aGV5IGRvIHN0aWxsIGV4aXN0LjwvZGl2
PjxkaXY+PGJyPjwvZGl2PjxkaXY+SXQgd291bGQgYmUgZ29vZCB0byBhZGRyZXNzIHRoaXMgdXNl
IGNhc2UgaW4gdGhlIE5FUCwgZXZlbiBpZiB0aGUgY29uY2x1c2lvbiBpcyBqdXN0ICJjaGFuZ2lu
ZyB0aGUgc3RyZWFtIHdpbGwgYnJlYWsgdGVzdHMgb2YgdGhpcyBmb3JtIjwvZGl2PjxkaXY+PGJy
PjwvZGl2PjxkaXY+RXJpYzxicj48YnI+PGRpdiBjbGFzcz0iZ21haWxfcXVvdGUiPjxkaXYgZGly
PSJsdHIiPk9uIFNhdCwgMiBKdW4gMjAxOCBhdCAxMjowNSBSb2JlcnQgS2VybiAmbHQ7cm9iZXJ0
Lmtlcm5AZ21haWwuY29tJmd0OyB3cm90ZTo8YnI+PC9kaXY+PGJsb2NrcXVvdGUgY2xhc3M9Imdt
YWlsX3F1b3RlIiBzdHlsZT0ibWFyZ2luOjAgMCAwIC44ZXg7Ym9yZGVyLWxlZnQ6MXB4ICNjY2Mg
c29saWQ7cGFkZGluZy1sZWZ0OjFleDsiPjxkaXYgZGlyPSJsdHIiPkFzIHByb21pc2VkIGRpc3Ry
ZXNzaW5nbHkgbWFueSBtb250aHMgYWdvLCBJIGhhdmUgd3JpdHRlbiB1cCBhIE5FUCBhYm91dCBy
ZWxheGluZyB0aGUgc3RyZWFtLWNvbXBhdGliaWxpdHkgcG9saWN5IHRoYXQgd2UgY3VycmVudGx5
IGhhdmUuPGRpdj48YnI+PC9kaXY+PGRpdj48YSBocmVmPSJodHRwczovL2dpdGh1Yi5jb20vbnVt
cHkvbnVtcHkvcHVsbC8xMTIyOSIgdGFyZ2V0PSJfYmxhbmsiIGRhdGEtc2FmZXJlZGlyZWN0dXJs
PSJodHRwczovL3d3dy5nb29nbGUuY29tL3VybD9xPWh0dHBzOi8vZ2l0aHViLmNvbS9udW1weS9u
dW1weS9wdWxsLzExMjI5JmFtcDtzb3VyY2U9Z21haWwmYW1wO3VzdD0xNTI4MTQ0NjY5OTExMDAw
JmFtcDt1c2c9QUZRakNOSE0zRGJQd3plaTB6eWlZaXh5eG5jWG9nX1EzdyI+aHR0cHM6Ly9naXRo
dWIuY29tL251bXB5Lzx3YnI+bnVtcHkvcHVsbC8xMTIyOTwvYT48YnI+PC9kaXY+PGRpdj48YSBo
cmVmPSJodHRwczovL2dpdGh1Yi5jb20vcmtlcm4vbnVtcHkvYmxvYi9uZXAvcm5nL2RvYy9uZXBz
L25lcC0wMDE5LXJuZy1wb2xpY3kucnN0IiB0YXJnZXQ9Il9ibGFuayIgZGF0YS1zYWZlcmVkaXJl
Y3R1cmw9Imh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vdXJsP3E9aHR0cHM6Ly9naXRodWIuY29tL3Jr
ZXJuL251bXB5L2Jsb2IvbmVwL3JuZy9kb2MvbmVwcy9uZXAtMDAxOS1ybmctcG9saWN5LnJzdCZh
bXA7c291cmNlPWdtYWlsJmFtcDt1c3Q9MTUyODE0NDY2OTkxMTAwMCZhbXA7dXNnPUFGUWpDTkV4
THdJcEV3XzZXRmZxTkF6azZGdHJ1REdqMEEiPmh0dHBzOi8vZ2l0aHViLmNvbS9ya2Vybi88d2Jy
Pm51bXB5L2Jsb2IvbmVwL3JuZy9kb2MvbmVwcy88d2JyPm5lcC0wMDE5LXJuZy1wb2xpY3kucnN0
PC9hPjxicj48L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2PkkgcGFydGljdWxhcmx5IGludml0ZSBj
b21tZW50IG9uIHRoZSB0d28gbGlzdHMgb2YgbWV0aG9kcyB0aGF0IHdlIHN0aWxsIHdvdWxkIG1h
a2Ugc3RyaWN0IGNvbXBhdGliaWxpdHkgZ3VhcmFudGVlcyBmb3IuPC9kaXY+PGRpdj48YnI+PC9k
aXY+PGRpdj4tLS08L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2PjxkaXY+PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PC9kaXY+PGRpdj5SYW5kb20gTnVtYmVyIEdlbmVyYXRvciBQb2xpY3k8
L2Rpdj48ZGl2Pj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PTwvZGl2PjxkaXY+PGJyPjwv
ZGl2PjxkaXY+OkF1dGhvcjogUm9iZXJ0IEtlcm4gJmx0OzxhIGhyZWY9Im1haWx0bzpyb2JlcnQu
a2VybkBnbWFpbC5jb20iIHRhcmdldD0iX2JsYW5rIj5yb2JlcnQua2VybkBnbWFpbC5jb208L2E+
Jmd0OzwvZGl2PjxkaXY+OlN0YXR1czogRHJhZnQ8L2Rpdj48ZGl2PjpUeXBlOiBTdGFuZGFyZHMg
VHJhY2s8L2Rpdj48ZGl2PjpDcmVhdGVkOiAyMDE4LTA1LTI0PC9kaXY+PGRpdj48YnI+PC9kaXY+
PGRpdj48YnI+PC9kaXY+PGRpdj5BYnN0cmFjdDwvZGl2PjxkaXY+LS0tLS0tLS08L2Rpdj48ZGl2
Pjxicj48L2Rpdj48ZGl2PkZvciB0aGUgcGFzdCBkZWNhZGUsIE51bVB5IGhhcyBoYWQgYSBzdHJp
Y3QgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgcG9saWN5IGZvcjwvZGl2PjxkaXY+dGhlIG51bWJl
ciBzdHJlYW0gb2YgYWxsIG9mIGl0cyByYW5kb20gbnVtYmVyIGRpc3RyaWJ1dGlvbnMuJm5ic3A7
IFVubGlrZSBvdGhlcjwvZGl2PjxkaXY+bnVtZXJpY2FsIGNvbXBvbmVudHMgaW4gYGBudW1weWBg
LCB3aGljaCBhcmUgdXN1YWxseSBhbGxvd2VkIHRvIHJldHVybjwvZGl2PjxkaXY+ZGlmZmVyZW50
IHdoZW4gcmVzdWx0cyB3aGVuIHRoZXkgYXJlIG1vZGlmaWVkIGlmIHRoZXkgcmVtYWluIGNvcnJl
Y3QsIHdlIGhhdmU8L2Rpdj48ZGl2Pm9ibGlnYXRlZCB0aGUgcmFuZG9tIG51bWJlciBkaXN0cmli
dXRpb25zIHRvIGFsd2F5cyBwcm9kdWNlIHRoZSBleGFjdCBzYW1lPC9kaXY+PGRpdj5udW1iZXJz
IGluIGV2ZXJ5IHZlcnNpb24uJm5ic3A7IFRoZSBvYmplY3RpdmUgb2Ygb3VyIHN0cmVhbS1jb21w
YXRpYmlsaXR5IGd1YXJhbnRlZTwvZGl2PjxkaXY+d2FzIHRvIHByb3ZpZGUgZXhhY3QgcmVwcm9k
dWNpYmlsaXR5IGZvciBzaW11bGF0aW9ucyBhY3Jvc3MgbnVtcHkgdmVyc2lvbnMgaW48L2Rpdj48
ZGl2Pm9yZGVyIHRvIHByb21vdGUgcmVwcm9kdWNpYmxlIHJlc2VhcmNoLiZuYnNwOyBIb3dldmVy
LCB0aGlzIHBvbGljeSBoYXMgbWFkZSBpdCB2ZXJ5PC9kaXY+PGRpdj5kaWZmaWN1bHQgdG8gZW5o
YW5jZSBhbnkgb2YgdGhlIGRpc3RyaWJ1dGlvbnMgd2l0aCBmYXN0ZXIgb3IgbW9yZSBhY2N1cmF0
ZTwvZGl2PjxkaXY+YWxnb3JpdGhtcy4mbmJzcDsgQWZ0ZXIgYSBkZWNhZGUgb2YgZXhwZXJpZW5j
ZSBhbmQgaW1wcm92ZW1lbnRzIGluIHRoZSBzdXJyb3VuZGluZzwvZGl2PjxkaXY+ZWNvc3lzdGVt
IG9mIHNjaWVudGlmaWMgc29mdHdhcmUsIHdlIGJlbGlldmUgdGhhdCB0aGVyZSBhcmUgbm93IGJl
dHRlciB3YXlzIHRvPC9kaXY+PGRpdj5hY2hpZXZlIHRoZXNlIG9iamVjdGl2ZXMuJm5ic3A7IFdl
IHByb3Bvc2UgcmVsYXhpbmcgb3VyIHN0cmljdCBzdHJlYW0tY29tcGF0aWJpbGl0eTwvZGl2Pjxk
aXY+cG9saWN5IHRvIHJlbW92ZSB0aGUgb2JzdGFjbGVzIHRoYXQgYXJlIGluIHRoZSB3YXkgb2Yg
YWNjZXB0aW5nIGNvbnRyaWJ1dGlvbnM8L2Rpdj48ZGl2PnRvIG91ciByYW5kb20gbnVtYmVyIGdl
bmVyYXRpb24gY2FwYWJpbGl0aWVzLjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+PGJyPjwvZGl2
PjxkaXY+VGhlIFN0YXR1cyBRdW88L2Rpdj48ZGl2Pi0tLS0tLS0tLS0tLS0tPC9kaXY+PGRpdj48
YnI+PC9kaXY+PGRpdj5PdXIgY3VycmVudCBwb2xpY3ksIGluIGZ1bGw6PC9kaXY+PGRpdj48YnI+
PC9kaXY+PGRpdj4mbmJzcDsgJm5ic3A7IEEgZml4ZWQgc2VlZCBhbmQgYSBmaXhlZCBzZXJpZXMg
b2YgY2FsbHMgdG8gYGBSYW5kb21TdGF0ZWBgIG1ldGhvZHMgdXNpbmcgdGhlPC9kaXY+PGRpdj4m
bmJzcDsgJm5ic3A7IHNhbWUgcGFyYW1ldGVycyB3aWxsIGFsd2F5cyBwcm9kdWNlIHRoZSBzYW1l
IHJlc3VsdHMgdXAgdG8gcm91bmRvZmYgZXJyb3I8L2Rpdj48ZGl2PiZuYnNwOyAmbmJzcDsgZXhj
ZXB0IHdoZW4gdGhlIHZhbHVlcyB3ZXJlIGluY29ycmVjdC4mbmJzcDsgSW5jb3JyZWN0IHZhbHVl
cyB3aWxsIGJlIGZpeGVkIGFuZDwvZGl2PjxkaXY+Jm5ic3A7ICZuYnNwOyB0aGUgTnVtUHkgdmVy
c2lvbiBpbiB3aGljaCB0aGUgZml4IHdhcyBtYWRlIHdpbGwgYmUgbm90ZWQgaW4gdGhlIHJlbGV2
YW50PC9kaXY+PGRpdj4mbmJzcDsgJm5ic3A7IGRvY3N0cmluZy4mbmJzcDsgRXh0ZW5zaW9uIG9m
IGV4aXN0aW5nIHBhcmFtZXRlciByYW5nZXMgYW5kIHRoZSBhZGRpdGlvbiBvZiBuZXc8L2Rpdj48
ZGl2PiZuYnNwOyAmbmJzcDsgcGFyYW1ldGVycyBpcyBhbGxvd2VkIGFzIGxvbmcgdGhlIHByZXZp
b3VzIGJlaGF2aW9yIHJlbWFpbnMgdW5jaGFuZ2VkLjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+
VGhpcyBwb2xpY3kgd2FzIGZpcnN0IGluc3RhdGVkIGluIE5vdiAyMDA4IChpbiBlc3NlbmNlOyB0
aGUgZnVsbCBzZXQgb2Ygd2Vhc2VsPC9kaXY+PGRpdj53b3JkcyBncmV3IG92ZXIgdGltZSkgaW4g
cmVzcG9uc2UgdG8gYSB1c2VyIHdhbnRpbmcgdG8gYmUgc3VyZSB0aGF0IHRoZTwvZGl2PjxkaXY+
c2ltdWxhdGlvbnMgdGhhdCBmb3JtZWQgdGhlIGJhc2lzIG9mIHRoZWlyIHNjaWVudGlmaWMgcHVi
bGljYXRpb24gY291bGQgYmU8L2Rpdj48ZGl2PnJlcHJvZHVjZWQgeWVhcnMgbGF0ZXIsIGV4YWN0
bHksIHdpdGggd2hhdGV2ZXIgdmVyc2lvbiBvZiBgYG51bXB5YGAgdGhhdCB3YXM8L2Rpdj48ZGl2
PmN1cnJlbnQgYXQgdGhlIHRpbWUuJm5ic3A7IFdlIHdlcmUga2VlbiB0byBzdXBwb3J0IHJlcHJv
ZHVjaWJsZSByZXNlYXJjaCwgYW5kIGl0IHdhczwvZGl2PjxkaXY+c3RpbGwgZWFybHkgaW4gdGhl
IGxpZmUgb2YgYGBudW1weS5yYW5kb21gYC4mbmJzcDsgV2UgaGFkIG5vdCBzZWVuIG11Y2ggY2F1
c2UgdG88L2Rpdj48ZGl2PmNoYW5nZSB0aGUgZGlzdHJpYnV0aW9uIG1ldGhvZHMgYWxsIHRoYXQg
bXVjaC48L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2PldlIGFsc28gaGFkIG5vdCB0aG91Z2h0IHZl
cnkgdGhvcm91Z2hseSBhYm91dCB0aGUgbGltaXRzIG9mIHdoYXQgd2UgcmVhbGx5PC9kaXY+PGRp
dj5jb3VsZCBwcm9taXNlIChhbmQgYnkg4oCcd2XigJ0gaW4gdGhpcyBzZWN0aW9uLCB3ZSByZWFs
bHkgbWVhbiBSb2JlcnQgS2VybiwgbGV04oCZczwvZGl2PjxkaXY+YmUgaG9uZXN0KS4mbmJzcDsg
RGVzcGl0ZSBhbGwgb2YgdGhlIHdlYXNlbCB3b3Jkcywgb3VyIHBvbGljeSBvdmVycHJvbWlzZXM8
L2Rpdj48ZGl2PmNvbXBhdGliaWxpdHkuJm5ic3A7IFRoZSBzYW1lIHZlcnNpb24gb2YgYGBudW1w
eWBgIGJ1aWx0IG9uIGRpZmZlcmVudCBwbGF0Zm9ybXMsIG9yPC9kaXY+PGRpdj5qdXN0IGluIGEg
ZGlmZmVyZW50IHdheSBjb3VsZCBjYXVzZSBjaGFuZ2VzIGluIHRoZSBzdHJlYW0sIHdpdGggdmFy
eWluZyBkZWdyZWVzPC9kaXY+PGRpdj5vZiByYXJpdHkuJm5ic3A7IFRoZSBiaWdnZXN0IGlzIHRo
YXQgdGhlIGBgLm11bHRpdmFyaWF0ZV9ub3JtYWwoKWBgIG1ldGhvZCByZWxpZXMgb248L2Rpdj48
ZGl2PmBgbnVtcHkubGluYWxnYGAgZnVuY3Rpb25zLiZuYnNwOyBFdmVuIG9uIHRoZSBzYW1lIHBs
YXRmb3JtLCBpZiBvbmUgbGlua3MgYGBudW1weWBgPC9kaXY+PGRpdj53aXRoIGEgZGlmZmVyZW50
IExBUEFDSywgYGAubXVsdGl2YXJpYXRlX25vcm1hbCgpYGAgbWF5IHdlbGwgcmV0dXJuIGNvbXBs
ZXRlbHk8L2Rpdj48ZGl2PmRpZmZlcmVudCByZXN1bHRzLiZuYnNwOyBNb3JlIHJhcmVseSwgYnVp
bGRpbmcgb24gYSBkaWZmZXJlbnQgT1Mgb3IgQ1BVIGNhbiBjYXVzZTwvZGl2PjxkaXY+ZGlmZmVy
ZW5jZXMgaW4gdGhlIHN0cmVhbS4mbmJzcDsgV2UgdXNlIEMgYGBsb25nYGAgaW50ZWdlcnMgaW50
ZXJuYWxseSBmb3IgaW50ZWdlcjwvZGl2PjxkaXY+ZGlzdHJpYnV0aW9uIChpdCBzZWVtZWQgbGlr
ZSBhIGdvb2QgaWRlYSBhdCB0aGUgdGltZSksIGFuZCB0aG9zZSBjYW4gdmFyeSBpbjwvZGl2Pjxk
aXY+c2l6ZSBkZXBlbmRpbmcgb24gdGhlIHBsYXRmb3JtLiZuYnNwOyBEaXN0cmlidXRpb24gbWV0
aG9kcyBjYW4gb3ZlcmZsb3cgdGhlaXI8L2Rpdj48ZGl2PmludGVybmFsIEMgYGBsb25nc2BgIGF0
IGRpZmZlcmVudCBicmVha3BvaW50cyBkZXBlbmRpbmcgb24gdGhlIHBsYXRmb3JtIGFuZDwvZGl2
PjxkaXY+Y2F1c2UgYWxsIG9mIHRoZSByYW5kb20gdmFyaWF0ZSBkcmF3cyB0aGF0IGZvbGxvdyB0
byBiZSBkaWZmZXJlbnQuPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5BbmQgZXZlbiBpZiBhbGwg
b2YgdGhhdCBpcyBjb250cm9sbGVkLCBvdXIgcG9saWN5IHN0aWxsIGRvZXMgbm90IHByb3ZpZGUg
ZXhhY3Q8L2Rpdj48ZGl2Pmd1YXJhbnRlZXMgYWNyb3NzIHZlcnNpb25zLiZuYnNwOyBXZSBzdGls
bCBkbyBhcHBseSBidWcgZml4ZXMgd2hlbiBjb3JyZWN0bmVzcyBpcyBhdDwvZGl2PjxkaXY+c3Rh
a2UuJm5ic3A7IEFuZCBldmVuIGlmIHdlIGRpZG7igJl0IGRvIHRoYXQsIGFueSBub250cml2aWFs
IHByb2dyYW0gZG9lcyBtb3JlIHRoYW48L2Rpdj48ZGl2Pmp1c3QgZHJhdyByYW5kb20gbnVtYmVy
cy4mbmJzcDsgVGhleSBkbyBjb21wdXRhdGlvbnMgb24gdGhvc2UgbnVtYmVycywgdHJhbnNmb3Jt
PC9kaXY+PGRpdj50aG9zZSB3aXRoIG51bWVyaWNhbCBhbGdvcml0aG1zIGZyb20gdGhlIHJlc3Qg
b2YgYGBudW1weWBgLCB3aGljaCBpcyBub3Q8L2Rpdj48ZGl2PnN1YmplY3QgdG8gc28gc3RyaWN0
IGEgcG9saWN5LiZuYnNwOyBUcnlpbmcgdG8gbWFpbnRhaW4gc3RyZWFtLWNvbXBhdGliaWxpdHkg
Zm9yIG91cjwvZGl2PjxkaXY+cmFuZG9tIG51bWJlciBkaXN0cmlidXRpb25zIGRvZXMgbm90IGhl
bHAgcmVwcm9kdWNpYmxlIHJlc2VhcmNoIGZvciB0aGVzZTwvZGl2PjxkaXY+cmVhc29ucy48L2Rp
dj48ZGl2Pjxicj48L2Rpdj48ZGl2PlRoZSBzdGFuZGFyZCBwcmFjdGljZSBub3cgZm9yIGJpdC1m
b3ItYml0IHJlcHJvZHVjaWJsZSByZXNlYXJjaCBpcyB0byBwaW4gYWxsPC9kaXY+PGRpdj5vZiB0
aGUgdmVyc2lvbnMgb2YgY29kZSBvZiB5b3VyIHNvZnR3YXJlIHN0YWNrLCBwb3NzaWJseSBkb3du
IHRvIHRoZSBPUyBpdHNlbGYuPC9kaXY+PGRpdj5UaGUgbGFuZHNjYXBlIGZvciBhY2NvbXBsaXNo
aW5nIHRoaXMgaXMgbXVjaCBlYXNpZXIgdG9kYXkgdGhhbiBpdCB3YXMgaW4gMjAwOC48L2Rpdj48
ZGl2PldlIG5vdyBoYXZlIGBgcGlwYGAuJm5ic3A7IFdlIG5vdyBoYXZlIHZpcnR1YWwgbWFjaGlu
ZXMuJm5ic3A7IFRob3NlIHdobyBuZWVkIHRvPC9kaXY+PGRpdj5yZXByb2R1Y2Ugc2ltdWxhdGlv
bnMgZXhhY3RseSBub3cgY2FuIChhbmQgb3VnaHQgdG8pIGRvIHNvIGJ5IHVzaW5nIHRoZSBleGFj
dDwvZGl2PjxkaXY+c2FtZSB2ZXJzaW9uIG9mIGBgbnVtcHlgYC4mbmJzcDsgV2UgZG8gbm90IG5l
ZWQgdG8gbWFpbnRhaW4gc3RyZWFtLWNvbXBhdGliaWxpdHk8L2Rpdj48ZGl2PmFjcm9zcyBgYG51
bXB5YGAgdmVyc2lvbnMgdG8gaGVscCB0aGVtLjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+T3Vy
IHN0cmVhbS1jb21wYXRpYmlsaXR5IGd1YXJhbnRlZSBoYXMgaGluZGVyZWQgb3VyIGFiaWxpdHkg
dG8gbWFrZTwvZGl2PjxkaXY+aW1wcm92ZW1lbnRzIHRvIGBgbnVtcHkucmFuZG9tYGAuJm5ic3A7
IFNldmVyYWwgZmlyc3QtdGltZSBjb250cmlidXRvcnMgaGF2ZTwvZGl2PjxkaXY+c3VibWl0dGVk
IFBScyB0byBpbXByb3ZlIHRoZSBkaXN0cmlidXRpb25zLCB1c3VhbGx5IGJ5IGltcGxlbWVudGlu
ZyBhIGZhc3Rlciw8L2Rpdj48ZGl2Pm9yIG1vcmUgYWNjdXJhdGUgYWxnb3JpdGhtIHRoYW4gdGhl
IG9uZSB0aGF0IGlzIGN1cnJlbnRseSB0aGVyZS48L2Rpdj48ZGl2PlVuZm9ydHVuYXRlbHksIG1v
c3Qgb2YgdGhlbSB3b3VsZCBoYXZlIHJlcXVpcmVkIGJyZWFraW5nIHRoZSBzdHJlYW0gdG8gZG8g
c28uPC9kaXY+PGRpdj5CbG9ja2VkIGJ5IG91ciBwb2xpY3ksIGFuZCBvdXIgaW5hYmlsaXR5IHRv
IHdvcmsgYXJvdW5kIHRoYXQgcG9saWN5LCBtYW55IG9mPC9kaXY+PGRpdj50aG9zZSBjb250cmli
dXRvcnMgc2ltcGx5IHdhbGtlZCBhd2F5LjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+PGJyPjwv
ZGl2PjxkaXY+SW1wbGVtZW50YXRpb248L2Rpdj48ZGl2Pi0tLS0tLS0tLS0tLS0tPC9kaXY+PGRp
dj48YnI+PC9kaXY+PGRpdj5XZSBwcm9wb3NlIGZpcnN0IGZyZWV6aW5nIGBgUmFuZG9tU3RhdGVg
YCBhcyBpdCBpcyBhbmQgZGV2ZWxvcGluZyBhIG5ldyBSTkc8L2Rpdj48ZGl2PnN1YnN5c3RlbSBh
bG9uZ3NpZGUgaXQuJm5ic3A7IFRoaXMgYWxsb3dzIGFueW9uZSB3aG8gaGFzIGJlZW4gcmVseWlu
ZyBvbiBvdXIgb2xkPC9kaXY+PGRpdj5zdHJlYW0tY29tcGF0aWJpbGl0eSBndWFyYW50ZWUgdG8g
aGF2ZSBwbGVudHkgb2YgdGltZSB0byBtaWdyYXRlLjwvZGl2PjxkaXY+YGBSYW5kb21TdGF0ZWBg
IHdpbGwgYmUgY29uc2lkZXJlZCBkZXByZWNhdGVkLCBidXQgd2l0aCBhIGxvbmcgZGVwcmVjYXRp
b248L2Rpdj48ZGl2PmN5Y2xlLCBhdCBsZWFzdCBhIGZldyB5ZWFycy4mbmJzcDsgRGVwcmVjYXRp
b24gd2FybmluZ3Mgd2lsbCBzdGFydCBzaWxlbnQgYnV0IGJlY29tZTwvZGl2PjxkaXY+aW5jcmVh
c2luZ2x5IG5vaXN5IG92ZXIgdGltZS4mbmJzcDsgQnVncyBpbiB0aGUgY3VycmVudCBzdGF0ZSBv
ZiB0aGUgY29kZSB3aWxsICpub3QqPC9kaXY+PGRpdj5iZSBmaXhlZCBpZiBmaXhpbmcgdGhlbSB3
b3VsZCBpbXBhY3QgdGhlIHN0cmVhbS4mbmJzcDsgSG93ZXZlciwgaWYgY2hhbmdlcyBpbiB0aGU8
L2Rpdj48ZGl2PnJlc3Qgb2YgYGBudW1weWBgIHdvdWxkIGJyZWFrIHNvbWV0aGluZyBpbiB0aGUg
YGBSYW5kb21TdGF0ZWBgIGNvZGUsIHdlIHdpbGw8L2Rpdj48ZGl2PmZpeCBgYFJhbmRvbVN0YXRl
YGAgdG8gY29udGludWUgd29ya2luZyAoZm9yIGV4YW1wbGUsIHNvbWUgY2hhbmdlIGluIHRoZTwv
ZGl2PjxkaXY+QyBBUEkpLiZuYnNwOyBObyBuZXcgZmVhdHVyZXMgd2lsbCBiZSBhZGRlZCB0byBg
YFJhbmRvbVN0YXRlYGAuJm5ic3A7IFVzZXJzIHNob3VsZDwvZGl2PjxkaXY+bWlncmF0ZSB0byB0
aGUgbmV3IHN1YnN5c3RlbSBhcyB0aGV5IGFyZSBhYmxlIHRvLjwvZGl2PjxkaXY+PGJyPjwvZGl2
PjxkaXY+V29yayBvbiBhIHByb3Bvc2VkIGBuZXcgUFJORyBzdWJzeXN0ZW08L2Rpdj48ZGl2PiZs
dDs8YSBocmVmPSJodHRwczovL2dpdGh1Yi5jb20vYmFzaHRhZ2UvcmFuZG9tZ2VuIiB0YXJnZXQ9
Il9ibGFuayIgZGF0YS1zYWZlcmVkaXJlY3R1cmw9Imh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vdXJs
P3E9aHR0cHM6Ly9naXRodWIuY29tL2Jhc2h0YWdlL3JhbmRvbWdlbiZhbXA7c291cmNlPWdtYWls
JmFtcDt1c3Q9MTUyODE0NDY2OTkxMTAwMCZhbXA7dXNnPUFGUWpDTkhtV09wbVZTRU5hWlhvSnFh
QUNoQmxUc1VDWUEiPmh0dHBzOi8vZ2l0aHViLmNvbS9iYXNodGFnZS88d2JyPnJhbmRvbWdlbjwv
YT4mZ3Q7YF8gaXMgYWxyZWFkeSB1bmRlcndheS4mbmJzcDsgVGhlIHNwZWNpZmljczwvZGl2Pjxk
aXY+b2YgdGhlIG5ldyBkZXNpZ24gYXJlIG91dCBvZiBzY29wZSBmb3IgdGhpcyBORVAgYW5kIHVw
IGZvciBtdWNoIGRpc2N1c3Npb24sIGJ1dDwvZGl2PjxkaXY+d2Ugd2lsbCBkaXNjdXNzIGdlbmVy
YWwgcG9saWNpZXMgdGhhdCB3aWxsIGd1aWRlIHRoZSBldm9sdXRpb24gb2Ygd2hhdGV2ZXIgY29k
ZTwvZGl2PjxkaXY+aXMgYWRvcHRlZC48L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2PkZpcnN0LCB3
ZSB3aWxsIG1haW50YWluIEFQSSBzb3VyY2UgY29tcGF0aWJpbGl0eSBqdXN0IGFzIHdlIGRvIHdp
dGggdGhlIHJlc3Qgb2Y8L2Rpdj48ZGl2PmBgbnVtcHlgYC4mbmJzcDsgSWYgd2UgKm11c3QqIG1h
a2UgYSBicmVha2luZyBjaGFuZ2UsIHdlIHdpbGwgb25seSBkbyBzbyB3aXRoIGFuPC9kaXY+PGRp
dj5hcHByb3ByaWF0ZSBkZXByZWNhdGlvbiBwZXJpb2QgYW5kIHdhcm5pbmdzLjwvZGl2PjxkaXY+
PGJyPjwvZGl2PjxkaXY+U2Vjb25kLCBicmVha2luZyBzdHJlYW0tY29tcGF0aWJpbGl0eSBpbiBv
cmRlciB0byBpbnRyb2R1Y2UgbmV3IGZlYXR1cmVzIG9yPC9kaXY+PGRpdj5pbXByb3ZlIHBlcmZv
cm1hbmNlIHdpbGwgYmUgKmFsbG93ZWQqIHdpdGggKmNhdXRpb24qLiZuYnNwOyBTdWNoIGNoYW5n
ZXMgd2lsbCBiZTwvZGl2PjxkaXY+Y29uc2lkZXJlZCBmZWF0dXJlcywgYW5kIGFzIHN1Y2ggd2ls
bCBiZSBubyBmYXN0ZXIgdGhhbiB0aGUgc3RhbmRhcmQgcmVsZWFzZTwvZGl2PjxkaXY+Y2FkZW5j
ZSBvZiBmZWF0dXJlcyAoaS5lLiBvbiBgYFguWWBgIHJlbGVhc2VzLCBuZXZlciBgYFguWS5aYGAp
LiZuYnNwOyBTbG93bmVzcyBpczwvZGl2PjxkaXY+bm90IGEgYnVnLiZuYnNwOyBDb3JyZWN0bmVz
cyBidWcgZml4ZXMgdGhhdCBicmVhayBzdHJlYW0tY29tcGF0aWJpbGl0eSBjYW4gaGFwcGVuIG9u
PC9kaXY+PGRpdj5idWdmaXggcmVsZWFzZXMsIHBlciB1c3VhbCwgYnV0IGRldmVsb3BlcnMgc2hv
dWxkIGNvbnNpZGVyIGlmIHRoZXkgY2FuIHdhaXQ8L2Rpdj48ZGl2PnVudGlsIHRoZSBuZXh0IGZl
YXR1cmUgcmVsZWFzZS4mbmJzcDsgV2UgZW5jb3VyYWdlIGRldmVsb3BlcnMgdG8gc3Ryb25nbHkg
d2VpZ2h0PC9kaXY+PGRpdj51c2Vy4oCZcyBwYWluIGZyb20gdGhlIGJyZWFrIGluIHN0cmVhbS1j
b21wYXRpYmlsaXR5IGFnYWluc3QgdGhlIGltcHJvdmVtZW50cy48L2Rpdj48ZGl2Pk9uZSBleGFt
cGxlIG9mIGEgd29ydGh3aGlsZSBpbXByb3ZlbWVudCB3b3VsZCBiZSB0byBjaGFuZ2UgYWxnb3Jp
dGhtcyBmb3I8L2Rpdj48ZGl2PmEgc2lnbmlmaWNhbnQgaW5jcmVhc2UgaW4gcGVyZm9ybWFuY2Us
IGZvciBleGFtcGxlLCBtb3ZpbmcgZnJvbSB0aGUgYEJveC1NdWxsZXI8L2Rpdj48ZGl2PnRyYW5z
Zm9ybSAmbHQ7PGEgaHJlZj0iaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQm94JUUyJTgw
JTkzTXVsbGVyX3RyYW5zZm9ybSIgdGFyZ2V0PSJfYmxhbmsiIGRhdGEtc2FmZXJlZGlyZWN0dXJs
PSJodHRwczovL3d3dy5nb29nbGUuY29tL3VybD9xPWh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93
aWtpL0JveCUyNUUyJTI1ODAlMjU5M011bGxlcl90cmFuc2Zvcm0mYW1wO3NvdXJjZT1nbWFpbCZh
bXA7dXN0PTE1MjgxNDQ2Njk5MTEwMDAmYW1wO3VzZz1BRlFqQ05Fczk2NUVuTy1TbGFBdzhqSS1k
WjViSmFYSm93Ij5odHRwczovL2VuLndpa2lwZWRpYS5vcmcvPHdicj53aWtpL0JveCVFMiU4MCU5
M011bGxlcl88d2JyPnRyYW5zZm9ybTwvYT4mZ3Q7YF8gbWV0aG9kPC9kaXY+PGRpdj5vZiBHYXVz
c2lhbiB2YXJpYXRlIGdlbmVyYXRpb24gdG8gdGhlIGZhc3RlciBgWmlnZ3VyYXQgYWxnb3JpdGht
PC9kaXY+PGRpdj4mbHQ7PGEgaHJlZj0iaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvWmln
Z3VyYXRfYWxnb3JpdGhtIiB0YXJnZXQ9Il9ibGFuayIgZGF0YS1zYWZlcmVkaXJlY3R1cmw9Imh0
dHBzOi8vd3d3Lmdvb2dsZS5jb20vdXJsP3E9aHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kv
WmlnZ3VyYXRfYWxnb3JpdGhtJmFtcDtzb3VyY2U9Z21haWwmYW1wO3VzdD0xNTI4MTQ0NjY5OTEx
MDAwJmFtcDt1c2c9QUZRakNOR3hhZXp1RFV5NlZkYjJuM2NCMHJ4YllHeVBidyI+aHR0cHM6Ly9l
bi53aWtpcGVkaWEub3JnLzx3YnI+d2lraS9aaWdndXJhdF9hbGdvcml0aG08L2E+Jmd0O2BfLiZu
YnNwOyBBbiBleGFtcGxlIG9mIGFuPC9kaXY+PGRpdj51bndvcnRoeSBpbXByb3ZlbWVudCB3b3Vs
ZCBiZSB0d2Vha2luZyB0aGUgWmlnZ3VyYXQgdGFibGVzIGp1c3QgYSBsaXR0bGUgYml0LjwvZGl2
PjxkaXY+PGJyPjwvZGl2PjxkaXY+QW55IG5ldyBkZXNpZ24gZm9yIHRoZSBSTkcgc3Vic3lzdGVt
IHdpbGwgcHJvdmlkZSBhIGNob2ljZSBvZiBkaWZmZXJlbnQgY29yZTwvZGl2PjxkaXY+dW5pZm9y
bSBQUk5HIGFsZ29yaXRobXMuJm5ic3A7IFdlIHdpbGwgYmUgbW9yZSBzdHJpY3QgYWJvdXQgYSBz
ZWxlY3Qgc3Vic2V0IG9mPC9kaXY+PGRpdj5tZXRob2RzIG9uIHRoZXNlIGNvcmUgUFJORyBvYmpl
Y3RzLiZuYnNwOyBUaGV5IE1VU1QgZ3VhcmFudGVlIHN0cmVhbS1jb21wYXRpYmlsaXR5PC9kaXY+
PGRpdj5mb3IgYSBtaW5pbWFsLCBzcGVjaWZpZWQgc2V0IG9mIG1ldGhvZHMgd2hpY2ggYXJlIGNo
b3NlbiB0byBtYWtlIGl0IGVhc2llciB0bzwvZGl2PjxkaXY+Y29tcG9zZSB0aGVtIHRvIGJ1aWxk
IG90aGVyIGRpc3RyaWJ1dGlvbnMuJm5ic3A7IE5hbWVseSw8L2Rpdj48ZGl2Pjxicj48L2Rpdj48
ZGl2PiZuYnNwOyAmbmJzcDsgKiBgYC5ieXRlcygpYGA8L2Rpdj48ZGl2PiZuYnNwOyAmbmJzcDsg
KiBgYC5yYW5kb21fdWludGVnZXJzKClgYDwvZGl2PjxkaXY+Jm5ic3A7ICZuYnNwOyAqIGBgLnJh
bmRvbV9zYW1wbGUoKWBgPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5GdXJ0aGVybW9yZSwgdGhl
IG5ldyBkZXNpZ24gc2hvdWxkIGFsc28gcHJvdmlkZSBvbmUgZ2VuZXJhdG9yIGNsYXNzICh3ZSBz
aGFsbDwvZGl2PjxkaXY+Y2FsbCBpdCBgYFN0YWJsZVJhbmRvbWBgIGZvciBkaXNjdXNzaW9uIHB1
cnBvc2VzKSB0aGF0IHByb3ZpZGVzIGEgc2xpZ2h0bHk8L2Rpdj48ZGl2PmJyb2FkZXIgc3Vic2V0
IG9mIGRpc3RyaWJ1dGlvbiBtZXRob2RzIGZvciB3aGljaCBzdHJlYW0tY29tcGF0aWJpbGl0eSBp
czwvZGl2PjxkaXY+Kmd1YXJhbnRlZWQqLiZuYnNwOyBUaGUgcG9pbnQgb2YgYGBTdGFibGVSYW5k
b21gYCBpcyB0byBwcm92aWRlIHNvbWV0aGluZyB0aGF0IGNhbjwvZGl2PjxkaXY+YmUgdXNlZCBp
biB1bml0IHRlc3RzIHNvIHByb2plY3RzIHRoYXQgY3VycmVudGx5IGhhdmUgdGVzdHMgd2hpY2gg
cmVseSBvbiB0aGU8L2Rpdj48ZGl2PnByZWNpc2Ugc3RyZWFtIGNhbiBiZSBtaWdyYXRlZCBvZmYg
b2YgYGBSYW5kb21TdGF0ZWBgLiZuYnNwOyBGb3IgdGhlIGJlc3Q8L2Rpdj48ZGl2PnRyYW5zaXRp
b24sIGBgU3RhYmxlUmFuZG9tYGAgc2hvdWxkIHVzZSBhcyBpdHMgY29yZSB1bmlmb3JtIFBSTkcg
dGhlIGN1cnJlbnQ8L2Rpdj48ZGl2Pk1UMTk5MzcgYWxnb3JpdGhtLiZuYnNwOyBBcyBiZXN0IGFz
IHBvc3NpYmxlLCB0aGUgQVBJIGZvciB0aGUgZGlzdHJpYnV0aW9uIG1ldGhvZHM8L2Rpdj48ZGl2
PnRoYXQgYXJlIHByb3ZpZGVkIG9uIGBgU3RhYmxlUmFuZG9tYGAgc2hvdWxkIG1hdGNoIHRoZWly
IGNvdW50ZXJwYXJ0cyBvbjwvZGl2PjxkaXY+YGBSYW5kb21TdGF0ZWBgLiZuYnNwOyBUaGV5IHNo
b3VsZCBwcm92aWRlIHRoZSBzYW1lIHN0cmVhbSB0aGF0IHRoZSBjdXJyZW50IHZlcnNpb248L2Rp
dj48ZGl2Pm9mIGBgUmFuZG9tU3RhdGVgYCBkb2VzLiZuYnNwOyBCZWNhdXNlIHRoZWlyIGludGVu
ZGVkIHVzZSBpcyBmb3IgdW5pdCB0ZXN0cywgd2UgZG88L2Rpdj48ZGl2Pm5vdCBuZWVkIHRoZSBw
ZXJmb3JtYW5jZSBpbXByb3ZlbWVudHMgZnJvbSB0aGUgbmV3IGFsZ29yaXRobXMgdGhhdCB3aWxs
IGJlPC9kaXY+PGRpdj5pbnRyb2R1Y2VkIGJ5IHRoZSBuZXcgc3Vic3lzdGVtLjwvZGl2PjxkaXY+
PGJyPjwvZGl2PjxkaXY+VGhlIGxpc3Qgb2YgYGBTdGFibGVSYW5kb21gYCBtZXRob2RzIHNob3Vs
ZCBiZSBjaG9zZW4gdG8gc3VwcG9ydCB1bml0IHRlc3RzOjwvZGl2PjxkaXY+PGJyPjwvZGl2Pjxk
aXY+Jm5ic3A7ICZuYnNwOyAqIGBgLnJhbmRpbnQoKWBgPC9kaXY+PGRpdj4mbmJzcDsgJm5ic3A7
ICogYGAudW5pZm9ybSgpYGA8L2Rpdj48ZGl2PiZuYnNwOyAmbmJzcDsgKiBgYC5ub3JtYWwoKWBg
PC9kaXY+PGRpdj4mbmJzcDsgJm5ic3A7ICogYGAuc3RhbmRhcmRfbm9ybWFsKClgYDwvZGl2Pjxk
aXY+Jm5ic3A7ICZuYnNwOyAqIGBgLmNob2ljZSgpYGA8L2Rpdj48ZGl2PiZuYnNwOyAmbmJzcDsg
KiBgYC5zaHVmZmxlKClgYDwvZGl2PjxkaXY+Jm5ic3A7ICZuYnNwOyAqIGBgLnBlcm11dGF0aW9u
KClgYDwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+Tm90IFZlcnNpb25p
bmc8L2Rpdj48ZGl2Pi0tLS0tLS0tLS0tLS0tPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5Gb3Ig
YSBsb25nIHRpbWUsIHdlIGNvbnNpZGVyZWQgdGhhdCB0aGUgd2F5IHRvIGFsbG93IGFsZ29yaXRo
bWljIGltcHJvdmVtZW50czwvZGl2PjxkaXY+d2hpbGUgbWFpbnRhaW5pbmcgdGhlIHN0cmVhbSB3
YXMgdG8gYXBwbHkgc29tZSBmb3JtIG9mIHZlcnNpb25pbmcuJm5ic3A7IFRoYXQgaXMsPC9kaXY+
PGRpdj5ldmVyeSB0aW1lIHdlIG1ha2UgYSBzdHJlYW0gY2hhbmdlIGluIG9uZSBvZiB0aGUgZGlz
dHJpYnV0aW9ucywgd2UgaW5jcmVtZW50PC9kaXY+PGRpdj5zb21lIHZlcnNpb24gbnVtYmVyIHNv
bWV3aGVyZS4mbmJzcDsgYGBudW1weS5yYW5kb21gYCB3b3VsZCBrZWVwIGFsbCBwYXN0IHZlcnNp
b25zPC9kaXY+PGRpdj5vZiB0aGUgY29kZSwgYW5kIHRoZXJlIHdvdWxkIGJlIGEgd2F5IHRvIGdl
dCB0aGUgb2xkIHZlcnNpb25zLiZuYnNwOyBQcm9wb3NhbHMgb2Y8L2Rpdj48ZGl2PmhvdyB0byBk
byB0aGlzIGV4YWN0bHkgdmFyaWVkIHdpZGVseSwgYnV0IHdlIHdpbGwgbm90IGV4aGF1c3RpdmVs
eSBsaXN0IHRoZW08L2Rpdj48ZGl2PmhlcmUuJm5ic3A7IFdlIHNwZW50IHllYXJzIGdvaW5nIGJh
Y2sgYW5kIGZvcnRoIG9uIHRoZXNlIGRlc2lnbnMgYW5kIHdlcmUgbm90IGFibGU8L2Rpdj48ZGl2
PnRvIGZpbmQgb25lIHRoYXQgc3VmZmljZWQuJm5ic3A7IExldCB0aGF0IHRpbWUgbG9zdCwgYW5k
IG1vcmUgaW1wb3J0YW50bHksIHRoZTwvZGl2PjxkaXY+Y29udHJpYnV0b3JzIHRoYXQgd2UgbG9z
dCB3aGlsZSB3ZSBkaXRoZXJlZCwgc2VydmUgYXMgZXZpZGVuY2UgYWdhaW5zdCB0aGU8L2Rpdj48
ZGl2Pm5vdGlvbi48L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2PkNvbmNyZXRlbHksIGFkZGluZyBp
biB2ZXJzaW9uaW5nIG1ha2VzIG1haW50ZW5hbmNlIG9mIGBgbnVtcHkucmFuZG9tYGA8L2Rpdj48
ZGl2PmRpZmZpY3VsdC4mbmJzcDsgTmVjZXNzYXJpbHksIHdlIHdvdWxkIGJlIGtlZXBpbmcgbG90
cyBvZiB2ZXJzaW9ucyBvZiB0aGUgc2FtZSBjb2RlPC9kaXY+PGRpdj5hcm91bmQuJm5ic3A7IEFk
ZGluZyBhIG5ldyBhbGdvcml0aG0gc2FmZWx5IHdvdWxkIHN0aWxsIGJlIHF1aXRlIGhhcmQuPC9k
aXY+PGRpdj48YnI+PC9kaXY+PGRpdj5CdXQgbW9zdCBpbXBvcnRhbnRseSwgdmVyc2lvbmluZyBp
cyBmdW5kYW1lbnRhbGx5IGRpZmZpY3VsdCB0byAqdXNlKiBjb3JyZWN0bHkuPC9kaXY+PGRpdj5X
ZSB3YW50IHRvIG1ha2UgaXQgZWFzeSBhbmQgc3RyYWlnaHRmb3J3YXJkIHRvIGdldCB0aGUgbGF0
ZXN0LCBmYXN0ZXN0LCBiZXN0PC9kaXY+PGRpdj52ZXJzaW9ucyBvZiB0aGUgZGlzdHJpYnV0aW9u
IGFsZ29yaXRobXM7IG90aGVyd2lzZSwgd2hhdCdzIHRoZSBwb2ludD8mbmJzcDsgVGhlIHdheTwv
ZGl2PjxkaXY+dG8gbWFrZSB0aGF0IGVhc3kgaXMgdG8gbWFrZSB0aGUgbGF0ZXN0IHRoZSBkZWZh
dWx0LiZuYnNwOyBCdXQgdGhlIGRlZmF1bHQgd2lsbDwvZGl2PjxkaXY+bmVjZXNzYXJpbHkgY2hh
bmdlIGZyb20gcmVsZWFzZSB0byByZWxlYXNlLCBzbyB0aGUgdXNlcuKAmXMgY29kZSB3b3VsZCBu
ZWVkIHRvIGJlPC9kaXY+PGRpdj5hbHRlcmVkIGFueXdheSB0byBzcGVjaWZ5IHRoZSBzcGVjaWZp
YyB2ZXJzaW9uIHRoYXQgb25lIHdhbnRzIHRvIHJlcGxpY2F0ZS48L2Rpdj48ZGl2Pjxicj48L2Rp
dj48ZGl2PkFkZGluZyBpbiB2ZXJzaW9uaW5nIHRvIG1haW50YWluIHN0cmVhbS1jb21wYXRpYmls
aXR5IHdvdWxkIHN0aWxsIG9ubHkgcHJvdmlkZTwvZGl2PjxkaXY+dGhlIHNhbWUgbGV2ZWwgb2Yg
c3RyZWFtLWNvbXBhdGliaWxpdHkgdGhhdCB3ZSBjdXJyZW50bHkgZG8sIHdpdGggYWxsIG9mIHRo
ZTwvZGl2PjxkaXY+bGltaXRhdGlvbnMgZGVzY3JpYmVkIGVhcmxpZXIuJm5ic3A7IEdpdmVuIHRo
YXQgdGhlIHN0YW5kYXJkIHByYWN0aWNlIGZvciBzdWNoIG5lZWRzPC9kaXY+PGRpdj5pcyB0byBw
aW4gdGhlIHJlbGVhc2Ugb2YgYGBudW1weWBgIGFzIGEgd2hvbGUsIHZlcnNpb25pbmcgYGBSYW5k
b21TdGF0ZWBgIGFsb25lPC9kaXY+PGRpdj5pcyBzdXBlcmZsdW91cy48L2Rpdj48ZGl2Pjxicj48
L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2PkRpc2N1c3Npb248L2Rpdj48ZGl2Pi0tLS0tLS0tLS08
L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2Pi0gPGEgaHJlZj0iaHR0cHM6Ly9tYWlsLnB5dGhvbi5v
cmcvcGlwZXJtYWlsL251bXB5LWRpc2N1c3Npb24vMjAxOC1KYW51YXJ5LzA3NzYwOC5odG1sIiB0
YXJnZXQ9Il9ibGFuayIgZGF0YS1zYWZlcmVkaXJlY3R1cmw9Imh0dHBzOi8vd3d3Lmdvb2dsZS5j
b20vdXJsP3E9aHR0cHM6Ly9tYWlsLnB5dGhvbi5vcmcvcGlwZXJtYWlsL251bXB5LWRpc2N1c3Np
b24vMjAxOC1KYW51YXJ5LzA3NzYwOC5odG1sJmFtcDtzb3VyY2U9Z21haWwmYW1wO3VzdD0xNTI4
MTQ0NjY5OTExMDAwJmFtcDt1c2c9QUZRakNORXJQR2laUkdaUHNZMno4ZVlDR2hJMXpyNWVEdyI+
aHR0cHM6Ly9tYWlsLnB5dGhvbi5vcmcvPHdicj5waXBlcm1haWwvbnVtcHktZGlzY3Vzc2lvbi88
d2JyPjIwMTgtSmFudWFyeS8wNzc2MDguaHRtbDwvYT48L2Rpdj48ZGl2Pi0gPGEgaHJlZj0iaHR0
cHM6Ly9naXRodWIuY29tL251bXB5L251bXB5L3B1bGwvMTAxMjQjaXNzdWVjb21tZW50LTM1MDg3
NjIyMSIgdGFyZ2V0PSJfYmxhbmsiIGRhdGEtc2FmZXJlZGlyZWN0dXJsPSJodHRwczovL3d3dy5n
b29nbGUuY29tL3VybD9xPWh0dHBzOi8vZ2l0aHViLmNvbS9udW1weS9udW1weS9wdWxsLzEwMTI0
JTIzaXNzdWVjb21tZW50LTM1MDg3NjIyMSZhbXA7c291cmNlPWdtYWlsJmFtcDt1c3Q9MTUyODE0
NDY2OTkxMTAwMCZhbXA7dXNnPUFGUWpDTkdteGExUUdnRUJIYVVuTlB1Z2tvNEVhQWpyVXciPmh0
dHBzOi8vZ2l0aHViLmNvbS9udW1weS88d2JyPm51bXB5L3B1bGwvMTAxMjQjaXNzdWVjb21tZW50
LTx3YnI+MzUwODc2MjIxPC9hPjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+PGJyPjwvZGl2Pjxk
aXY+Q29weXJpZ2h0PC9kaXY+PGRpdj4tLS0tLS0tLS08L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2
PlRoaXMgZG9jdW1lbnQgaGFzIGJlZW4gcGxhY2VkIGluIHRoZSBwdWJsaWMgZG9tYWluLjwvZGl2
PjxkaXY+PGJyPjwvZGl2PjxkaXY+PGJyPjwvZGl2Pi0tIDxicj48ZGl2IGRpcj0ibHRyIiBjbGFz
cz0ibV81NTIyMDg5MDg3MjcyODkwNDkyZ21haWxfc2lnbmF0dXJlIj5Sb2JlcnQgS2VybjwvZGl2
PjwvZGl2PjwvZGl2PgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX188d2JyPl9fX19fX19f
X19fX19fX19fPGJyPgpOdW1QeS1EaXNjdXNzaW9uIG1haWxpbmcgbGlzdDxicj4KPGEgaHJlZj0i
bWFpbHRvOk51bVB5LURpc2N1c3Npb25AcHl0aG9uLm9yZyIgdGFyZ2V0PSJfYmxhbmsiPk51bVB5
LURpc2N1c3Npb25AcHl0aG9uLm9yZzwvYT48YnI+CjxhIGhyZWY9Imh0dHBzOi8vbWFpbC5weXRo
b24ub3JnL21haWxtYW4vbGlzdGluZm8vbnVtcHktZGlzY3Vzc2lvbiIgcmVsPSJub3JlZmVycmVy
IiB0YXJnZXQ9Il9ibGFuayIgZGF0YS1zYWZlcmVkaXJlY3R1cmw9Imh0dHBzOi8vd3d3Lmdvb2ds
ZS5jb20vdXJsP3E9aHR0cHM6Ly9tYWlsLnB5dGhvbi5vcmcvbWFpbG1hbi9saXN0aW5mby9udW1w
eS1kaXNjdXNzaW9uJmFtcDtzb3VyY2U9Z21haWwmYW1wO3VzdD0xNTI4MTQ0NjY5OTExMDAwJmFt
cDt1c2c9QUZRakNOSHRtbGhzMHZBeGxmU3FJalJCYjVBcVhGVG9KdyI+aHR0cHM6Ly9tYWlsLnB5
dGhvbi5vcmcvbWFpbG1hPHdicj5uL2xpc3RpbmZvL251bXB5LWRpc2N1c3Npb248L2E+PGJyPgo8
L2Jsb2NrcXVvdGU+PC9kaXY+PC9kaXY+" style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0">​</div></div></div>