Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
retronym opened this issue Jan 10, 2018 · 21 comments
Open

Comments

@retronym
Copy link
Owner

retronym commented Jan 10, 2018

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 scala/scala#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
Copy link

dragos commented Jan 10, 2018

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: dragos/scala@7c0f351

@dragos
Copy link

dragos commented Jan 10, 2018

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

  • the order of source files need not be the same
  • you can recompile a subset of all project files as long as the other files were compiled previously, didn't change, and are on the classpath (touch-ing some files and recompiling should give exactly the same results)

@johnynek
Copy link

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
Copy link

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 (sbt/io#58). It would be nice to get good performance on incremental compilation while keeping these properties.

@johnynek
Copy link

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
Copy link
Owner Author

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
Copy link
Owner Author

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
Copy link
Owner Author

/cc @smarter

@ittaiz
Copy link

ittaiz commented Jan 11, 2018

@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
Copy link

smarter commented Jan 11, 2018

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
Copy link
Owner Author

retronym commented Jan 17, 2018

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

@xeno-by
Copy link

xeno-by commented Jan 17, 2018

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

@retronym
Copy link
Owner Author

retronym commented Jan 18, 2018

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
Copy link
Owner Author

retronym commented Jan 22, 2018

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
Copy link
Owner Author

retronym commented Jan 22, 2018

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
Copy link
Owner Author

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
Copy link
Owner Author

retronym commented Jan 22, 2018

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\r�1\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\r�1\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
Copy link
Owner Author

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
Copy link
Owner Author

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
Copy link

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
Copy link
Owner Author

retronym commented Feb 2, 2018

Quick progress update: I've submitted all the changes in my prototype branch as PRs. See scala/scala-dev#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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants