retronym / scalac-stability

Test cases for unstable output of Scalac
2 stars 0 forks source link

Gather more test cases and a better working definition of "stability" #1

Open retronym opened 6 years ago

retronym commented 6 years ago

I'm gathering test cases for unstable output for Scalac with a view to improving the compiler to make them stable. See the README for the tests I've come up with so far.

This ticket is a 🦇 -signal to some people that might be interested in this effort, and hopefully might be able to help me come up with additional test cases.

I'm also interested in what "stability" means to you.

@dragos (who fixed an bug if this ilk in https://github.com/scala/scala/pull/5965 and might be able to exploit from stability in https://triplequote.com/hydra) @johnynek @ittaiz (from https://github.com/bazelbuild/rules_scala) @jvican (from Scala Center, and who I recall is interested in this topic) @eed3si9n / @dwijnand (from sbt)

dragos commented 6 years ago

Great initiative! I have a WIP branch for lamdbalift ordering, I thought I filed a ticket already but it seems I missed it. Anyway, maybe this helps: https://github.com/dragos/scala/commit/7c0f351f61e84ab72c97101b1e6481633e1ba30d

dragos commented 6 years ago

Stability, for us, means that bytecode should be identical for the same inputs, where "same" allows some minor differences:

johnynek commented 6 years ago

I would like a bit simpler (I think) definition. To have a resident compiler in bazel, we have a process that bazel manages (called a "worker") that gets passed the arguments to the compiler run. We then allocate a new scala.tools.nsc.MainClass and just pass it Array[String] args to the process method:

https://github.com/bazelbuild/rules_scala/blob/master/src/java/io/bazel/rulesscala/scalac/ScalacProcessor.java#L237

I would like the contract that if you do this multiple times, if the input args are identical (that Array[String]), then the output to be bit-for-bit identical (and for the names of the files generated to be identical).

Note, this is not currently true for us. We occasionally see reproducibility bugs (as we call them) and have yet to diagnose the cause.

In the most extreme case, bazel took the output from a scalac that did not error, but the jar we got was incorrect, such that downstream compilations failed. But bazel didn't rerun the compilation because its inputs had not changed (and it even got cached on our CI).

We don't know if this bug is in bazel (highly unlikely since google uses it at such scale and does heavily cache), in the bazel scala rules somehow (again, we can't see how we can mess it up, but it of course is possible), or if scalac has some state that is not removed by allocating a new MainClass. It is very hard for us to be sure about the last one.

eed3si9n commented 6 years ago

I think any effort towards making compilation a pure function would be great. For the big picture/why, this matters for the purpose of both caching and verification. https://reproducible-builds.org/ says:

Reproducible builds are a set of software development practices that create a verifiable path from human readable source code to the binary code used by computers.

Related to this might be various use of timestamps that might sneak into the final product, like in JAR (https://github.com/sbt/io/pull/58). It would be nice to get good performance on incremental compilation while keeping these properties.

johnynek commented 6 years ago

we definitely zero out the timestamps in bazel when creating jars, but perhaps there could be some non-determinism in the class files.

We have a test for reproducibility in the bazel rules_scala, and it passes. But like I said, internally at stripe we have seen some non-reproducibility (which is almost certainly not timestamps on jars).

retronym commented 6 years ago

Thanks for all the input.

@dragos Thanks for the patch. I'll also try just using a LinkedHashSet there.

@johnynek If you run into that problem, could you please hold onto the pair of differing class files? A diff of the output of javap -v -private might be enough for me to figure out the problem.

@eed3si9n Glad SBT is making moves in this area at the JAR/ZIP level. Here's a related maven plugin that might serve as inspiration: https://zlika.github.io/reproducible-build-maven-plugin/

retronym commented 6 years ago

I've added another test for quasiquotes.

Here's my WIP branch that uses finer grained fresh names counters (one per source-file-defined method/class, rather than one per source file). It fixes all the problems identified in this repo so far.

retronym commented 6 years ago

/cc @smarter

ittaiz commented 6 years ago

@johnynek The reproducibility test still fails for me locally from time to time. We should take a look at how to make it more fine grain since right now when it fails it's hard to know which jars differ, let alone which class files and we also don't keep a copy of them to give to @retronym

smarter commented 6 years ago

In Dotty, @nicolasstucki implemented idempotency tests for this sort of things: https://github.com/lampepfl/dotty/blob/master/compiler/test/dotty/tools/dotc/IdempotencyTests.scala

retronym commented 6 years ago

Asking @xeno-by for some background on the change to macros/quasiquotes that switched to globally scoped fresh names.

xeno-by commented 6 years ago

Hmmm I'm not sure I can recall this right now. @densh, maybe that was necessary for your work on quasiquotes?

retronym commented 6 years ago

Some progress:

I've ported the test cases from this PR into unit tests in my stable-output WIP branch.

I wrote a script that can run a stability test for any project after exporting a files with the compiler options. I have a local sbt plugin that adds the argsFile task to perform this export.

Using this script on the compiler sources themselves reveals the next problem: the order of default getter methods within the data of the @ScalaSignature annotation depends on the order that their methods were type completed. I've added a failing test for this. Perhaps the pickler could sort decls before writing, at least those of synthetic methods. (That seems to work)

I've also published a new version of jardiff, which I used to inspect and compare class files (or classpaths thereof). The new raw mode -r is useful to highlights differences that the tool normalizes away by default (such as method ordering).

retronym commented 6 years ago

Parameter alias computation was also unstable to order-of-typechecking, we need to defer some of that to post-typer, I beleive.

Static forwarders of synthetics (e.g. default getters) need to be sorted in the same way that I've started sorting synthetics themselves. Bridges probably have the same problem. Maybe we should enter default getters of a template into scope eagerly in a deterministic order, rather than deferring that job to the type completers.

retronym commented 6 years ago

I've implemented eager entry of default getters, which indeed is central way to fix the various symptoms of instability that they cause. I was able to rollback some previous fixes.

I also found a problem with mixin outer accessors, which would incorrectly take on the position of the super class. This position was only available under joint compilation, so it was incorrect and unstable.

retronym commented 6 years ago

Next cabs off the rank:

diff --git a/scala/tools/nsc/typechecker/Macros.class.asm b/scala/tools/nsc/typechecker/Macros.class.asm
index 2ad1af1..33e8908 100644
--- a/scala/tools/nsc/typechecker/Macros.class.asm
+++ b/scala/tools/nsc/typechecker/Macros.class.asm
@@ -4,7 +4,7 @@

   // compiled from: Macros.scala

image


Individually compiling /Users/jz/code/scala/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala
diff --git a/scala/tools/nsc/transform/patmat/PatternMatching$OptimizingMatchTranslator.class.asm b/scala/tools/nsc/transform/patmat/PatternMatching$OptimizingMatchTranslator.class.asm
index 1183847..a4054cd 100644
--- a/scala/tools/nsc/transform/patmat/PatternMatching$OptimizingMatchTranslator.class.asm
+++ b/scala/tools/nsc/transform/patmat/PatternMatching$OptimizingMatchTranslator.class.asm
@@ -338,6 +338,9 @@
   // access flags 0x42
   private volatile Lscala/tools/nsc/transform/patmat/MatchTreeMaking$TreeMakers$SubstOnlyTreeMaker$; SubstOnlyTreeMaker$module

+  // access flags 0x42
+  private volatile Lscala/tools/nsc/transform/patmat/MatchTreeMaking$TreeMakers$TypeTestTreeMaker$; TypeTestTreeMaker$module
+
   // access flags 0x12
   private final Z debugInfoEmitVars

@@ -349,9 +352,6 @@

   // access flags 0x42
   private volatile Lscala/tools/nsc/transform/patmat/MatchTreeMaking$TreeMakers$IrrefutableExtractorTreeMaker$; IrrefutableExtractorTreeMaker$module
-
-  // access flags 0x42
-  private volatile Lscala/tools/nsc/transform/patmat/MatchTreeMaking$TreeMakers$TypeTestTreeMaker$; TypeTestTreeMaker$module

   // access flags 0x42
   private volatile Lscala/tools/nsc/transform/patmat/MatchTreeMaking$TreeMakers$EqualityTestTreeMaker$; EqualityTestTreeMaker$module
@@ -2305,6 +2305,25 @@
     MAXLOCALS = 1
retronym commented 6 years ago

Looks like we've got an instability in the OVERRIDE flag.

cat /tmp/test.scala && git diff && scalac -d /tmp /tmp/test.scala && qscala -cp /tmp Test a > /tmp/a.log; qscala -cp /tmp Test b > /tmp/b.log && diff -u /tmp/{a,b}.log
import scala.reflect.internal.Flags
import scala.reflect.internal.pickling.ByteCodecs
import scala.tools.nsc.symtab.classfile.ClassfileParser

object Test {
  def main(args: Array[String]): Unit = {
    def test(ssig: String): Unit = {
      val bytes = ssig.getBytes(java.nio.charset.StandardCharsets.UTF_8)
      val len = ByteCodecs.decode(bytes)
      import scala.tools.nsc._
      val g = new Global(new Settings)
      import g._
      new Run
      object unpickler extends scala.reflect.internal.pickling.UnPickler {
        val symbolTable: g.type = g
      }
      unpickler.unpickle(bytes take len, 0, NoSymbol.newClassSymbol(TypeName("dummy")), NoSymbol.newModuleSymbol(TermName("dummy$"), newFlags = Flags.MODULE), "test.scala")
    }
    if (args.head == "a") test(a)
    else test(b)
  }
  val a = "\u0006\u0001\u0019uh!C\u0001\u0003!\u0003\r\u0009a\u0003D~\u0005\u0019i\u0015m\u0019:pg*\u00111\u0001B\u0001\u000cif\u0004Xm\u00195fG.,'O\u0003\u0002\u0006\r\u0005\u0019an]2\u000b\u0005\u001dA\u0011!\u0002;p_2\u001c(\"A\u0005\u0002\u000bM\u001c\u0017\r\\1\u0004\u0001M)\u0001\u0001\u0004\u0009\u001bAA\u0011QBD\u0007\u0002\u0011%\u0011q\u0002\u0003\u0002\u0007\u0003:L(+\u001a4\u0011\u0005EAR\"\u0001\n\u000b\u0005M!\u0012a\u0002:v]RLW.\u001a\u0006\u0003+Y\u0009a!\\1de>\u001c(BA\u000c\u0009\u0003\u001d\u0011XM\u001a7fGRL!!\u0007\n\u0003\u001b5\u000b7M]8Sk:$\u0018.\\3t!\u0009Yb$D\u0001\u001d\u0015\u0009iB#\u0001\u0003vi&d\u0017BA\u0010\u001d\u0005\u0019!&/Y2fgB\u00111$I\u0005\u0003Eq\u0011q\u0001S3ma\u0016\u00148\u000fC\u0003%\u0001\u0011\u0005Q%\u0001\u0004%S:LG\u000f\n\u000b\u0002MA\u0011QbJ\u0005\u0003Q!\u0011A!\u00168ji\"A!\u0006\u0001EC\u0002\u0013\u00051&A\u0005gCN$HK]1dWV\u0009A\u0006E\u0002._Ej\u0011A\u000c\u0006\u0003/\u0019I!\u0001\r\u0018\u0003\u0013\u0019\u000b7\u000f\u001e+sC\u000e\\W\"\u0001\u0001\u0009\u000bM\u0002A\u0011\u0001\u001b\u0002\u001d\u001ddwNY1m'\u0016$H/\u001b8hgV\u0009Q\u0007\u0005\u00027o5\u0009A!\u0003\u00029\u0009\u0009A1+\u001a;uS:<7\u000fC\u0003;\u0001\u0011E1(\u0001\u000bgS:$W*Y2s_\u000ec\u0017m]:M_\u0006$WM\u001d\u000b\u0002yA\u0011QHQ\u0007\u0002})\u0011q\u0008Q\u0001\u0005Y\u0006twMC\u0001B\u0003\u0011Q\u0017M^1\n\u0005\rs$aC\"mCN\u001cHj\\1eKJ4A!\u0012\u0001A\r\n\u0001R*Y2s_&k\u0007\u000f\u001c\"j]\u0012LgnZ\n\u0005\u000929%\n\u0005\u0002\u000e\u0011&\u0011\u0011\n\u0003\u0002\u0008!J|G-^2u!\u0009i1*\u0003\u0002M\u0011\u0009a1+\u001a:jC2L'0\u00192mK\"Aa\n\u0012BK\u0002\u0013\u0005q*\u0001\u0005jg\n+h\u000e\u001a7f+\u0005\u0001\u0006CA\u0007R\u0013\u0009\u0011\u0006BA\u0004C_>dW-\u00198\u0009\u0011Q#%\u0011#Q\u0001\nA\u000b\u0011\"[:Ck:$G.\u001a\u0011\u0009\u0011Y#%Q3A\u0005\u0002=\u000b!\"[:CY\u0006\u001c7NY8y\u0011!AFI!E!\u0002\u0013\u0001\u0016aC5t\u00052\u000c7m\u001b2pq\u0002B\u0001B\u0017#\u0003\u0016\u0004%\u0009aW\u0001\nG2\u000c7o\u001d(b[\u0016,\u0012\u0001\u0018\u0009\u0003;\u0012t!A\u00182\u0011\u0005}CQ\"\u00011\u000b\u0005\u0005T\u0011A\u0002\u001fs_>$h(\u0003\u0002d\u0011\u00051\u0001K]3eK\u001aL!!\u001a4\u0003\rM#(/\u001b8h\u0015\u0009\u0019\u0007\u0002\u0003\u0005i\u0009\nE\u0009\u0015!\u0003]\u0003)\u0019G.Y:t\u001d\u0006lW\r\u0009\u0005\u0009U\u0012\u0013)\u001a!C\u00017\u0006AQ.\u001a;i\u001d\u0006lW\r\u0003\u0005m\u0009\nE\u0009\u0015!\u0003]\u0003%iW\r\u001e5OC6,\u0007\u0005\u0003\u0005o\u0009\nU\r\u0011\"\u0001p\u0003%\u0019\u0018n\u001a8biV\u0014X-F\u0001q!\r\u0009h/\u001f\u0008\u0003eRt!aX:\n\u0003%I!!\u001e\u0005\u0002\u000fA\u000c7m[1hK&\u0011q\u000f\u001f\u0002\u0005\u0019&\u001cHO\u0003\u0002v\u0011A\u0019\u0011O\u001e>\u0011\u0005mdX\"\u0001\u0002\n\u0005u\u0014!a\u0003$j]\u001e,'\u000f\u001d:j]RD\u0001b #\u0003\u0012\u0003\u0006I\u0001]\u0001\u000bg&<g.\u0019;ve\u0016\u0004\u0003BCA\u0002\u0009\nU\r\u0011\"\u0001\u0002\u0006\u0005)A/\u0019:hgV\u0011\u0011q\u0001\u0009\u0005cZ\u000cI\u0001\u0005\u0003\u0002\u000c\u0005UabA\u0019\u0002\u000e%!\u0011qBA\u0009\u0003\u00199Gn\u001c2bY&\u0019\u00111\u0003\u0002\u0003\u0011\u0005s\u0017\r\\={KJLA!a\u0006\u0002\u001a\u0009!AK]3f\u0013\u0011\u0009Y\"!\u0008\u0003\u000bQ\u0013X-Z:\u000b\u0007\u0005}a#\u0001\u0005j]R,'O\\1m\u0011)\u0009\u0019\u0003\u0012B\u0009B\u0003%\u0011qA\u0001\u0007i\u0006\u0014xm\u001d\u0011\u0009\u000f\u0005\u001dB\u0009\"\u0001\u0002*\u00051A(\u001b8jiz\"b\"a\u000b\u0002.\u0005=\u0012\u0011GA\u001a\u0003k\u00099\u0004\u0005\u00022\u0009\"1a*!\nA\u0002ACaAVA\u0013\u0001\u0004\u0001\u0006B\u0002.\u0002&\u0001\u0007A\u000c\u0003\u0004k\u0003K\u0001\r\u0001\u0018\u0005\u0007]\u0006\u0015\u0002\u0019\u00019\u0009\u0011\u0005\r\u0011Q\u0005a\u0001\u0003\u000fAa!a\u000fE\u0009\u0003y\u0015!F5t?\u0012\nX.\u0019:lIEl\u0017M]6%c6\u000c'o\u001b\u0005\u0007\u0003!E\u0011A(\u0002\u0015%\u001cx\u000b[5uK\n|\u0007\u0010C\u0005\u0002D\u0011\u000b\u0009\u0011\"\u0001\u0002F\u0005!1m\u001c9z)9\u0009Y#a\u0012\u0002J\u0005-\u0013QJA(\u0003#B\u0001BTA!!\u0003\u0005\r\u0001\u0015\u0005\u0009-\u0006\u0005\u0003\u0013!a\u0001!\"A!,!\u0011\u0011\u0002\u0003\u0007A\u000c\u0003\u0005k\u0003\u0003\u0002\n\u00111\u0001]\u0011!q\u0017\u0011\u0009I\u0001\u0002\u0004\u0001\u0008BCA\u0002\u0003\u0003\u0002\n\u00111\u0001\u0002\u0008!A\u0011Q\u000b#\u0002\u0002\u0013\u0005q*\u0001\u0008d_BLH\u0005Z3gCVdG\u000fJ\u0019\u0009\u0011\u0005eC)!A\u0005\u0002=\u000babY8qs\u0012\"WMZ1vYR$#\u0007\u0003\u0005\u0002^\u0011\u000b\u0009\u0011\"\u0001\\\u00039\u0019w\u000e]=%I\u00164\u0017-\u001e7uIMB\u0001\"!\u0019E\u0003\u0003%\u0009aW\u0001\u000fG>\u0004\u0018\u0010\n3fM\u0006,H\u000e\u001e\u00135\u0011!\u0009)\u0007RA\u0001\n\u0003y\u0017AD2paf$C-\u001a4bk2$H%\u000e\u0005\n\u0003S\"\u0015\u0011!C\u0001\u0003\u000b\u0009abY8qs\u0012\"WMZ1vYR$c\u0007C\u0005\u0002n\u0011\u000b\u0009\u0011\"\u0011\u0002p\u0005i\u0001O]8ek\u000e$\u0008K]3gSb,\"!!\u001d\u0011\u0007u\n\u0019(\u0003\u0002f}!I\u0011q\u000f#\u0002\u0002\u0013\u0005\u0011\u0011P\u0001\raJ|G-^2u\u0003JLG/_\u000b\u0003\u0003w\u00022!DA?\u0013\r\u0009y\u0008\u0003\u0002\u0004\u0013:$\u0008\"CAB\u0009\u0006\u0005I\u0011AAC\u00039\u0001(o\u001c3vGR,E.Z7f]R$B!a\"\u0002\u000eB\u0019Q\"!#\n\u0007\u0005-\u0005BA\u0002B]fD!\"a$\u0002\u0002\u0006\u0005\u0009\u0019AA>\u0003\rAH%\r\u0005\n\u0003'#\u0015\u0011!C!\u0003+\u000bq\u0002\u001d:pIV\u001cG/\u0013;fe\u0006$xN]\u000b\u0003\u0003/\u0003b!!'\u0002 \u0006\u001dUBAAN\u0015\r\u0009i\nC\u0001\u000bG>dG.Z2uS>t\u0017\u0002BAQ\u00037\u0013\u0001\"\u0013;fe\u0006$xN\u001d\u0005\n\u0003K#\u0015\u0011!C\u0001\u0003O\u000b\u0001bY1o\u000bF,\u0018\r\u001c\u000b\u0004!\u0006%\u0006BCAH\u0003G\u000b\u0009\u00111\u0001\u0002\u0008\"I\u0011Q\u0016#\u0002\u0002\u0013\u0005\u0013qV\u0001\u0009Q\u0006\u001c\u0008nQ8eKR\u0011\u00111\u0010\u0005\n\u0003g#\u0015\u0011!C!\u0003k\u000b\u0001\u0002^8TiJLgn\u001a\u000b\u0003\u0003cB\u0011\"!/E\u0003\u0003%\u0009%a/\u0002\r\u0015\u000cX/\u00197t)\r\u0001\u0016Q\u0018\u0005\u000b\u0003\u001f\u000b9,!AA\u0002\u0005\u001duaBAa\u0001!\u0005\u00111Y\u0001\u0011\u001b\u0006\u001c'o\\%na2\u0014\u0015N\u001c3j]\u001e\u00042!MAc\r\u0019)\u0005\u0001#\u0001\u0002HN!\u0011Q\u0019\u0007K\u0011!\u00099#!2\u0005\u0002\u0005-GCAAb\u0011!\u0009y-!2\u0005\u0002\u0005E\u0017A\u00039jG.dW-\u0011;p[R!\u0011\u0011BAj\u0011!\u0009).!4A\u0002\u0005\u001d\u0015aA8cU\"A\u0011\u0011\\Ac\u0009\u0003\u0009Y.\u0001\u0007v]BL7m\u001b7f\u0003R|W\u000e\u0006\u0003\u0002\u0008\u0006u\u0007\u0002CAp\u0003/\u0004\r!!\u0003\u0002\u0009Q\u0014X-\u001a\u0005\u0009\u0003G\u000c)\r\"\u0001\u0002f\u00061\u0001/[2lY\u0016$B!!\u0003\u0002h\"A\u0011\u0011^Aq\u0001\u0004\u0009I!\u0001\u0007nC\u000e\u0014x.S7qYJ+g\r\u0003\u0005\u0002n\u0006\u0015G\u0011AAx\u0003!)h\u000e]5dW2,G\u0003BA\u0016\u0003cD\u0001\"a9\u0002l\u0002\u0007\u0011\u0011\u0002\u0005\u0009\u0003k\u000c)\r\"\u0003\u0002x\u0006\u0019!m\u001c=\u0016\u0009\u0005e(1\u0004\u000b\u0005\u0003w\u0014\u0019\u0002\r\u0003\u0002~\n\u001d\u0001#B/\u0002\u0000\n\r\u0011b\u0001B\u0001M\n)1\u0009\\1tgB!!Q\u0001B\u0004\u0019\u0001!AB!\u0003\u0002t\u0006\u0005\u0009\u0011!B\u0001\u0005\u0017\u00111a\u0018\u00132#\u0011\u0011i!a\"\u0011\u00075\u0011y!C\u0002\u0003\u0012!\u0011qAT8uQ&tw\r\u0003\u0005\u0003\u0016\u0005M\u0008\u0019\u0001B\u000c\u0003\u0015\u0019G.\u0019>{!\u0015i\u0016q B\r!\u0011\u0011)Aa\u0007\u0005\u0011\u0009u\u00111\u001fb\u0001\u0005\u0017\u0011\u0011\u0001\u0016\u0005\u000b\u0005C\u0009)-!A\u0005\u0002\n\r\u0012!B1qa2LHCDA\u0016\u0005K\u00119C!\u000b\u0003,\u00095\"q\u0006\u0005\u0007\u001d\n}\u0001\u0019\u0001)\u0009\rY\u0013y\u00021\u0001Q\u0011\u0019Q&q\u0004a\u00019\"1!Na\u0008A\u0002qCaA\u001cB\u0010\u0001\u0004\u0001\u0008\u0002CA\u0002\u0005?\u0001\r!a\u0002\u0009\u0015\u0009M\u0012QYA\u0001\n\u0003\u0013)$A\u0004v]\u0006\u0004\u0008\u000f\\=\u0015\u0009\u0009]\"1\u0009\u0009\u0006\u001b\u0009e\"QH\u0005\u0004\u0005wA!AB(qi&|g\u000e\u0005\u0006\u000e\u0005\u0001\u0006\u000b\u0018/q\u0003\u000fI1A!\u0011\u0009\u0005\u0019!V\u000f\u001d7fm!Q!Q\u0009B\u0019\u0003\u0003\u0005\r!a\u000b\u0002\u0007a$\u0003\u0007C\u0004\u0003J\u0001!\u0009!a\u001c\u0002\u00175\u000c7M]8F]\u001eLg.\u001a\u0005\u0008\u0005\u001b\u0002A\u0011\u0001B(\u00035\u0011\u0017N\u001c3NC\u000e\u0014x.S7qYR)aE!\u0015\u0003`!A!1\u000bB&\u0001\u0004\u0011)&\u0001\u0005nC\u000e\u0014x\u000eR3g!\u0011\u0009YAa\u0016\n\u0009\u0009e#1\u000c\u0002\u0007'fl'm\u001c7\n\u0009\u0009u\u0013Q\u0004\u0002\u0008'fl'm\u001c7t\u0011!\u0009IOa\u0013A\u0002\u0005%\u0001b\u0002B2\u0001\u0011\u0005!QM\u0001\u0015Y>\u000cG-T1de>LU\u000e\u001d7CS:$\u0017N\\4\u0015\u0009\u0009\u001d$\u0011\u000e\u0009\u0006\u001b\u0009e\u00121\u0006\u0005\u0009\u0005'\u0012\u0009\u00071\u0001\u0003V!1a\u000b\u0001C\u0001\u0005[\"2\u0001\u0015B8\u0011!\u0011\u0009Ha\u001bA\u0002\u0005%\u0011\u0001C3ya\u0006tG-Z3\u0009\rY\u0003A\u0011\u0001B;)\r\u0001&q\u000f\u0005\u0009\u0005'\u0012\u0019\u00081\u0001\u0003V!9!1\u0010\u0001\u0005\u0002\u0009u\u0014AE:uC:$\u0017M\u001d3Jg\nc\u0017mY6c_b$2\u0001\u0015B@\u0011!\u0011\u0019F!\u001fA\u0002\u0009U\u0003b\u0002BB\u0001\u0011\u0005!QQ\u0001$G>l\u0007/\u001e;f\u001b\u0006\u001c'o\u001c#fMRK\u0008/\u001a$s_6l\u0015m\u0019:p\u00136\u0004HNU3g)\u0019\u00119I!%\u0003\u001cB!\u00111\u0002BE\u0013\u0011\u0011YI!$\u0003\u0009QK\u0008/Z\u0005\u0005\u0005\u001f\u000biBA\u0003UsB,7\u000f\u0003\u0005\u0003\u0014\n\u0005\u0005\u0019\u0001BK\u0003%i\u0017m\u0019:p\u0009\u0012,g\r\u0005\u0003\u0002\u000c\u0009]\u0015\u0002\u0002BM\u00033\u0011a\u0001R3g\u0009\u00164\u0007\u0002CAu\u0005\u0003\u0003\r!!\u0003\u0009\u000f\u0009}\u0005\u0001\"\u0001\u0003\"\u0006qA/\u001f9fI6\u000b7M]8C_\u0012LHCBA\u0005\u0005G\u0013\u0009\u000c\u0003\u0005\u0003&\nu\u0005\u0019\u0001BT\u0003\u0015!\u0018\u0010]3s!\r\u0009$\u0011V\u0005\u0005\u0005W\u0013iKA\u0003UsB,'/C\u0002\u00030\n\u0011a\u0001V=qKJ\u001c\u0008\u0002\u0003BJ\u0005;\u0003\rA!&\u0009\u000f\u0009U\u0006\u0001\"\u0001\u00038\u000612\u000f^1oI\u0006\u0014H\rV=qK\u0012l\u0015m\u0019:p\u0005>$\u0017\u0010\u0006\u0004\u0002\n\u0009e&1\u0018\u0005\u0009\u0005K\u0013\u0019\u000c1\u0001\u0003(\"A!1\u0013BZ\u0001\u0004\u0011)\nC\u0004\u0003@\u0002!\u0009A!1\u0002\u00195\u000c7M]8D_:$X\r\u001f;\u0015\u0011\u0009\r'Q\u001aBh\u0005'\u00042!\rBc\u0013\u0011\u00119M!3\u0003\u00195\u000b7M]8D_:$X\r\u001f;\n\u0007\u0009-'A\u0001\u0008Ti\u0012\u000cE\u000f^1dQ6,g\u000e^:\u0009\u0011\u0009\u0015&Q\u0018a\u0001\u0005OC\u0001B!5\u0003>\u0002\u0007\u0011\u0011B\u0001\u000baJ,g-\u001b=Ue\u0016,\u0007\u0002\u0003Bk\u0005{\u0003\r!!\u0003\u0002\u0019\u0015D\u0008/\u00198eK\u0016$&/Z3\u0007\r\u0009e\u0007\u0001\u0011Bn\u0005%i\u0015m\u0019:p\u0003J<7oE\u0003\u0003X29%\nC\u0006\u0003`\n]'Q3A\u0005\u0002\u0009\u0005\u0018!A2\u0016\u0005\u0009\r\u0007b\u0003Bs\u0005/\u0014\u0009\u0012)A\u0005\u0005\u0007\u000c!a\u0019\u0011\u0009\u0017\u0009%(q\u001bBK\u0002\u0013\u0005!1^\u0001\u0007_RDWM]:\u0016\u0005\u00095\u0008\u0003B9w\u0003\u000fC1B!=\u0003X\nE\u0009\u0015!\u0003\u0003n\u00069q\u000e\u001e5feN\u0004\u0003\u0002CA\u0014\u0005/$\u0009A!>\u0015\r\u0009](\u0011 B~!\r\u0009$q\u001b\u0005\u0009\u0005?\u0014\u0019\u00101\u0001\u0003D\"A!\u0011\u001eBz\u0001\u0004\u0011i\u000f\u0003\u0006\u0002D\u0009]\u0017\u0011!C\u0001\u0005$bAa>\u0004\u0002\r\r\u0001B\u0003Bp\u0005{\u0004\n\u00111\u0001\u0003D\"Q!\u0011\u001eB!\u0003\u0005\rA!<\u0009\u0015\u0005U#q[A\u0001\n\u0003\u0011\u0009\u000f\u0003\u0006\u0002Z\u0009]\u0017\u0011!C\u0001\u0005WD!\"!\u001c\u0003X\u0006\u0005I\u0011IA8\u0011)\u00099Ha6\u0002\u0002\u0013\u0005\u0011\u0011\u0010\u0005\u000b\u0003\u0007\u00139.!A\u0005\u0002\r=A\u0003BAD\u0007#A!\"a$\u0004\u000e\u0005\u0005\u0009\u0019AA>\u0011)\u0009\u0019Ja6\u0002\u0002\u0013\u0005\u0013Q\u0013\u0005\u000b\u0003K\u00139.!A\u0005\u0002\r]Ac\u0001)\u0004\u001a!Q\u0011qRB\u000b\u0003\u0003\u0005\r!a\"\u0009\u0015\u00055&q[A\u0001\n\u0003\ny\u000b\u0003\u0006\u00024\n]\u0017\u0011!C!\u0003kC!\"!/\u0003X\u0006\u0005I\u0011IB\u0011)\r\u000161\u0005\u0005\u000b\u0003\u001f\u001by\"!AA\u0002\u0005\u001du!CB\u0014\u0001\u0005\u0005\u0009\u0012AB\u0015\u0003%i\u0015m\u0019:p\u0003J<7\u000fE\u00022\u0007W1\u0011B!7\u0001\u0003\u0003E\u0009a!\u000c\u0014\u000b\r-2q\u0006&\u0011\u0015\rE2Q\u0007Bb\u0005[\u001490\u0004\u0002\u00044)\u00111\u0003C\u0005\u0005\u0007o\u0019\u0019DA\u0009BEN$(/Y2u\rVt7\r^5p]JB\u0001\"a\n\u0004,\u0011\u000511\u0008\u000b\u0003\u0007SA!\"a-\u0004,\u0005\u0005IQIA[\u0011)\u0011\u0009ca\u000b\u0002\u0002\u0013\u00055\u0011\u0009\u000b\u0007\u0005o\u001c\u0019e!\u0012\u0009\u0011\u0009}7q\u0008a\u0001\u0005\u0007D\u0001B!;\u0004@\u0001\u0007!Q\u001e\u0005\u000b\u0005g\u0019Y#!A\u0005\u0002\u000e%C\u0003BB&\u0007'\u0002R!\u0004B\u001d\u0007\u001b\u0002r!DB(\u0005\u0007\u0014i/C\u0002\u0004R!\u0011a\u0001V;qY\u0016\u0014\u0004B\u0003B#\u0007\u000f\n\u0009\u00111\u0001\u0003x\"91q\u000b\u0001\u0005\u0002\re\u0013!C7bGJ|\u0017I]4t)\u0019\u00119pa\u0017\u0004^!A!QUB+\u0001\u0004\u00119\u000b\u0003\u0005\u0003r\rU\u0003\u0019AA\u0005\u0011\u001d\u0019\u0009\u0007\u0001C\u0001\u0007G\n\u0011c\u001d;b]\u0012\u000c'\u000fZ'bGJ|\u0017I]4t)\u0019\u00119p!\u001a\u0004h!A!QUB0\u0001\u0004\u00119\u000b\u0003\u0005\u0003r\r}\u0003\u0019AA\u0005\u0011%\u0019Y\u0007\u0001a\u0001\n\u0003\u0019i'A\u0006`_B,g.T1de>\u001cXCAB8!\u0019\u0019\u0009ha\u001e\u0004z5\u001111\u000f\u0006\u0005\u0007k\nY*A\u0005j[6,H/\u00192mK&\u0019qoa\u001d\u0013\u0009\rm4q\u0010\u0004\u0007\u0007{\u0002\u0001a!\u001f\u0003\u0019q\u0012XMZ5oK6,g\u000e\u001e \u0011\u0009\r\u00055qQ\u0007\u0003\u0007\u0007S1a!\"\u0015\u0003!\u0019wN\u001c;fqR\u001c\u0018\u0002BBE\u0007\u0007\u0013qaQ8oi\u0016DH\u000f\u0003\u0006\u0004\u000e\u000em$\u0019!D\u0001\u0007\u001f\u000b\u0001\"\u001e8jm\u0016\u00148/Z\u000b\u0003\u0003\u0017A\u0011ba%\u0001\u0001\u0004%\u0009a!&\u0002\u001f}{\u0007/\u001a8NC\u000e\u0014xn]0%KF$2AJBL\u0011)\u0009yi!%\u0002\u0002\u0003\u00071q\u000e\u0005\u0008\u00077\u0003A\u0011AB7\u0003)y\u0007/\u001a8NC\u000e\u0014xn\u001d\u0005\u0008\u0007?\u0003A\u0011ABQ\u0003A\u0001Xo\u001d5NC\u000e\u0014xnQ8oi\u0016DH\u000fF\u0002'\u0007GC\u0001Ba8\u0004\u001e\u0002\u0007!1\u0019\u0005\u0007\u0007O\u0003A\u0011A\u0013\u0002\u001fA|\u0007/T1de>\u001cuN\u001c;fqRDqaa+\u0001\u0009\u0003\u0019i+\u0001\u000cf]\u000edwn]5oO6\u000b7M]8Q_NLG/[8o+\u0009\u0019y\u000b\u0005\u0003\u00042\u000eUVBABZ\u0015\ri\u0012QD\u0005\u0005\u0007o\u001b\u0019L\u0001\u0005Q_NLG/[8o\r\u001d\u0019Y\u000cAA\u0001\u0007{\u0013Q\"T1de>,\u0005\u0010]1oI\u0016\u00148cAB]\u0019!Y!QUB]\u0005\u000b\u0007I\u0011ABa+\u0009\u00119\u000bC\u0006\u0004F\u000ee&\u0011!Q\u0001\n\u0009\u001d\u0016A\u0002;za\u0016\u0014\u0008\u0005C\u0006\u0003r\re&Q1A\u0005\u0002\r%WCAA\u0005\u0011-\u0019im!/\u0003\u0002\u0003\u0006I!!\u0003\u0002\u0013\u0015D\u0008/\u00198eK\u0016\u0004\u0003\u0002CA\u0014\u0007s#\u0009a!5\u0015\r\rM7Q[Bl!\r\u00094\u0011\u0018\u0005\u0009\u0005K\u001by\r1\u0001\u0003(\"A!\u0011OBh\u0001\u0004\u0009I\u0001\u0003\u0005\u0004\\\u000eef\u0011ABo\u0003%ygnU;dG\u0016\u001c8\u000f\u0006\u0003\u0002\n\r}\u0007\u0002CBq\u00073\u0004\r!!\u0003\u0002\u0011\u0015D\u0008/\u00198eK\u0012D\u0001b!:\u0004:\u001a\u00051q]\u0001\u000b_:4\u0015\r\u001c7cC\u000e\\G\u0003BA\u0005\u0007SD\u0001b!9\u0004d\u0002\u0007\u0011\u0011\u0002\u0005\u0009\u0007[\u001cI\u000c\"\u0001\u0004p\u0006aqN\\*vaB\u0014Xm]:fIR!\u0011\u0011BBy\u0011!\u0011\u0009ha;A\u0002\u0005%\u0001\u0002CB{\u0007s#\u0009aa>\u0002\u0013=tG)\u001a7bs\u0016$G\u0003BA\u0005\u0007sD\u0001b!9\u0004t\u0002\u0007\u0011\u0011\u0002\u0005\u0009\u0007{\u001cI\u000c\"\u0001\u0004\u0000\u0006IqN\\*lSB\u0004X\r\u001a\u000b\u0005\u0003\u0013!\u0009\u0001\u0003\u0005\u0004b\u000em\u0008\u0019AA\u0005\u0011!!)a!/\u0005\u0002\u0011\u001d\u0011!C8o\r\u0006LG.\u001e:f)\u0011\u0009I\u0001\"\u0003\u0009\u0011\r\u0005H1\u0001a\u0001\u0003\u0013A\u0001B!\u0009\u0004:\u0012\u0005AQ\u0002\u000b\u0005\u0003\u0013!y\u0001\u0003\u0005\u0005\u0012\u0011-\u0001\u0019AA\u0005\u0003%!Wm];hCJ,G\r\u0003\u0005\u0005\u0016\reF\u0011\u0003C\u000c\u0003\u0019)\u0007\u0010]1oIR!\u0011\u0011\u0002C\r\u0011!!\u0009\u0002b\u0005A\u0002\u0005%aA\u0002C\u000f\u0001\u0001!yB\u0001\u0009EK\u001al\u0015m\u0019:p\u000bb\u0004\u0018M\u001c3feN!A1DBj\u00115\u0011)\u000bb\u0007\u0003\u0002\u0003\u0006IAa*\u0004@\"i!\u0011\u000fC\u000e\u0005\u0003\u0005\u000b\u0011BA\u0005\u0007\u000fD1\u0002b\n\u0005\u001c\u0009\u0005\u0009\u0015!\u0003\u0005*\u0005!Qn\u001c3f!\u0011!Y\u0003b\u000c\u000f\u0007Y\"i#\u0003\u0002v\u0009%!A\u0011\u0007C\u001a\u0005\u0011iu\u000eZ3\u000b\u0005U$\u0001b\u0003C\u001c\u00097\u0011\u0009\u0011)A\u0005\u0005\u000f\u000bqa\\;uKJ\u0004F\u000f\u0003\u0005\u0002(\u0011mA\u0011\u0001C\u001e))!i\u0004b\u0010\u0005B\u0011\rCQ\u0009\u0009\u0004c\u0011m\u0001\u0002\u0003BS\u0009s\u0001\rAa*\u0009\u0011\u0009ED\u0011\u0008a\u0001\u0003\u0013A\u0001\u0002b\n\u0005:\u0001\u0007A\u0011\u0006\u0005\u0009\u0009o!I\u00041\u0001\u0003\u0008\"YA\u0011\nC\u000e\u0011\u000b\u0007I\u0011\u0001C&\u0003\u001dIgN\\3s!R,\"Aa\"\u0009\u0011\rmG1\u0004C!\u0009\u001f\"B!!\u0003\u0005R!AA1\u000bC'\u0001\u0004\u0009I!A\u0005fqB\u000cg\u000eZ3ea!A1Q\u001fC\u000e\u0009\u0003\"9\u0006\u0006\u0003\u0002\n\u0011e\u0003\u0002\u0003C.\u0009+\u0002\r!!\u0003\u0002\u000f\u0011,G.Y=fI\"A1Q\u001dC\u000e\u0009\u0003\"y\u0006\u0006\u0003\u0002\n\u0011\u0005\u0004\u0002\u0003C2\u0009;\u0002\r!!\u0003\u0002\u0011\u0019\u000cG\u000e\u001c2bG.Dq\u0002b\u001a\u0005\u001cA\u0005\u0019\u0011!A\u0005\n\r\u00057qX\u0001\u000cgV\u0004XM\u001d\u0013usB,'\u000fC\u0004\u0005l\u0001!\u0009\u0001\"\u001c\u0002\u00175\u000c7M]8FqB\u000cg\u000e\u001a\u000b\u000b\u0003\u0013!y\u0007\"\u001d\u0005t\u0011U\u0004\u0002\u0003BS\u0009S\u0002\rAa*\u0009\u0011\u0009ED\u0011\u000ea\u0001\u0003\u0013A\u0001\u0002b\n\u0005j\u0001\u0007A\u0011\u0006\u0005\u0009\u0009o\"I\u00071\u0001\u0003\u0008\u0006\u0011\u0001\u000f\u001e\u0005\u0008\u0009w\u0002A\u0011\u0001C?\u0003M\u0019H/\u00198eCJ$W*Y2s_\u0016C\u0008/\u00198e))\u0009I\u0001b \u0005\u0002\u0012\rEQ\u0011\u0005\u0009\u0005K#I\u00081\u0001\u0003(\"A!\u0011\u000fC=\u0001\u0004\u0009I\u0001\u0003\u0005\u0005(\u0011e\u0004\u0019\u0001C\u0015\u0011!!9\u0008\"\u001fA\u0002\u0009\u001dea\u0002CE\u0001\u0005\u0005B1\u0012\u0002\u000c\u001b\u0006\u001c'o\\*uCR,8oE\u0002\u0005\u00082A1\u0002b$\u0005\u0008\n\u0015\r\u0011\"\u0001\u0004J\u00061!/Z:vYRD1\u0002b%\u0005\u0008\n\u0005\u0009\u0015!\u0003\u0002\n\u00059!/Z:vYR\u0004\u0003\u0002CA\u0014\u0009\u000f#\u0009\u0001b&\u0015\u0009\u0011eE1\u0014\u0009\u0004c\u0011\u001d\u0005\u0002\u0003CH\u0009+\u0003\r!!\u0003*\u0019\u0011\u001dEq\u0014Cl\u000b#)I%b!\u0007\r\u0011\u0005\u0006\u0001\u0011CR\u0005\u001d!U\r\\1zK\u0012\u001cb\u0001b(\u0005\u001a\u001eS\u0005b\u0003C.\u0009?\u0013)\u001a!C\u0001\u0007\u0013DQ\u0002\"+\u0005 \nE\u0009\u0015!\u0003\u0002\n\u00115\u0015\u0001\u00033fY\u0006LX\r\u001a\u0011\u0009\u0011\u0005\u001dBq\u0014C\u0001\u0009[#B\u0001b,\u00052B\u0019\u0011\u0007b(\u0009\u0011\u0011mC1\u0016a\u0001\u0003\u0013A!\"a\u0011\u0005 \u0006\u0005I\u0011\u0001C[)\u0011!y\u000bb.\u0009\u0015\u0011mC1\u0017I\u0001\u0002\u0004\u0009I\u0001\u0003\u0006\u0002V\u0011}\u0015\u0011!C\u0001\u0007\u0013D!\"!\u001c\u0005 \u0006\u0005I\u0011IA8\u0011)\u00099\u0008b(\u0002\u0002\u0013\u0005\u0011\u0011\u0010\u0005\u000b\u0003\u0007#y*!A\u0005\u0002\u0011\u0005G\u0003BAD\u0009\u0007D!\"a$\u0005@\u0006\u0005\u0009\u0019AA>\u0011)\u0009\u0019\nb(\u0002\u0002\u0013\u0005\u0013Q\u0013\u0005\u000b\u0003K#y*!A\u0005\u0002\u0011%Gc\u0001)\u0005L\"Q\u0011q\u0012Cd\u0003\u0003\u0005\r!a\"\u0009\u0015\u00055FqTA\u0001\n\u0003\ny\u000b\u0003\u0006\u00024\u0012}\u0015\u0011!C!\u0003kC!\"!/\u0005 \u0006\u0005I\u0011\u0009Cj)\r\u0001FQ\u001b\u0005\u000b\u0003\u001f#\u0009.!AA\u0002\u0005\u001deA\u0002Cm\u0001\u0001#YNA\u0004GC&dWO]3\u0014\r\u0011]G\u0011T$K\u0011-!y\u000eb6\u0003\u0016\u0004%\u0009a!3\u0002\u000f\u0019\u000c\u0017\u000e\\;sK\"iA1\u001dCl\u0005#\u0005\u000b\u0011BA\u0005\u0009\u001b\u000b\u0001BZ1jYV\u0014X\r\u0009\u0005\u0009\u0003O!9\u000e\"\u0001\u0005hR!A\u0011\u001eCv!\r\u0009Dq\u001b\u0005\u0009\u0009?$)\u000f1\u0001\u0002\n!Q\u00111\u0009Cl\u0003\u0003%\u0009\u0001b<\u0015\u0009\u0011%H\u0011\u001f\u0005\u000b\u0009?$i\u000f%AA\u0002\u0005%\u0001BCA+\u0009/\u000c\u0009\u0011\"\u0001\u0004J\"Q\u0011Q\u000eCl\u0003\u0003%\u0009%a\u001c\u0009\u0015\u0005]Dq[A\u0001\n\u0003\u0009I\u0008\u0003\u0006\u0002\u0004\u0012]\u0017\u0011!C\u0001\u0009w$B!a\"\u0005~\"Q\u0011q\u0012C}\u0003\u0003\u0005\r!a\u001f\u0009\u0015\u0005MEq[A\u0001\n\u0003\n)\n\u0003\u0006\u0002&\u0012]\u0017\u0011!C\u0001\u000b\u0007!2\u0001UC\u0003\u0011)\u0009y)\"\u0001\u0002\u0002\u0003\u0007\u0011q\u0011\u0005\u000b\u0003[#9.!A\u0005B\u0005=\u0006BCAZ\u0009/\u000c\u0009\u0011\"\u0011\u00026\"Q\u0011\u0011\u0018Cl\u0003\u0003%\u0009%\"\u0004\u0015\u0007A+y\u0001\u0003\u0006\u0002\u0010\u0016-\u0011\u0011!a\u0001\u0003\u000f3a!b\u0005\u0001\u0001\u0016U!\u0001\u0003$bY2\u0014\u0017mY6\u0014\r\u0015EA\u0011T$K\u0011-!\u0019'\"\u0005\u0003\u0016\u0004%\u0009a!3\u0009\u001b\u0015mQ\u0011\u0003B\u0009B\u0003%\u0011\u0011\u0002CG\u0003%1\u0017\r\u001c7cC\u000e\\\u0007\u0005\u0003\u0005\u0002(\u0015EA\u0011AC\u0010)\u0011)\u0009#b\u0009\u0011\u0007E*\u0009\u0002\u0003\u0005\u0005d\u0015u\u0001\u0019AA\u0005\u0011)\u0009\u0019%\"\u0005\u0002\u0002\u0013\u0005Qq\u0005\u000b\u0005\u000bC)I\u0003\u0003\u0006\u0005d\u0015\u0015\u0002\u0013!a\u0001\u0003\u0013A!\"!\u0016\u0006\u0012\u0005\u0005I\u0011ABe\u0011)\u0009i'\"\u0005\u0002\u0002\u0013\u0005\u0013q\u000e\u0005\u000b\u0003o*\u0009\"!A\u0005\u0002\u0005e\u0004BCAB\u000b#\u0009\u0009\u0011\"\u0001\u00064Q!\u0011qQC\u001b\u0011)\u0009y)\"\r\u0002\u0002\u0003\u0007\u00111\u0010\u0005\u000b\u0003'+\u0009\"!A\u0005B\u0005U\u0005BCAS\u000b#\u0009\u0009\u0011\"\u0001\u0006<Q\u0019\u0001+\"\u0010\u0009\u0015\u0005=U\u0011HA\u0001\u0002\u0004\u00099\u0009\u0003\u0006\u0002.\u0016E\u0011\u0011!C!\u0003_C!\"a-\u0006\u0012\u0005\u0005I\u0011IA[\u0011)\u0009I,\"\u0005\u0002\u0002\u0013\u0005SQ\u0009\u000b\u0004!\u0016\u001d\u0003BCAH\u000b\u0007\n\u0009\u00111\u0001\u0002\u0008\u001a1Q1\n\u0001A\u000b\u001b\u0012qaU6jaB,Gm\u0005\u0004\u0006J\u0011euI\u0013\u0005\u000c\u000b#*IE!f\u0001\n\u0003\u0019I-A\u0004tW&\u0004\u0008/\u001a3\u0009\u001b\u0015US\u0011\nB\u0009B\u0003%\u0011\u0011\u0002CG\u0003!\u00198.\u001b9qK\u0012\u0004\u0003\u0002CA\u0014\u000b\u0013\"\u0009!\"\u0017\u0015\u0009\u0015mSQ\u000c\u0009\u0004c\u0015%\u0003\u0002CC)\u000b/\u0002\r!!\u0003\u0009\u0015\u0005\rS\u0011JA\u0001\n\u0003)\u0009\u0007\u0006\u0003\u0006\\\u0015\r\u0004BCC)\u000b?\u0002\n\u00111\u0001\u0002\n!Q\u0011QKC%\u0003\u0003%\u0009a!3\u0009\u0015\u00055T\u0011JA\u0001\n\u0003\ny\u0007\u0003\u0006\u0002x\u0015%\u0013\u0011!C\u0001\u0003sB!\"a!\u0006J\u0005\u0005I\u0011AC7)\u0011\u00099)b\u001c\u0009\u0015\u0005=U1NA\u0001\u0002\u0004\u0009Y\u0008\u0003\u0006\u0002\u0014\u0016%\u0013\u0011!C!\u0003+C!\"!*\u0006J\u0005\u0005I\u0011AC;)\r\u0001Vq\u000f\u0005\u000b\u0003\u001f+\u0019(!AA\u0002\u0005\u001d\u0005BCAW\u000b\u0013\n\u0009\u0011\"\u0011\u00020\"Q\u00111WC%\u0003\u0003%\u0009%!.\u0009\u0015\u0005eV\u0011JA\u0001\n\u0003*y\u0008F\u0002Q\u000b\u0003C!\"a$\u0006~\u0005\u0005\u0009\u0019AAD\r\u0019))\u0009\u0001!\u0006\u0008\n91+^2dKN\u001c8CBCB\u00093;%\nC\u0006\u0004b\u0016\r%Q3A\u0005\u0002\r%\u0007\"DCG\u000b\u0007\u0013\u0009\u0012)A\u0005\u0003\u0013!i)A\u0005fqB\u000cg\u000eZ3eA!A\u0011qECB\u0009\u0003)\u0009\n\u0006\u0003\u0006\u0014\u0016U\u0005cA\u0019\u0006\u0004\"A1\u0011]CH\u0001\u0004\u0009I\u0001\u0003\u0006\u0002D\u0015\r\u0015\u0011!C\u0001\u000b3#B!b%\u0006\u001c\"Q1\u0011]CL!\u0003\u0005\r!!\u0003\u0009\u0015\u0005US1QA\u0001\n\u0003\u0019I\r\u0003\u0006\u0002n\u0015\r\u0015\u0011!C!\u0003_B!\"a\u001e\u0006\u0004\u0006\u0005I\u0011AA=\u0011)\u0009\u0019)b!\u0002\u0002\u0013\u0005QQ\u0015\u000b\u0005\u0003\u000f+9\u000b\u0003\u0006\u0002\u0010\u0016\r\u0016\u0011!a\u0001\u0003wB!\"a%\u0006\u0004\u0006\u0005I\u0011IAK\u0011)\u0009)+b!\u0002\u0002\u0013\u0005QQ\u0016\u000b\u0004!\u0016=\u0006BCAH\u000bW\u000b\u0009\u00111\u0001\u0002\u0008\"Q\u0011QVCB\u0003\u0003%\u0009%a,\u0009\u0015\u0005MV1QA\u0001\n\u0003\n)\u000c\u0003\u0006\u0002:\u0016\r\u0015\u0011!C!\u000bo#2\u0001UC]\u0011)\u0009y)\".\u0002\u0002\u0003\u0007\u0011qQ\u0004\n\u000b{\u0003\u0011\u0011!E\u0001\u000b\u000bqaU;dG\u0016\u001c8\u000fE\u00022\u000b\u00034\u0011\"\"\"\u0001\u0003\u0003E\u0009!b1\u0014\u000b\u0015\u0005WQ\u0019&\u0011\u0011\rERqYA\u0005\u000b'KA!\"3\u00044\u0009\u0009\u0012IY:ue\u0006\u001cGOR;oGRLwN\\\u0019\u0009\u0011\u0005\u001dR\u0011\u0019C\u0001\u000b\u001b$\"!b0\u0009\u0015\u0005MV\u0011YA\u0001\n\u000b\n)\u000c\u0003\u0006\u0003\"\u0015\u0005\u0017\u0011!CA\u000b'$B!b%\u0006V\"A1\u0011]Ci\u0001\u0004\u0009I\u0001\u0003\u0006\u00034\u0015\u0005\u0017\u0011!CA\u000b3$B!b7\u0006^B)QB!\u000f\u0002\n!Q!QICl\u0003\u0003\u0005\r!b%\u0008\u0013\u0015\u0005\u0008!!A\u0009\u0002\u0015\r\u0018\u0001\u0003$bY2\u0014\u0017mY6\u0011\u0007E*)OB\u0005\u0006\u0014\u0001\u0009\u0009\u0011#\u0001\u0006hN)QQ]Cu\u0015BA1\u0011GCd\u0003\u0013)\u0009\u0003\u0003\u0005\u0002(\u0015\u0015H\u0011ACw)\u0009)\u0019\u000f\u0003\u0006\u00024\u0016\u0015\u0018\u0011!C#\u0003kC!B!\u0009\u0006f\u0006\u0005I\u0011QCz)\u0011)\u0009#\">\u0009\u0011\u0011\rT\u0011\u001fa\u0001\u0003\u0013A!Ba\r\u0006f\u0006\u0005I\u0011QC})\u0011)Y.b?\u0009\u0015\u0009\u0015Sq_A\u0001\u0002\u0004)\u0009cB\u0005\u0006\u0000\u0002\u0009\u0009\u0011#\u0001\u0007\u0002\u00059A)\u001a7bs\u0016$\u0007cA\u0019\u0007\u0004\u0019IA\u0011\u0015\u0001\u0002\u0002#\u0005aQA\n\u0006\r\u000719A\u0013\u0009\u0009\u0007c)9-!\u0003\u00050\"A\u0011q\u0005D\u0002\u0009\u00031Y\u0001\u0006\u0002\u0007\u0002!Q\u00111\u0017D\u0002\u0003\u0003%)%!.\u0009\u0015\u0009\u0005b1AA\u0001\n\u00033\u0009\u0002\u0006\u0003\u00050\u001aM\u0001\u0002\u0003C.\r\u001f\u0001\r!!\u0003\u0009\u0015\u0009Mb1AA\u0001\n\u000339\u0002\u0006\u0003\u0006\\\u001ae\u0001B\u0003B#\r+\u0009\u0009\u00111\u0001\u00050\u001eIaQ\u0004\u0001\u0002\u0002#\u0005aqD\u0001\u0008'.L\u0007\u000f]3e!\r\u0009d\u0011\u0005\u0004\n\u000b\u0017\u0002\u0011\u0011!E\u0001\rG\u0019RA\"\u0009\u0007&)\u0003\u0002b!\r\u0006H\u0006%Q1\u000c\u0005\u0009\u0003O1\u0009\u0003\"\u0001\u0007*Q\u0011aq\u0004\u0005\u000b\u0003g3\u0009#!A\u0005F\u0005U\u0006B\u0003B\u0011\rC\u0009\u0009\u0011\"!\u00070Q!Q1\u000cD\u0019\u0011!)\u0009F\"\u000cA\u0002\u0005%\u0001B\u0003B\u001a\rC\u0009\u0009\u0011\"!\u00076Q!Q1\u001cD\u001c\u0011)\u0011)Eb\r\u0002\u0002\u0003\u0007Q1L\u0004\n\rw\u0001\u0011\u0011!E\u0001\r{\u0009qAR1jYV\u0014X\rE\u00022\r1\u0011\u0002\"7\u0001\u0003\u0003E\u0009A\"\u0011\u0014\u000b\u0019}b1\u0009&\u0011\u0011\rERqYA\u0005\u0009SD\u0001\"a\n\u0007@\u0011\u0005aq\u0009\u000b\u0003\r{A!\"a-\u0007@\u0005\u0005IQIA[\u0011)\u0011\u0009Cb\u0010\u0002\u0002\u0013\u0005eQ\n\u000b\u0005\u0009S4y\u0005\u0003\u0005\u0005`\u001a-\u0003\u0019AA\u0005\u0011)\u0011\u0019Db\u0010\u0002\u0002\u0013\u0005e1\u000b\u000b\u0005\u000b74)\u0006\u0003\u0006\u0003F\u0019E\u0013\u0011!a\u0001\u0009SDqA\"\u0017\u0001\u0009\u00031Y&A\u0003EK2\u000c\u0017\u0010\u0006\u0003\u00050\u001au\u0003\u0002CBq\r/\u0002\r!!\u0003\u0009\u000f\u0019\u0005\u0004\u0001\"\u0001\u0007d\u0005!1k[5q)\u0011)YF\"\u001a\u0009\u0011\r\u0005hq\u000ca\u0001\u0003\u0013AqA\"\u001b\u0001\u0009\u00031Y'\u0001\u000cnC\u000e\u0014x.\u0012=qC:$w+\u001b;i%VtG/[7f)!!IJ\"\u001c\u0007p\u0019E\u0004\u0002\u0003BS\rO\u0002\rAa*\u0009\u0011\u0009Edq\ra\u0001\u0003\u0013Aqa\u0005D4\u0001\u00041\u0019\u0008E\u00022\rkJ1Ab\u001e\u0019\u00051i\u0015m\u0019:p%VtG/[7f\u0011\u001d1Y\u0008\u0001C\u0001\r{\n\u0011$\\1de>,\u0005\u0010]1oI^KG\u000f[8viJ+h\u000e^5nKR1A\u0011\u0014D@\r\u0003C\u0001B!*\u0007z\u0001\u0007!q\u0015\u0005\u0009\u0005c2I\u00081\u0001\u0002\n!AaQ\u0011\u0001A\u0002\u0013\u0005q*A\riCN\u0004VM\u001c3j]\u001el\u0015m\u0019:p\u000bb\u0004\u0018M\\:j_:\u001c\u0008\"\u0003DE\u0001\u0001\u0007I\u0011\u0001DF\u0003uA\u0017m\u001d)f]\u0012LgnZ'bGJ|W\u0009\u001f9b]NLwN\\:`I\u0015\u000cHc\u0001\u0014\u0007\u000e\"I\u0011q\u0012DD\u0003\u0003\u0005\r\u0001\u0015\u0005\u0007\r#\u0003A\u0011A(\u0002?QL\u0008/\u001a:TQ>,H\u000eZ#ya\u0006tG\rR3gKJ\u0014X\rZ'bGJ|7\u000fC\u0005\u0007\u0016\u0002\u0011\r\u0011\"\u0003\u0007\u0018\u00061am\u001c:dK\u0012,\"A\"'\u0011\r\rEf1TA\u0005\u0013\u00111ija-\u0003\u0017]+\u0017m\u001b%bg\"\u001cV\r\u001e\u0005\n\u00097\u0002!\u0019!C\u0005\rC+\"Ab)\u0011\u0011\u0019\u0015f1VA\u0005\r_k!Ab*\u000b\u0009\u0019%\u00161T\u0001\u0008[V$\u0018M\u00197f\u0013\u00111iKb*\u0003\u0017]+\u0017m\u001b%bg\"l\u0015\r\u001d\u0009\u0007\rK3\u0009,a\u001f\n\u0009\u0019Mfq\u0015\u0002\u0004'\u0016$\u0008b\u0002D\\\u0001\u0011%a\u0011X\u0001\nSN$U\r\\1zK\u0012$2\u0001\u0015D^\u0011!\u0011\u0009H\".A\u0002\u0005%\u0001B\u0002D`\u0001\u0011\u0005Q%\u0001\u0007dY\u0016\u000c'\u000fR3mCf,G\rC\u0004\u0007D\u0002!IA\"2\u0002)\r\u000cGnY;mCR,WK\u001c3fiB\u000c'/Y7t)\u00111yKb2\u0009\u0011\u0009Ed\u0011\u0019a\u0001\u0003\u0013A\u0011Bb3\u0001\u0005\u0004%IA\"4\u0002\u0017UtG-\u001a;qCJ\u000cWn]\u000b\u0003\r\u001f\u0004bA\"*\u0007R\u0006m\u0014\u0002\u0002Dj\rO\u0013q\u0001S1tQN+G\u000fC\u0004\u0007X\u0002!\u0009A\"7\u0002-9|G/\u001b4z+:$W\r\u001e9be\u0006l7/\u00113eK\u0012$2A\nDn\u0011!1iN\"6A\u0002\u0019}\u0017!\u00038foVsG-\u001a;t!\u0011\u0009hO!\u0016\u0009\u000f\u0019\r\u0008\u0001\"\u0001\u0007f\u0006Ibn\u001c;jMf,f\u000eZ3ua\u0006\u0014\u0018-\\:J]\u001a,'O]3e)\u00151cq\u001dDv\u0011!1IO\"9A\u0002\u0019}\u0017aC;oI\u0016$hj\\'pe\u0016D\u0001B\"<\u0007b\u0002\u0007aq^\u0001\nS:4WM\u001d:fIN\u0004B!\u001d<\u0003\u0008\"9a1\u001f\u0001\u0005\u0002\u0019U\u0018AD7bGJ|W\u0009\u001f9b]\u0012\u000cE\u000e\u001c\u000b\u0007\u0003\u001319P\"?\u0009\u0011\u0009\u0015f\u0011\u001fa\u0001\u0005OC\u0001B!\u001d\u0007r\u0002\u0007\u0011\u0011\u0002\u0009\u0004w\u0006E\u0001"
  val b = "\u0006\u0001\u0019uh!C\u0001\u0003!\u0003\r\u0009a\u0003D~\u0005\u0019i\u0015m\u0019:pg*\u00111\u0001B\u0001\u000cif\u0004Xm\u00195fG.,'O\u0003\u0002\u0006\r\u0005\u0019an]2\u000b\u0005\u001dA\u0011!\u0002;p_2\u001c(\"A\u0005\u0002\u000bM\u001c\u0017\r\\1\u0004\u0001M)\u0001\u0001\u0004\u0009\u001bAA\u0011QBD\u0007\u0002\u0011%\u0011q\u0002\u0003\u0002\u0007\u0003:L(+\u001a4\u0011\u0005EAR\"\u0001\n\u000b\u0005M!\u0012a\u0002:v]RLW.\u001a\u0006\u0003+Y\u0009a!\\1de>\u001c(BA\u000c\u0009\u0003\u001d\u0011XM\u001a7fGRL!!\u0007\n\u0003\u001b5\u000b7M]8Sk:$\u0018.\\3t!\u0009Yb$D\u0001\u001d\u0015\u0009iB#\u0001\u0003vi&d\u0017BA\u0010\u001d\u0005\u0019!&/Y2fgB\u00111$I\u0005\u0003Eq\u0011q\u0001S3ma\u0016\u00148\u000fC\u0003%\u0001\u0011\u0005Q%\u0001\u0004%S:LG\u000f\n\u000b\u0002MA\u0011QbJ\u0005\u0003Q!\u0011A!\u00168ji\"A!\u0006\u0001EC\u0002\u0013\u00051&A\u0005gCN$HK]1dWV\u0009A\u0006E\u0002._Ej\u0011A\u000c\u0006\u0003/\u0019I!\u0001\r\u0018\u0003\u0013\u0019\u000b7\u000f\u001e+sC\u000e\\W\"\u0001\u0001\u0009\u000bM\u0002A\u0011\u0001\u001b\u0002\u001d\u001ddwNY1m'\u0016$H/\u001b8hgV\u0009Q\u0007\u0005\u00027o5\u0009A!\u0003\u00029\u0009\u0009A1+\u001a;uS:<7\u000fC\u0003;\u0001\u0011E1(\u0001\u000bgS:$W*Y2s_\u000ec\u0017m]:M_\u0006$WM\u001d\u000b\u0002yA\u0011QHQ\u0007\u0002})\u0011q\u0008Q\u0001\u0005Y\u0006twMC\u0001B\u0003\u0011Q\u0017M^1\n\u0005\rs$aC\"mCN\u001cHj\\1eKJ4A!\u0012\u0001A\r\n\u0001R*Y2s_&k\u0007\u000f\u001c\"j]\u0012LgnZ\n\u0005\u000929%\n\u0005\u0002\u000e\u0011&\u0011\u0011\n\u0003\u0002\u0008!J|G-^2u!\u0009i1*\u0003\u0002M\u0011\u0009a1+\u001a:jC2L'0\u00192mK\"Aa\n\u0012BK\u0002\u0013\u0005q*\u0001\u0005jg\n+h\u000e\u001a7f+\u0005\u0001\u0006CA\u0007R\u0013\u0009\u0011\u0006BA\u0004C_>dW-\u00198\u0009\u0011Q#%\u0011#Q\u0001\nA\u000b\u0011\"[:Ck:$G.\u001a\u0011\u0009\u0011Y#%Q3A\u0005\u0002=\u000b!\"[:CY\u0006\u001c7NY8y\u0011!AFI!E!\u0002\u0013\u0001\u0016aC5t\u00052\u000c7m\u001b2pq\u0002B\u0001B\u0017#\u0003\u0016\u0004%\u0009aW\u0001\nG2\u000c7o\u001d(b[\u0016,\u0012\u0001\u0018\u0009\u0003;\u0012t!A\u00182\u0011\u0005}CQ\"\u00011\u000b\u0005\u0005T\u0011A\u0002\u001fs_>$h(\u0003\u0002d\u0011\u00051\u0001K]3eK\u001aL!!\u001a4\u0003\rM#(/\u001b8h\u0015\u0009\u0019\u0007\u0002\u0003\u0005i\u0009\nE\u0009\u0015!\u0003]\u0003)\u0019G.Y:t\u001d\u0006lW\r\u0009\u0005\u0009U\u0012\u0013)\u001a!C\u00017\u0006AQ.\u001a;i\u001d\u0006lW\r\u0003\u0005m\u0009\nE\u0009\u0015!\u0003]\u0003%iW\r\u001e5OC6,\u0007\u0005\u0003\u0005o\u0009\nU\r\u0011\"\u0001p\u0003%\u0019\u0018n\u001a8biV\u0014X-F\u0001q!\r\u0009h/\u001f\u0008\u0003eRt!aX:\n\u0003%I!!\u001e\u0005\u0002\u000fA\u000c7m[1hK&\u0011q\u000f\u001f\u0002\u0005\u0019&\u001cHO\u0003\u0002v\u0011A\u0019\u0011O\u001e>\u0011\u0005mdX\"\u0001\u0002\n\u0005u\u0014!a\u0003$j]\u001e,'\u000f\u001d:j]RD\u0001b #\u0003\u0012\u0003\u0006I\u0001]\u0001\u000bg&<g.\u0019;ve\u0016\u0004\u0003BCA\u0002\u0009\nU\r\u0011\"\u0001\u0002\u0006\u0005)A/\u0019:hgV\u0011\u0011q\u0001\u0009\u0005cZ\u000cI\u0001\u0005\u0003\u0002\u000c\u0005UabA\u0019\u0002\u000e%!\u0011qBA\u0009\u0003\u00199Gn\u001c2bY&\u0019\u00111\u0003\u0002\u0003\u0011\u0005s\u0017\r\\={KJLA!a\u0006\u0002\u001a\u0009!AK]3f\u0013\u0011\u0009Y\"!\u0008\u0003\u000bQ\u0013X-Z:\u000b\u0007\u0005}a#\u0001\u0005j]R,'O\\1m\u0011)\u0009\u0019\u0003\u0012B\u0009B\u0003%\u0011qA\u0001\u0007i\u0006\u0014xm\u001d\u0011\u0009\u000f\u0005\u001dB\u0009\"\u0001\u0002*\u00051A(\u001b8jiz\"b\"a\u000b\u0002.\u0005=\u0012\u0011GA\u001a\u0003k\u00099\u0004\u0005\u00022\u0009\"1a*!\nA\u0002ACaAVA\u0013\u0001\u0004\u0001\u0006B\u0002.\u0002&\u0001\u0007A\u000c\u0003\u0004k\u0003K\u0001\r\u0001\u0018\u0005\u0007]\u0006\u0015\u0002\u0019\u00019\u0009\u0011\u0005\r\u0011Q\u0005a\u0001\u0003\u000fAa!a\u000fE\u0009\u0003y\u0015!F5t?\u0012\nX.\u0019:lIEl\u0017M]6%c6\u000c'o\u001b\u0005\u0007\u0003!E\u0011A(\u0002\u0015%\u001cx\u000b[5uK\n|\u0007\u0010C\u0005\u0002D\u0011\u000b\u0009\u0011\"\u0001\u0002F\u0005!1m\u001c9z)9\u0009Y#a\u0012\u0002J\u0005-\u0013QJA(\u0003#B\u0001BTA!!\u0003\u0005\r\u0001\u0015\u0005\u0009-\u0006\u0005\u0003\u0013!a\u0001!\"A!,!\u0011\u0011\u0002\u0003\u0007A\u000c\u0003\u0005k\u0003\u0003\u0002\n\u00111\u0001]\u0011!q\u0017\u0011\u0009I\u0001\u0002\u0004\u0001\u0008BCA\u0002\u0003\u0003\u0002\n\u00111\u0001\u0002\u0008!A\u0011Q\u000b#\u0002\u0002\u0013\u0005q*\u0001\u0008d_BLH\u0005Z3gCVdG\u000fJ\u0019\u0009\u0011\u0005eC)!A\u0005\u0002=\u000babY8qs\u0012\"WMZ1vYR$#\u0007\u0003\u0005\u0002^\u0011\u000b\u0009\u0011\"\u0001\\\u00039\u0019w\u000e]=%I\u00164\u0017-\u001e7uIMB\u0001\"!\u0019E\u0003\u0003%\u0009aW\u0001\u000fG>\u0004\u0018\u0010\n3fM\u0006,H\u000e\u001e\u00135\u0011!\u0009)\u0007RA\u0001\n\u0003y\u0017AD2paf$C-\u001a4bk2$H%\u000e\u0005\n\u0003S\"\u0015\u0011!C\u0001\u0003\u000b\u0009abY8qs\u0012\"WMZ1vYR$c\u0007C\u0005\u0002n\u0011\u000b\u0009\u0011\"\u0011\u0002p\u0005i\u0001O]8ek\u000e$\u0008K]3gSb,\"!!\u001d\u0011\u0007u\n\u0019(\u0003\u0002f}!I\u0011q\u000f#\u0002\u0002\u0013\u0005\u0011\u0011P\u0001\raJ|G-^2u\u0003JLG/_\u000b\u0003\u0003w\u00022!DA?\u0013\r\u0009y\u0008\u0003\u0002\u0004\u0013:$\u0008\"CAB\u0009\u0006\u0005I\u0011AAC\u00039\u0001(o\u001c3vGR,E.Z7f]R$B!a\"\u0002\u000eB\u0019Q\"!#\n\u0007\u0005-\u0005BA\u0002B]fD!\"a$\u0002\u0002\u0006\u0005\u0009\u0019AA>\u0003\rAH%\r\u0005\n\u0003'#\u0015\u0011!C!\u0003+\u000bq\u0002\u001d:pIV\u001cG/\u0013;fe\u0006$xN]\u000b\u0003\u0003/\u0003b!!'\u0002 \u0006\u001dUBAAN\u0015\r\u0009i\nC\u0001\u000bG>dG.Z2uS>t\u0017\u0002BAQ\u00037\u0013\u0001\"\u0013;fe\u0006$xN\u001d\u0005\n\u0003K#\u0015\u0011!C\u0001\u0003O\u000b\u0001bY1o\u000bF,\u0018\r\u001c\u000b\u0004!\u0006%\u0006BCAH\u0003G\u000b\u0009\u00111\u0001\u0002\u0008\"I\u0011Q\u0016#\u0002\u0002\u0013\u0005\u0013qV\u0001\u0009Q\u0006\u001c\u0008nQ8eKR\u0011\u00111\u0010\u0005\n\u0003g#\u0015\u0011!C!\u0003k\u000b\u0001\u0002^8TiJLgn\u001a\u000b\u0003\u0003cB\u0011\"!/E\u0003\u0003%\u0009%a/\u0002\r\u0015\u000cX/\u00197t)\r\u0001\u0016Q\u0018\u0005\u000b\u0003\u001f\u000b9,!AA\u0002\u0005\u001duaBAa\u0001!\u0005\u00111Y\u0001\u0011\u001b\u0006\u001c'o\\%na2\u0014\u0015N\u001c3j]\u001e\u00042!MAc\r\u0019)\u0005\u0001#\u0001\u0002HN!\u0011Q\u0019\u0007K\u0011!\u00099#!2\u0005\u0002\u0005-GCAAb\u0011!\u0009y-!2\u0005\u0002\u0005E\u0017A\u00039jG.dW-\u0011;p[R!\u0011\u0011BAj\u0011!\u0009).!4A\u0002\u0005\u001d\u0015aA8cU\"A\u0011\u0011\\Ac\u0009\u0003\u0009Y.\u0001\u0007v]BL7m\u001b7f\u0003R|W\u000e\u0006\u0003\u0002\u0008\u0006u\u0007\u0002CAp\u0003/\u0004\r!!\u0003\u0002\u0009Q\u0014X-\u001a\u0005\u0009\u0003G\u000c)\r\"\u0001\u0002f\u00061\u0001/[2lY\u0016$B!!\u0003\u0002h\"A\u0011\u0011^Aq\u0001\u0004\u0009I!\u0001\u0007nC\u000e\u0014x.S7qYJ+g\r\u0003\u0005\u0002n\u0006\u0015G\u0011AAx\u0003!)h\u000e]5dW2,G\u0003BA\u0016\u0003cD\u0001\"a9\u0002l\u0002\u0007\u0011\u0011\u0002\u0005\u0009\u0003k\u000c)\r\"\u0003\u0002x\u0006\u0019!m\u001c=\u0016\u0009\u0005e(1\u0004\u000b\u0005\u0003w\u0014\u0019\u0002\r\u0003\u0002~\n\u001d\u0001#B/\u0002\u0000\n\r\u0011b\u0001B\u0001M\n)1\u0009\\1tgB!!Q\u0001B\u0004\u0019\u0001!AB!\u0003\u0002t\u0006\u0005\u0009\u0011!B\u0001\u0005\u0017\u00111a\u0018\u00132#\u0011\u0011i!a\"\u0011\u00075\u0011y!C\u0002\u0003\u0012!\u0011qAT8uQ&tw\r\u0003\u0005\u0003\u0016\u0005M\u0008\u0019\u0001B\u000c\u0003\u0015\u0019G.\u0019>{!\u0015i\u0016q B\r!\u0011\u0011)Aa\u0007\u0005\u0011\u0009u\u00111\u001fb\u0001\u0005\u0017\u0011\u0011\u0001\u0016\u0005\u000b\u0005C\u0009)-!A\u0005\u0002\n\r\u0012!B1qa2LHCDA\u0016\u0005K\u00119C!\u000b\u0003,\u00095\"q\u0006\u0005\u0007\u001d\n}\u0001\u0019\u0001)\u0009\rY\u0013y\u00021\u0001Q\u0011\u0019Q&q\u0004a\u00019\"1!Na\u0008A\u0002qCaA\u001cB\u0010\u0001\u0004\u0001\u0008\u0002CA\u0002\u0005?\u0001\r!a\u0002\u0009\u0015\u0009M\u0012QYA\u0001\n\u0003\u0013)$A\u0004v]\u0006\u0004\u0008\u000f\\=\u0015\u0009\u0009]\"1\u0009\u0009\u0006\u001b\u0009e\"QH\u0005\u0004\u0005wA!AB(qi&|g\u000e\u0005\u0006\u000e\u0005\u0001\u0006\u000b\u0018/q\u0003\u000fI1A!\u0011\u0009\u0005\u0019!V\u000f\u001d7fm!Q!Q\u0009B\u0019\u0003\u0003\u0005\r!a\u000b\u0002\u0007a$\u0003\u0007C\u0004\u0003J\u0001!\u0009!a\u001c\u0002\u00175\u000c7M]8F]\u001eLg.\u001a\u0005\u0008\u0005\u001b\u0002A\u0011\u0001B(\u00035\u0011\u0017N\u001c3NC\u000e\u0014x.S7qYR)aE!\u0015\u0003`!A!1\u000bB&\u0001\u0004\u0011)&\u0001\u0005nC\u000e\u0014x\u000eR3g!\u0011\u0009YAa\u0016\n\u0009\u0009e#1\u000c\u0002\u0007'fl'm\u001c7\n\u0009\u0009u\u0013Q\u0004\u0002\u0008'fl'm\u001c7t\u0011!\u0009IOa\u0013A\u0002\u0005%\u0001b\u0002B2\u0001\u0011\u0005!QM\u0001\u0015Y>\u000cG-T1de>LU\u000e\u001d7CS:$\u0017N\\4\u0015\u0009\u0009\u001d$\u0011\u000e\u0009\u0006\u001b\u0009e\u00121\u0006\u0005\u0009\u0005'\u0012\u0009\u00071\u0001\u0003V!1a\u000b\u0001C\u0001\u0005[\"2\u0001\u0015B8\u0011!\u0011\u0009Ha\u001bA\u0002\u0005%\u0011\u0001C3ya\u0006tG-Z3\u0009\rY\u0003A\u0011\u0001B;)\r\u0001&q\u000f\u0005\u0009\u0005'\u0012\u0019\u00081\u0001\u0003V!9!1\u0010\u0001\u0005\u0002\u0009u\u0014AE:uC:$\u0017M\u001d3Jg\nc\u0017mY6c_b$2\u0001\u0015B@\u0011!\u0011\u0019F!\u001fA\u0002\u0009U\u0003b\u0002BB\u0001\u0011\u0005!QQ\u0001$G>l\u0007/\u001e;f\u001b\u0006\u001c'o\u001c#fMRK\u0008/\u001a$s_6l\u0015m\u0019:p\u00136\u0004HNU3g)\u0019\u00119I!%\u0003\u001cB!\u00111\u0002BE\u0013\u0011\u0011YI!$\u0003\u0009QK\u0008/Z\u0005\u0005\u0005\u001f\u000biBA\u0003UsB,7\u000f\u0003\u0005\u0003\u0014\n\u0005\u0005\u0019\u0001BK\u0003%i\u0017m\u0019:p\u0009\u0012,g\r\u0005\u0003\u0002\u000c\u0009]\u0015\u0002\u0002BM\u00033\u0011a\u0001R3g\u0009\u00164\u0007\u0002CAu\u0005\u0003\u0003\r!!\u0003\u0009\u000f\u0009}\u0005\u0001\"\u0001\u0003\"\u0006qA/\u001f9fI6\u000b7M]8C_\u0012LHCBA\u0005\u0005G\u0013\u0009\u000c\u0003\u0005\u0003&\nu\u0005\u0019\u0001BT\u0003\u0015!\u0018\u0010]3s!\r\u0009$\u0011V\u0005\u0005\u0005W\u0013iKA\u0003UsB,'/C\u0002\u00030\n\u0011a\u0001V=qKJ\u001c\u0008\u0002\u0003BJ\u0005;\u0003\rA!&\u0009\u000f\u0009U\u0006\u0001\"\u0001\u00038\u000612\u000f^1oI\u0006\u0014H\rV=qK\u0012l\u0015m\u0019:p\u0005>$\u0017\u0010\u0006\u0004\u0002\n\u0009e&1\u0018\u0005\u0009\u0005K\u0013\u0019\u000c1\u0001\u0003(\"A!1\u0013BZ\u0001\u0004\u0011)\nC\u0004\u0003@\u0002!\u0009A!1\u0002\u00195\u000c7M]8D_:$X\r\u001f;\u0015\u0011\u0009\r'Q\u001aBh\u0005'\u00042!\rBc\u0013\u0011\u00119M!3\u0003\u00195\u000b7M]8D_:$X\r\u001f;\n\u0007\u0009-'A\u0001\u0008Ti\u0012\u000cE\u000f^1dQ6,g\u000e^:\u0009\u0011\u0009\u0015&Q\u0018a\u0001\u0005OC\u0001B!5\u0003>\u0002\u0007\u0011\u0011B\u0001\u000baJ,g-\u001b=Ue\u0016,\u0007\u0002\u0003Bk\u0005{\u0003\r!!\u0003\u0002\u0019\u0015D\u0008/\u00198eK\u0016$&/Z3\u0007\r\u0009e\u0007\u0001\u0011Bn\u0005%i\u0015m\u0019:p\u0003J<7oE\u0003\u0003X29%\nC\u0006\u0003`\n]'Q3A\u0005\u0002\u0009\u0005\u0018!A2\u0016\u0005\u0009\r\u0007b\u0003Bs\u0005/\u0014\u0009\u0012)A\u0005\u0005\u0007\u000c!a\u0019\u0011\u0009\u0017\u0009%(q\u001bBK\u0002\u0013\u0005!1^\u0001\u0007_RDWM]:\u0016\u0005\u00095\u0008\u0003B9w\u0003\u000fC1B!=\u0003X\nE\u0009\u0015!\u0003\u0003n\u00069q\u000e\u001e5feN\u0004\u0003\u0002CA\u0014\u0005/$\u0009A!>\u0015\r\u0009](\u0011 B~!\r\u0009$q\u001b\u0005\u0009\u0005?\u0014\u0019\u00101\u0001\u0003D\"A!\u0011\u001eBz\u0001\u0004\u0011i\u000f\u0003\u0006\u0002D\u0009]\u0017\u0011!C\u0001\u0005$bAa>\u0004\u0002\r\r\u0001B\u0003Bp\u0005{\u0004\n\u00111\u0001\u0003D\"Q!\u0011\u001eB!\u0003\u0005\rA!<\u0009\u0015\u0005U#q[A\u0001\n\u0003\u0011\u0009\u000f\u0003\u0006\u0002Z\u0009]\u0017\u0011!C\u0001\u0005WD!\"!\u001c\u0003X\u0006\u0005I\u0011IA8\u0011)\u00099Ha6\u0002\u0002\u0013\u0005\u0011\u0011\u0010\u0005\u000b\u0003\u0007\u00139.!A\u0005\u0002\r=A\u0003BAD\u0007#A!\"a$\u0004\u000e\u0005\u0005\u0009\u0019AA>\u0011)\u0009\u0019Ja6\u0002\u0002\u0013\u0005\u0013Q\u0013\u0005\u000b\u0003K\u00139.!A\u0005\u0002\r]Ac\u0001)\u0004\u001a!Q\u0011qRB\u000b\u0003\u0003\u0005\r!a\"\u0009\u0015\u00055&q[A\u0001\n\u0003\ny\u000b\u0003\u0006\u00024\n]\u0017\u0011!C!\u0003kC!\"!/\u0003X\u0006\u0005I\u0011IB\u0011)\r\u000161\u0005\u0005\u000b\u0003\u001f\u001by\"!AA\u0002\u0005\u001du!CB\u0014\u0001\u0005\u0005\u0009\u0012AB\u0015\u0003%i\u0015m\u0019:p\u0003J<7\u000fE\u00022\u0007W1\u0011B!7\u0001\u0003\u0003E\u0009a!\u000c\u0014\u000b\r-2q\u0006&\u0011\u0015\rE2Q\u0007Bb\u0005[\u001490\u0004\u0002\u00044)\u00111\u0003C\u0005\u0005\u0007o\u0019\u0019DA\u0009BEN$(/Y2u\rVt7\r^5p]JB\u0001\"a\n\u0004,\u0011\u000511\u0008\u000b\u0003\u0007SA!\"a-\u0004,\u0005\u0005IQIA[\u0011)\u0011\u0009ca\u000b\u0002\u0002\u0013\u00055\u0011\u0009\u000b\u0007\u0005o\u001c\u0019e!\u0012\u0009\u0011\u0009}7q\u0008a\u0001\u0005\u0007D\u0001B!;\u0004@\u0001\u0007!Q\u001e\u0005\u000b\u0005g\u0019Y#!A\u0005\u0002\u000e%C\u0003BB&\u0007'\u0002R!\u0004B\u001d\u0007\u001b\u0002r!DB(\u0005\u0007\u0014i/C\u0002\u0004R!\u0011a\u0001V;qY\u0016\u0014\u0004B\u0003B#\u0007\u000f\n\u0009\u00111\u0001\u0003x\"91q\u000b\u0001\u0005\u0002\re\u0013!C7bGJ|\u0017I]4t)\u0019\u00119pa\u0017\u0004^!A!QUB+\u0001\u0004\u00119\u000b\u0003\u0005\u0003r\rU\u0003\u0019AA\u0005\u0011\u001d\u0019\u0009\u0007\u0001C\u0001\u0007G\n\u0011c\u001d;b]\u0012\u000c'\u000fZ'bGJ|\u0017I]4t)\u0019\u00119p!\u001a\u0004h!A!QUB0\u0001\u0004\u00119\u000b\u0003\u0005\u0003r\r}\u0003\u0019AA\u0005\u0011%\u0019Y\u0007\u0001a\u0001\n\u0003\u0019i'A\u0006`_B,g.T1de>\u001cXCAB8!\u0019\u0019\u0009ha\u001e\u0004z5\u001111\u000f\u0006\u0005\u0007k\nY*A\u0005j[6,H/\u00192mK&\u0019qoa\u001d\u0013\u0009\rm4q\u0010\u0004\u0007\u0007{\u0002\u0001a!\u001f\u0003\u0019q\u0012XMZ5oK6,g\u000e\u001e \u0011\u0009\r\u00055qQ\u0007\u0003\u0007\u0007S1a!\"\u0015\u0003!\u0019wN\u001c;fqR\u001c\u0018\u0002BBE\u0007\u0007\u0013qaQ8oi\u0016DH\u000f\u0003\u0006\u0004\u000e\u000em$\u0019!D!\u0007\u001f\u000b\u0001\"\u001e8jm\u0016\u00148/Z\u000b\u0003\u0003\u0017A\u0011ba%\u0001\u0001\u0004%\u0009a!&\u0002\u001f}{\u0007/\u001a8NC\u000e\u0014xn]0%KF$2AJBL\u0011)\u0009yi!%\u0002\u0002\u0003\u00071q\u000e\u0005\u0008\u00077\u0003A\u0011AB7\u0003)y\u0007/\u001a8NC\u000e\u0014xn\u001d\u0005\u0008\u0007?\u0003A\u0011ABQ\u0003A\u0001Xo\u001d5NC\u000e\u0014xnQ8oi\u0016DH\u000fF\u0002'\u0007GC\u0001Ba8\u0004\u001e\u0002\u0007!1\u0019\u0005\u0007\u0007O\u0003A\u0011A\u0013\u0002\u001fA|\u0007/T1de>\u001cuN\u001c;fqRDqaa+\u0001\u0009\u0003\u0019i+\u0001\u000cf]\u000edwn]5oO6\u000b7M]8Q_NLG/[8o+\u0009\u0019y\u000b\u0005\u0003\u00042\u000eUVBABZ\u0015\ri\u0012QD\u0005\u0005\u0007o\u001b\u0019L\u0001\u0005Q_NLG/[8o\r\u001d\u0019Y\u000cAA\u0001\u0007{\u0013Q\"T1de>,\u0005\u0010]1oI\u0016\u00148cAB]\u0019!Y!QUB]\u0005\u000b\u0007I\u0011ABa+\u0009\u00119\u000bC\u0006\u0004F\u000ee&\u0011!Q\u0001\n\u0009\u001d\u0016A\u0002;za\u0016\u0014\u0008\u0005C\u0006\u0003r\re&Q1A\u0005\u0002\r%WCAA\u0005\u0011-\u0019im!/\u0003\u0002\u0003\u0006I!!\u0003\u0002\u0013\u0015D\u0008/\u00198eK\u0016\u0004\u0003\u0002CA\u0014\u0007s#\u0009a!5\u0015\r\rM7Q[Bl!\r\u00094\u0011\u0018\u0005\u0009\u0005K\u001by\r1\u0001\u0003(\"A!\u0011OBh\u0001\u0004\u0009I\u0001\u0003\u0005\u0004\\\u000eef\u0011ABo\u0003%ygnU;dG\u0016\u001c8\u000f\u0006\u0003\u0002\n\r}\u0007\u0002CBq\u00073\u0004\r!!\u0003\u0002\u0011\u0015D\u0008/\u00198eK\u0012D\u0001b!:\u0004:\u001a\u00051q]\u0001\u000b_:4\u0015\r\u001c7cC\u000e\\G\u0003BA\u0005\u0007SD\u0001b!9\u0004d\u0002\u0007\u0011\u0011\u0002\u0005\u0009\u0007[\u001cI\u000c\"\u0001\u0004p\u0006aqN\\*vaB\u0014Xm]:fIR!\u0011\u0011BBy\u0011!\u0011\u0009ha;A\u0002\u0005%\u0001\u0002CB{\u0007s#\u0009aa>\u0002\u0013=tG)\u001a7bs\u0016$G\u0003BA\u0005\u0007sD\u0001b!9\u0004t\u0002\u0007\u0011\u0011\u0002\u0005\u0009\u0007{\u001cI\u000c\"\u0001\u0004\u0000\u0006IqN\\*lSB\u0004X\r\u001a\u000b\u0005\u0003\u0013!\u0009\u0001\u0003\u0005\u0004b\u000em\u0008\u0019AA\u0005\u0011!!)a!/\u0005\u0002\u0011\u001d\u0011!C8o\r\u0006LG.\u001e:f)\u0011\u0009I\u0001\"\u0003\u0009\u0011\r\u0005H1\u0001a\u0001\u0003\u0013A\u0001B!\u0009\u0004:\u0012\u0005AQ\u0002\u000b\u0005\u0003\u0013!y\u0001\u0003\u0005\u0005\u0012\u0011-\u0001\u0019AA\u0005\u0003%!Wm];hCJ,G\r\u0003\u0005\u0005\u0016\reF\u0011\u0003C\u000c\u0003\u0019)\u0007\u0010]1oIR!\u0011\u0011\u0002C\r\u0011!!\u0009\u0002b\u0005A\u0002\u0005%aA\u0002C\u000f\u0001\u0001!yB\u0001\u0009EK\u001al\u0015m\u0019:p\u000bb\u0004\u0018M\u001c3feN!A1DBj\u00115\u0011)\u000bb\u0007\u0003\u0002\u0003\u0006IAa*\u0004@\"i!\u0011\u000fC\u000e\u0005\u0003\u0005\u000b\u0011BA\u0005\u0007\u000fD1\u0002b\n\u0005\u001c\u0009\u0005\u0009\u0015!\u0003\u0005*\u0005!Qn\u001c3f!\u0011!Y\u0003b\u000c\u000f\u0007Y\"i#\u0003\u0002v\u0009%!A\u0011\u0007C\u001a\u0005\u0011iu\u000eZ3\u000b\u0005U$\u0001b\u0003C\u001c\u00097\u0011\u0009\u0011)A\u0005\u0005\u000f\u000bqa\\;uKJ\u0004F\u000f\u0003\u0005\u0002(\u0011mA\u0011\u0001C\u001e))!i\u0004b\u0010\u0005B\u0011\rCQ\u0009\u0009\u0004c\u0011m\u0001\u0002\u0003BS\u0009s\u0001\rAa*\u0009\u0011\u0009ED\u0011\u0008a\u0001\u0003\u0013A\u0001\u0002b\n\u0005:\u0001\u0007A\u0011\u0006\u0005\u0009\u0009o!I\u00041\u0001\u0003\u0008\"YA\u0011\nC\u000e\u0011\u000b\u0007I\u0011\u0001C&\u0003\u001dIgN\\3s!R,\"Aa\"\u0009\u0011\rmG1\u0004C!\u0009\u001f\"B!!\u0003\u0005R!AA1\u000bC'\u0001\u0004\u0009I!A\u0005fqB\u000cg\u000eZ3ea!A1Q\u001fC\u000e\u0009\u0003\"9\u0006\u0006\u0003\u0002\n\u0011e\u0003\u0002\u0003C.\u0009+\u0002\r!!\u0003\u0002\u000f\u0011,G.Y=fI\"A1Q\u001dC\u000e\u0009\u0003\"y\u0006\u0006\u0003\u0002\n\u0011\u0005\u0004\u0002\u0003C2\u0009;\u0002\r!!\u0003\u0002\u0011\u0019\u000cG\u000e\u001c2bG.Dq\u0002b\u001a\u0005\u001cA\u0005\u0019\u0011!A\u0005\n\r\u00057qX\u0001\u000cgV\u0004XM\u001d\u0013usB,'\u000fC\u0004\u0005l\u0001!\u0009\u0001\"\u001c\u0002\u00175\u000c7M]8FqB\u000cg\u000e\u001a\u000b\u000b\u0003\u0013!y\u0007\"\u001d\u0005t\u0011U\u0004\u0002\u0003BS\u0009S\u0002\rAa*\u0009\u0011\u0009ED\u0011\u000ea\u0001\u0003\u0013A\u0001\u0002b\n\u0005j\u0001\u0007A\u0011\u0006\u0005\u0009\u0009o\"I\u00071\u0001\u0003\u0008\u0006\u0011\u0001\u000f\u001e\u0005\u0008\u0009w\u0002A\u0011\u0001C?\u0003M\u0019H/\u00198eCJ$W*Y2s_\u0016C\u0008/\u00198e))\u0009I\u0001b \u0005\u0002\u0012\rEQ\u0011\u0005\u0009\u0005K#I\u00081\u0001\u0003(\"A!\u0011\u000fC=\u0001\u0004\u0009I\u0001\u0003\u0005\u0005(\u0011e\u0004\u0019\u0001C\u0015\u0011!!9\u0008\"\u001fA\u0002\u0009\u001dea\u0002CE\u0001\u0005\u0005B1\u0012\u0002\u000c\u001b\u0006\u001c'o\\*uCR,8oE\u0002\u0005\u00082A1\u0002b$\u0005\u0008\n\u0015\r\u0011\"\u0001\u0004J\u00061!/Z:vYRD1\u0002b%\u0005\u0008\n\u0005\u0009\u0015!\u0003\u0002\n\u00059!/Z:vYR\u0004\u0003\u0002CA\u0014\u0009\u000f#\u0009\u0001b&\u0015\u0009\u0011eE1\u0014\u0009\u0004c\u0011\u001d\u0005\u0002\u0003CH\u0009+\u0003\r!!\u0003*\u0019\u0011\u001dEq\u0014Cl\u000b#)I%b!\u0007\r\u0011\u0005\u0006\u0001\u0011CR\u0005\u001d!U\r\\1zK\u0012\u001cb\u0001b(\u0005\u001a\u001eS\u0005b\u0003C.\u0009?\u0013)\u001a!C\u0001\u0007\u0013DQ\u0002\"+\u0005 \nE\u0009\u0015!\u0003\u0002\n\u00115\u0015\u0001\u00033fY\u0006LX\r\u001a\u0011\u0009\u0011\u0005\u001dBq\u0014C\u0001\u0009[#B\u0001b,\u00052B\u0019\u0011\u0007b(\u0009\u0011\u0011mC1\u0016a\u0001\u0003\u0013A!\"a\u0011\u0005 \u0006\u0005I\u0011\u0001C[)\u0011!y\u000bb.\u0009\u0015\u0011mC1\u0017I\u0001\u0002\u0004\u0009I\u0001\u0003\u0006\u0002V\u0011}\u0015\u0011!C\u0001\u0007\u0013D!\"!\u001c\u0005 \u0006\u0005I\u0011IA8\u0011)\u00099\u0008b(\u0002\u0002\u0013\u0005\u0011\u0011\u0010\u0005\u000b\u0003\u0007#y*!A\u0005\u0002\u0011\u0005G\u0003BAD\u0009\u0007D!\"a$\u0005@\u0006\u0005\u0009\u0019AA>\u0011)\u0009\u0019\nb(\u0002\u0002\u0013\u0005\u0013Q\u0013\u0005\u000b\u0003K#y*!A\u0005\u0002\u0011%Gc\u0001)\u0005L\"Q\u0011q\u0012Cd\u0003\u0003\u0005\r!a\"\u0009\u0015\u00055FqTA\u0001\n\u0003\ny\u000b\u0003\u0006\u00024\u0012}\u0015\u0011!C!\u0003kC!\"!/\u0005 \u0006\u0005I\u0011\u0009Cj)\r\u0001FQ\u001b\u0005\u000b\u0003\u001f#\u0009.!AA\u0002\u0005\u001deA\u0002Cm\u0001\u0001#YNA\u0004GC&dWO]3\u0014\r\u0011]G\u0011T$K\u0011-!y\u000eb6\u0003\u0016\u0004%\u0009a!3\u0002\u000f\u0019\u000c\u0017\u000e\\;sK\"iA1\u001dCl\u0005#\u0005\u000b\u0011BA\u0005\u0009\u001b\u000b\u0001BZ1jYV\u0014X\r\u0009\u0005\u0009\u0003O!9\u000e\"\u0001\u0005hR!A\u0011\u001eCv!\r\u0009Dq\u001b\u0005\u0009\u0009?$)\u000f1\u0001\u0002\n!Q\u00111\u0009Cl\u0003\u0003%\u0009\u0001b<\u0015\u0009\u0011%H\u0011\u001f\u0005\u000b\u0009?$i\u000f%AA\u0002\u0005%\u0001BCA+\u0009/\u000c\u0009\u0011\"\u0001\u0004J\"Q\u0011Q\u000eCl\u0003\u0003%\u0009%a\u001c\u0009\u0015\u0005]Dq[A\u0001\n\u0003\u0009I\u0008\u0003\u0006\u0002\u0004\u0012]\u0017\u0011!C\u0001\u0009w$B!a\"\u0005~\"Q\u0011q\u0012C}\u0003\u0003\u0005\r!a\u001f\u0009\u0015\u0005MEq[A\u0001\n\u0003\n)\n\u0003\u0006\u0002&\u0012]\u0017\u0011!C\u0001\u000b\u0007!2\u0001UC\u0003\u0011)\u0009y)\"\u0001\u0002\u0002\u0003\u0007\u0011q\u0011\u0005\u000b\u0003[#9.!A\u0005B\u0005=\u0006BCAZ\u0009/\u000c\u0009\u0011\"\u0011\u00026\"Q\u0011\u0011\u0018Cl\u0003\u0003%\u0009%\"\u0004\u0015\u0007A+y\u0001\u0003\u0006\u0002\u0010\u0016-\u0011\u0011!a\u0001\u0003\u000f3a!b\u0005\u0001\u0001\u0016U!\u0001\u0003$bY2\u0014\u0017mY6\u0014\r\u0015EA\u0011T$K\u0011-!\u0019'\"\u0005\u0003\u0016\u0004%\u0009a!3\u0009\u001b\u0015mQ\u0011\u0003B\u0009B\u0003%\u0011\u0011\u0002CG\u0003%1\u0017\r\u001c7cC\u000e\\\u0007\u0005\u0003\u0005\u0002(\u0015EA\u0011AC\u0010)\u0011)\u0009#b\u0009\u0011\u0007E*\u0009\u0002\u0003\u0005\u0005d\u0015u\u0001\u0019AA\u0005\u0011)\u0009\u0019%\"\u0005\u0002\u0002\u0013\u0005Qq\u0005\u000b\u0005\u000bC)I\u0003\u0003\u0006\u0005d\u0015\u0015\u0002\u0013!a\u0001\u0003\u0013A!\"!\u0016\u0006\u0012\u0005\u0005I\u0011ABe\u0011)\u0009i'\"\u0005\u0002\u0002\u0013\u0005\u0013q\u000e\u0005\u000b\u0003o*\u0009\"!A\u0005\u0002\u0005e\u0004BCAB\u000b#\u0009\u0009\u0011\"\u0001\u00064Q!\u0011qQC\u001b\u0011)\u0009y)\"\r\u0002\u0002\u0003\u0007\u00111\u0010\u0005\u000b\u0003'+\u0009\"!A\u0005B\u0005U\u0005BCAS\u000b#\u0009\u0009\u0011\"\u0001\u0006<Q\u0019\u0001+\"\u0010\u0009\u0015\u0005=U\u0011HA\u0001\u0002\u0004\u00099\u0009\u0003\u0006\u0002.\u0016E\u0011\u0011!C!\u0003_C!\"a-\u0006\u0012\u0005\u0005I\u0011IA[\u0011)\u0009I,\"\u0005\u0002\u0002\u0013\u0005SQ\u0009\u000b\u0004!\u0016\u001d\u0003BCAH\u000b\u0007\n\u0009\u00111\u0001\u0002\u0008\u001a1Q1\n\u0001A\u000b\u001b\u0012qaU6jaB,Gm\u0005\u0004\u0006J\u0011euI\u0013\u0005\u000c\u000b#*IE!f\u0001\n\u0003\u0019I-A\u0004tW&\u0004\u0008/\u001a3\u0009\u001b\u0015US\u0011\nB\u0009B\u0003%\u0011\u0011\u0002CG\u0003!\u00198.\u001b9qK\u0012\u0004\u0003\u0002CA\u0014\u000b\u0013\"\u0009!\"\u0017\u0015\u0009\u0015mSQ\u000c\u0009\u0004c\u0015%\u0003\u0002CC)\u000b/\u0002\r!!\u0003\u0009\u0015\u0005\rS\u0011JA\u0001\n\u0003)\u0009\u0007\u0006\u0003\u0006\\\u0015\r\u0004BCC)\u000b?\u0002\n\u00111\u0001\u0002\n!Q\u0011QKC%\u0003\u0003%\u0009a!3\u0009\u0015\u00055T\u0011JA\u0001\n\u0003\ny\u0007\u0003\u0006\u0002x\u0015%\u0013\u0011!C\u0001\u0003sB!\"a!\u0006J\u0005\u0005I\u0011AC7)\u0011\u00099)b\u001c\u0009\u0015\u0005=U1NA\u0001\u0002\u0004\u0009Y\u0008\u0003\u0006\u0002\u0014\u0016%\u0013\u0011!C!\u0003+C!\"!*\u0006J\u0005\u0005I\u0011AC;)\r\u0001Vq\u000f\u0005\u000b\u0003\u001f+\u0019(!AA\u0002\u0005\u001d\u0005BCAW\u000b\u0013\n\u0009\u0011\"\u0011\u00020\"Q\u00111WC%\u0003\u0003%\u0009%!.\u0009\u0015\u0005eV\u0011JA\u0001\n\u0003*y\u0008F\u0002Q\u000b\u0003C!\"a$\u0006~\u0005\u0005\u0009\u0019AAD\r\u0019))\u0009\u0001!\u0006\u0008\n91+^2dKN\u001c8CBCB\u00093;%\nC\u0006\u0004b\u0016\r%Q3A\u0005\u0002\r%\u0007\"DCG\u000b\u0007\u0013\u0009\u0012)A\u0005\u0003\u0013!i)A\u0005fqB\u000cg\u000eZ3eA!A\u0011qECB\u0009\u0003)\u0009\n\u0006\u0003\u0006\u0014\u0016U\u0005cA\u0019\u0006\u0004\"A1\u0011]CH\u0001\u0004\u0009I\u0001\u0003\u0006\u0002D\u0015\r\u0015\u0011!C\u0001\u000b3#B!b%\u0006\u001c\"Q1\u0011]CL!\u0003\u0005\r!!\u0003\u0009\u0015\u0005US1QA\u0001\n\u0003\u0019I\r\u0003\u0006\u0002n\u0015\r\u0015\u0011!C!\u0003_B!\"a\u001e\u0006\u0004\u0006\u0005I\u0011AA=\u0011)\u0009\u0019)b!\u0002\u0002\u0013\u0005QQ\u0015\u000b\u0005\u0003\u000f+9\u000b\u0003\u0006\u0002\u0010\u0016\r\u0016\u0011!a\u0001\u0003wB!\"a%\u0006\u0004\u0006\u0005I\u0011IAK\u0011)\u0009)+b!\u0002\u0002\u0013\u0005QQ\u0016\u000b\u0004!\u0016=\u0006BCAH\u000bW\u000b\u0009\u00111\u0001\u0002\u0008\"Q\u0011QVCB\u0003\u0003%\u0009%a,\u0009\u0015\u0005MV1QA\u0001\n\u0003\n)\u000c\u0003\u0006\u0002:\u0016\r\u0015\u0011!C!\u000bo#2\u0001UC]\u0011)\u0009y)\".\u0002\u0002\u0003\u0007\u0011qQ\u0004\n\u000b{\u0003\u0011\u0011!E\u0001\u000b\u000bqaU;dG\u0016\u001c8\u000fE\u00022\u000b\u00034\u0011\"\"\"\u0001\u0003\u0003E\u0009!b1\u0014\u000b\u0015\u0005WQ\u0019&\u0011\u0011\rERqYA\u0005\u000b'KA!\"3\u00044\u0009\u0009\u0012IY:ue\u0006\u001cGOR;oGRLwN\\\u0019\u0009\u0011\u0005\u001dR\u0011\u0019C\u0001\u000b\u001b$\"!b0\u0009\u0015\u0005MV\u0011YA\u0001\n\u000b\n)\u000c\u0003\u0006\u0003\"\u0015\u0005\u0017\u0011!CA\u000b'$B!b%\u0006V\"A1\u0011]Ci\u0001\u0004\u0009I\u0001\u0003\u0006\u00034\u0015\u0005\u0017\u0011!CA\u000b3$B!b7\u0006^B)QB!\u000f\u0002\n!Q!QICl\u0003\u0003\u0005\r!b%\u0008\u0013\u0015\u0005\u0008!!A\u0009\u0002\u0015\r\u0018\u0001\u0003$bY2\u0014\u0017mY6\u0011\u0007E*)OB\u0005\u0006\u0014\u0001\u0009\u0009\u0011#\u0001\u0006hN)QQ]Cu\u0015BA1\u0011GCd\u0003\u0013)\u0009\u0003\u0003\u0005\u0002(\u0015\u0015H\u0011ACw)\u0009)\u0019\u000f\u0003\u0006\u00024\u0016\u0015\u0018\u0011!C#\u0003kC!B!\u0009\u0006f\u0006\u0005I\u0011QCz)\u0011)\u0009#\">\u0009\u0011\u0011\rT\u0011\u001fa\u0001\u0003\u0013A!Ba\r\u0006f\u0006\u0005I\u0011QC})\u0011)Y.b?\u0009\u0015\u0009\u0015Sq_A\u0001\u0002\u0004)\u0009cB\u0005\u0006\u0000\u0002\u0009\u0009\u0011#\u0001\u0007\u0002\u00059A)\u001a7bs\u0016$\u0007cA\u0019\u0007\u0004\u0019IA\u0011\u0015\u0001\u0002\u0002#\u0005aQA\n\u0006\r\u000719A\u0013\u0009\u0009\u0007c)9-!\u0003\u00050\"A\u0011q\u0005D\u0002\u0009\u00031Y\u0001\u0006\u0002\u0007\u0002!Q\u00111\u0017D\u0002\u0003\u0003%)%!.\u0009\u0015\u0009\u0005b1AA\u0001\n\u00033\u0009\u0002\u0006\u0003\u00050\u001aM\u0001\u0002\u0003C.\r\u001f\u0001\r!!\u0003\u0009\u0015\u0009Mb1AA\u0001\n\u000339\u0002\u0006\u0003\u0006\\\u001ae\u0001B\u0003B#\r+\u0009\u0009\u00111\u0001\u00050\u001eIaQ\u0004\u0001\u0002\u0002#\u0005aqD\u0001\u0008'.L\u0007\u000f]3e!\r\u0009d\u0011\u0005\u0004\n\u000b\u0017\u0002\u0011\u0011!E\u0001\rG\u0019RA\"\u0009\u0007&)\u0003\u0002b!\r\u0006H\u0006%Q1\u000c\u0005\u0009\u0003O1\u0009\u0003\"\u0001\u0007*Q\u0011aq\u0004\u0005\u000b\u0003g3\u0009#!A\u0005F\u0005U\u0006B\u0003B\u0011\rC\u0009\u0009\u0011\"!\u00070Q!Q1\u000cD\u0019\u0011!)\u0009F\"\u000cA\u0002\u0005%\u0001B\u0003B\u001a\rC\u0009\u0009\u0011\"!\u00076Q!Q1\u001cD\u001c\u0011)\u0011)Eb\r\u0002\u0002\u0003\u0007Q1L\u0004\n\rw\u0001\u0011\u0011!E\u0001\r{\u0009qAR1jYV\u0014X\rE\u00022\r1\u0011\u0002\"7\u0001\u0003\u0003E\u0009A\"\u0011\u0014\u000b\u0019}b1\u0009&\u0011\u0011\rERqYA\u0005\u0009SD\u0001\"a\n\u0007@\u0011\u0005aq\u0009\u000b\u0003\r{A!\"a-\u0007@\u0005\u0005IQIA[\u0011)\u0011\u0009Cb\u0010\u0002\u0002\u0013\u0005eQ\n\u000b\u0005\u0009S4y\u0005\u0003\u0005\u0005`\u001a-\u0003\u0019AA\u0005\u0011)\u0011\u0019Db\u0010\u0002\u0002\u0013\u0005e1\u000b\u000b\u0005\u000b74)\u0006\u0003\u0006\u0003F\u0019E\u0013\u0011!a\u0001\u0009SDqA\"\u0017\u0001\u0009\u00031Y&A\u0003EK2\u000c\u0017\u0010\u0006\u0003\u00050\u001au\u0003\u0002CBq\r/\u0002\r!!\u0003\u0009\u000f\u0019\u0005\u0004\u0001\"\u0001\u0007d\u0005!1k[5q)\u0011)YF\"\u001a\u0009\u0011\r\u0005hq\u000ca\u0001\u0003\u0013AqA\"\u001b\u0001\u0009\u00031Y'\u0001\u000cnC\u000e\u0014x.\u0012=qC:$w+\u001b;i%VtG/[7f)!!IJ\"\u001c\u0007p\u0019E\u0004\u0002\u0003BS\rO\u0002\rAa*\u0009\u0011\u0009Edq\ra\u0001\u0003\u0013Aqa\u0005D4\u0001\u00041\u0019\u0008E\u00022\rkJ1Ab\u001e\u0019\u00051i\u0015m\u0019:p%VtG/[7f\u0011\u001d1Y\u0008\u0001C\u0001\r{\n\u0011$\\1de>,\u0005\u0010]1oI^KG\u000f[8viJ+h\u000e^5nKR1A\u0011\u0014D@\r\u0003C\u0001B!*\u0007z\u0001\u0007!q\u0015\u0005\u0009\u0005c2I\u00081\u0001\u0002\n!AaQ\u0011\u0001A\u0002\u0013\u0005q*A\riCN\u0004VM\u001c3j]\u001el\u0015m\u0019:p\u000bb\u0004\u0018M\\:j_:\u001c\u0008\"\u0003DE\u0001\u0001\u0007I\u0011\u0001DF\u0003uA\u0017m\u001d)f]\u0012LgnZ'bGJ|W\u0009\u001f9b]NLwN\\:`I\u0015\u000cHc\u0001\u0014\u0007\u000e\"I\u0011q\u0012DD\u0003\u0003\u0005\r\u0001\u0015\u0005\u0007\r#\u0003A\u0011A(\u0002?QL\u0008/\u001a:TQ>,H\u000eZ#ya\u0006tG\rR3gKJ\u0014X\rZ'bGJ|7\u000fC\u0005\u0007\u0016\u0002\u0011\r\u0011\"\u0003\u0007\u0018\u00061am\u001c:dK\u0012,\"A\"'\u0011\r\rEf1TA\u0005\u0013\u00111ija-\u0003\u0017]+\u0017m\u001b%bg\"\u001cV\r\u001e\u0005\n\u00097\u0002!\u0019!C\u0005\rC+\"Ab)\u0011\u0011\u0019\u0015f1VA\u0005\r_k!Ab*\u000b\u0009\u0019%\u00161T\u0001\u0008[V$\u0018M\u00197f\u0013\u00111iKb*\u0003\u0017]+\u0017m\u001b%bg\"l\u0015\r\u001d\u0009\u0007\rK3\u0009,a\u001f\n\u0009\u0019Mfq\u0015\u0002\u0004'\u0016$\u0008b\u0002D\\\u0001\u0011%a\u0011X\u0001\nSN$U\r\\1zK\u0012$2\u0001\u0015D^\u0011!\u0011\u0009H\".A\u0002\u0005%\u0001B\u0002D`\u0001\u0011\u0005Q%\u0001\u0007dY\u0016\u000c'\u000fR3mCf,G\rC\u0004\u0007D\u0002!IA\"2\u0002)\r\u000cGnY;mCR,WK\u001c3fiB\u000c'/Y7t)\u00111yKb2\u0009\u0011\u0009Ed\u0011\u0019a\u0001\u0003\u0013A\u0011Bb3\u0001\u0005\u0004%IA\"4\u0002\u0017UtG-\u001a;qCJ\u000cWn]\u000b\u0003\r\u001f\u0004bA\"*\u0007R\u0006m\u0014\u0002\u0002Dj\rO\u0013q\u0001S1tQN+G\u000fC\u0004\u0007X\u0002!\u0009A\"7\u0002-9|G/\u001b4z+:$W\r\u001e9be\u0006l7/\u00113eK\u0012$2A\nDn\u0011!1iN\"6A\u0002\u0019}\u0017!\u00038foVsG-\u001a;t!\u0011\u0009hO!\u0016\u0009\u000f\u0019\r\u0008\u0001\"\u0001\u0007f\u0006Ibn\u001c;jMf,f\u000eZ3ua\u0006\u0014\u0018-\\:J]\u001a,'O]3e)\u00151cq\u001dDv\u0011!1IO\"9A\u0002\u0019}\u0017aC;oI\u0016$hj\\'pe\u0016D\u0001B\"<\u0007b\u0002\u0007aq^\u0001\nS:4WM\u001d:fIN\u0004B!\u001d<\u0003\u0008\"9a1\u001f\u0001\u0005\u0002\u0019U\u0018AD7bGJ|W\u0009\u001f9b]\u0012\u000cE\u000e\u001c\u000b\u0007\u0003\u001319P\"?\u0009\u0011\u0009\u0015f\u0011\u001fa\u0001\u0005OC\u0001B!\u001d\u0007r\u0002\u0007\u0011\u0011\u0002\u0009\u0004w\u0006E\u0001"
diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
index 57660b37bd..fd63fdc943 100644
--- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
+++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
@@ -192,11 +192,13 @@ abstract class UnPickler {
     protected def readName(): Name = {
       val tag = readByte()
       val len = readNat()
-      tag match {
+      val result = tag match {
         case TERMname => newTermName(bytes, readIndex, len)
         case TYPEname => newTypeName(bytes, readIndex, len)
         case _ => errorBadSignature("bad name tag: " + tag)
       }
+      println(result)
+      result
     }
     private def readEnd() = readNat() + readIndex

@@ -328,6 +330,7 @@ abstract class UnPickler {
         )
         if (shouldEnterInOwnerScope)
           symScope(sym.owner) enter sym
+        println(sym.name + " " + sym.debugFlagString)

         sym
       }
--- /tmp/a.log  2018-01-22 17:03:37.000000000 +1000
+++ /tmp/b.log  2018-01-22 17:03:38.000000000 +1000
@@ -562,7 +562,7 @@
 <refinement>
 universe
 <refinement>
-universe <method> <deferred> <stable> <accessor>
+universe <method> <deferred> override <stable> <accessor>
 _openMacros_$eq
 _openMacros_$eq <method> <accessor>
 x$1 <param> <synthetic>

This looks likely to be a player:

https://github.com/scala/scala/blob/bf9dd703af989bc32c484d9d578cbd8c85da508f/src/compiler/scala/tools/nsc/typechecker/Typers.scala#L3061-L3071

retronym commented 6 years ago

Minimized as:

âš¡ tail sandbox/{a,b}.scala && (echo "== a.scala b.scala"; qscalac -d /tmp -Ydebug -Xprint:typer sandbox/{a,b}.scala; echo "== b.scala a.scala";qscalac -d /tmp -Ydebug -Xprint:typer sandbox/{b,a}.scala  && echo "== b.scala" ; qscalac -d /tmp -Ydebug -Xprint:typer sandbox/b.scala) 2>&1 | egrep '==|def foo'
==> sandbox/a.scala <==
trait Context {
  val universe: Global
}

trait StdAttachments {
  self: Analyzer =>

  type UnaffiliatedMacroContext = Context
  type MacroContext = UnaffiliatedMacroContext { val universe: self.global.type }
}

==> sandbox/b.scala <==
class Macros {
    self: Analyzer =>
  def foo = List.apply[MacroContext]()
}
== a.scala b.scala
    <method> def foo: immutable.this.List[<empty>.this.Context{<method> <deferred> override <stable> <accessor> val universe: Macros.this.global.type}] = scala.collection.immutable.Nil
== b.scala a.scala
    <method> def foo: immutable.this.List[<empty>.this.Context{<method> <deferred> <stable> <accessor> val universe: Macros.this.global.type}] = scala.collection.immutable.Nil
== b.scala
    <method> def foo: immutable.this.List[<empty>.this.Context{<method> <deferred> override <stable> <accessor> val universe: Macros.this.global.type}] = scala.collection.immutable.Nil
retronym commented 6 years ago

The instability in the order of module vars/accessors in, e.g MatchTranslator, is due to the fact that the order of decls in a class info type is not explicitly pickled. After unpickling, the decls are ordered based on the order of entries in the pickle index, and that order is influenced by references, not just definitions.

We could update pickler to walk and enter decls before considering references (basically make it two pass). Another alternative might be to modify the pickle format to explicitly write the decl order.

gkossakowski commented 6 years ago

one of the sources of instability in builds that we encountered is non-determinism in macros we're building tooling to catch these problems more systematically (in bazel setting)

retronym commented 6 years ago

Quick progress update: I've submitted all the changes in my prototype branch as PRs. See https://github.com/scala/scala-dev/issues/405 for links.

Mostly they are against 2.13.x. If the set of changes prove stable and comprehensive in that branch, we might consider a 2.12 backport, but no guarantees.