From f459d57fdb9416442e9c49da2620f1d737fd4c85 Mon Sep 17 00:00:00 2001 From: ben Date: Mon, 14 Mar 2016 12:12:54 -0400 Subject: [PATCH] [icfp] add gregor benchmark --- icfp-2016/benchmark/README.md | 4 +- icfp-2016/benchmark/gregor/base/cldr/core.rkt | 104 ++++ .../gregor/base/cldr/data/cldr-core.zip | Bin 0 -> 103857 bytes icfp-2016/benchmark/gregor/base/cldr/file.rkt | 80 ++++ icfp-2016/benchmark/gregor/base/cldr/info.rkt | 3 + .../gregor/base/cldr/likely-subtags.rkt | 102 ++++ .../base/cldr/scribblings/cldr-core.scrbl | 207 ++++++++ icfp-2016/benchmark/gregor/base/types.rkt | 4 + .../benchmark/gregor/base/tzinfo/info.rkt | 5 + .../benchmark/gregor/base/tzinfo/main.rkt | 79 +++ .../gregor/base/tzinfo/private/generics.rkt | 15 + .../gregor/base/tzinfo/private/os/env.rkt | 6 + .../gregor/base/tzinfo/private/os/unix.rkt | 70 +++ .../tzinfo/private/os/windows-registry.rkt | 81 ++++ .../gregor/base/tzinfo/private/os/windows.rkt | 49 ++ .../gregor/base/tzinfo/private/structs.rkt | 47 ++ .../base/tzinfo/private/tabfile-parser.rkt | 59 +++ .../base/tzinfo/private/tzfile-parser.rkt | 132 +++++ .../base/tzinfo/private/zoneinfo-search.rkt | 65 +++ .../gregor/base/tzinfo/private/zoneinfo.rkt | 127 +++++ .../base/tzinfo/scribblings/tzinfo.scrbl | 229 +++++++++ .../benchmark/gregor/base/tzinfo/source.rkt | 17 + .../base/tzinfo/test/data/32-bit/+VERSION | 1 + .../base/tzinfo/test/data/32-bit/Factory | Bin 0 -> 101 bytes .../base/tzinfo/test/data/32-bit/US/Alaska | Bin 0 -> 861 bytes .../base/tzinfo/test/data/32-bit/US/Aleutian | Bin 0 -> 858 bytes .../base/tzinfo/test/data/32-bit/US/Arizona | Bin 0 -> 130 bytes .../base/tzinfo/test/data/32-bit/US/Central | Bin 0 -> 1279 bytes .../tzinfo/test/data/32-bit/US/East-Indiana | Bin 0 -> 606 bytes .../base/tzinfo/test/data/32-bit/US/Eastern | Bin 0 -> 1267 bytes .../base/tzinfo/test/data/32-bit/US/Hawaii | Bin 0 -> 101 bytes .../tzinfo/test/data/32-bit/US/Indiana-Starke | Bin 0 -> 869 bytes .../base/tzinfo/test/data/32-bit/US/Michigan | Bin 0 -> 811 bytes .../base/tzinfo/test/data/32-bit/US/Mountain | Bin 0 -> 877 bytes .../base/tzinfo/test/data/32-bit/US/Pacific | Bin 0 -> 1017 bytes .../base/tzinfo/test/data/32-bit/US/Samoa | Bin 0 -> 125 bytes .../gregor/base/tzinfo/test/data/32-bit/UTC | Bin 0 -> 56 bytes .../base/tzinfo/test/data/32-bit/iso3166.tab | 275 +++++++++++ .../base/tzinfo/test/data/32-bit/posixrules | Bin 0 -> 1267 bytes .../base/tzinfo/test/data/32-bit/zone.tab | 452 ++++++++++++++++++ .../base/tzinfo/test/data/64-bit/Factory | Bin 0 -> 264 bytes .../base/tzinfo/test/data/64-bit/US/Alaska | Bin 0 -> 2384 bytes .../base/tzinfo/test/data/64-bit/US/Aleutian | Bin 0 -> 2379 bytes .../base/tzinfo/test/data/64-bit/US/Arizona | Bin 0 -> 353 bytes .../base/tzinfo/test/data/64-bit/US/Central | Bin 0 -> 3585 bytes .../tzinfo/test/data/64-bit/US/East-Indiana | Bin 0 -> 1675 bytes .../base/tzinfo/test/data/64-bit/US/Eastern | Bin 0 -> 3545 bytes .../base/tzinfo/test/data/64-bit/US/Hawaii | Bin 0 -> 276 bytes .../tzinfo/test/data/64-bit/US/Indiana-Starke | Bin 0 -> 2437 bytes .../base/tzinfo/test/data/64-bit/US/Michigan | Bin 0 -> 2216 bytes .../base/tzinfo/test/data/64-bit/US/Mountain | Bin 0 -> 2453 bytes .../base/tzinfo/test/data/64-bit/US/Pacific | Bin 0 -> 2845 bytes .../tzinfo/test/data/64-bit/US/Pacific-New | Bin 0 -> 2845 bytes .../base/tzinfo/test/data/64-bit/US/Samoa | Bin 0 -> 272 bytes .../gregor/base/tzinfo/test/data/64-bit/UTC | Bin 0 -> 127 bytes .../base/tzinfo/test/data/64-bit/iso3166.tab | 275 +++++++++++ .../base/tzinfo/test/data/64-bit/localtime | Bin 0 -> 127 bytes .../base/tzinfo/test/data/64-bit/posixrules | Bin 0 -> 3545 bytes .../base/tzinfo/test/data/64-bit/zone.tab | 439 +++++++++++++++++ .../base/tzinfo/test/data/64-bit/zone1970.tab | 369 ++++++++++++++ .../gregor/base/tzinfo/test/zoneinfo.rkt | 64 +++ .../benchmark/gregor/base/tzinfo/zoneinfo.rkt | 9 + icfp-2016/benchmark/gregor/post/clock.rkt | 79 +++ .../benchmark/gregor/post/core-adapter.rkt | 15 + .../benchmark/gregor/post/core-structs.rkt | 23 + icfp-2016/benchmark/gregor/post/date.rkt | 129 +++++ icfp-2016/benchmark/gregor/post/datetime.rkt | 166 +++++++ .../benchmark/gregor/post/difference.rkt | 76 +++ .../benchmark/gregor/post/gregor-adapter.rkt | 24 + .../benchmark/gregor/post/gregor-structs.rkt | 28 ++ icfp-2016/benchmark/gregor/post/hmsn.rkt | 66 +++ icfp-2016/benchmark/gregor/post/main.rkt | 143 ++++++ .../benchmark/gregor/post/moment-base.rkt | 51 ++ icfp-2016/benchmark/gregor/post/moment.rkt | 180 +++++++ .../gregor/post/offset-resolvers.rkt | 141 ++++++ .../benchmark/gregor/post/structs-adapter.rkt | 15 + icfp-2016/benchmark/gregor/post/time.rkt | 89 ++++ .../benchmark/gregor/post/tzinfo-adapter.rkt | 22 + icfp-2016/benchmark/gregor/post/ymd.rkt | 243 ++++++++++ icfp-2016/benchmark/gregor/pre/clock.rkt | 78 +++ .../benchmark/gregor/pre/core-adapter.rkt | 14 + .../benchmark/gregor/pre/core-structs.rkt | 22 + icfp-2016/benchmark/gregor/pre/date.rkt | 128 +++++ icfp-2016/benchmark/gregor/pre/datetime.rkt | 165 +++++++ icfp-2016/benchmark/gregor/pre/difference.rkt | 75 +++ .../benchmark/gregor/pre/gregor-adapter.rkt | 23 + .../benchmark/gregor/pre/gregor-structs.rkt | 27 ++ icfp-2016/benchmark/gregor/pre/hmsn.rkt | 65 +++ icfp-2016/benchmark/gregor/pre/main.rkt | 142 ++++++ .../benchmark/gregor/pre/moment-base.rkt | 50 ++ icfp-2016/benchmark/gregor/pre/moment.rkt | 179 +++++++ .../benchmark/gregor/pre/offset-resolvers.rkt | 140 ++++++ .../benchmark/gregor/pre/structs-adapter.rkt | 14 + icfp-2016/benchmark/gregor/pre/time.rkt | 88 ++++ .../benchmark/gregor/pre/tzinfo-adapter.rkt | 21 + icfp-2016/benchmark/gregor/pre/ymd.rkt | 242 ++++++++++ .../modulegraph/{data => base}/acquire.tex | 0 .../modulegraph/{data => base}/echo.tex | 0 .../modulegraph/{data => base}/forth.tex | 0 .../modulegraph/{data => base}/fsm.tex | 0 .../modulegraph/{data => base}/fsmoo.tex | 0 .../modulegraph/{data => base}/fsmv2.tex | 0 .../modulegraph/{data => base}/gregor.tex | 0 .../modulegraph/{data => base}/htdp.tex | 0 .../modulegraph/{data => base}/kcfa.tex | 0 .../modulegraph/{data => base}/lnm.tex | 0 .../modulegraph/{data => base}/mbta.tex | 0 .../modulegraph/{data => base}/morsecode.tex | 0 .../modulegraph/{data => base}/quad.tex | 0 .../modulegraph/{data => base}/quadU.tex | 0 .../modulegraph/{data => base}/sieve.tex | 0 .../modulegraph/{data => base}/snake.tex | 0 .../modulegraph/{data => base}/suffixtree.tex | 0 .../modulegraph/{data => base}/synth.tex | 0 .../modulegraph/{data => base}/tetris.tex | 0 .../modulegraph/{data => base}/zombie.tex | 0 .../modulegraph/{data => base}/zordoz.tex | 0 icfp-2016/benchmark/modulegraph/post/main.rkt | 2 +- icfp-2016/benchmark/modulegraph/pre/main.rkt | 2 +- 119 files changed, 6333 insertions(+), 3 deletions(-) create mode 100644 icfp-2016/benchmark/gregor/base/cldr/core.rkt create mode 100644 icfp-2016/benchmark/gregor/base/cldr/data/cldr-core.zip create mode 100644 icfp-2016/benchmark/gregor/base/cldr/file.rkt create mode 100644 icfp-2016/benchmark/gregor/base/cldr/info.rkt create mode 100644 icfp-2016/benchmark/gregor/base/cldr/likely-subtags.rkt create mode 100644 icfp-2016/benchmark/gregor/base/cldr/scribblings/cldr-core.scrbl create mode 100644 icfp-2016/benchmark/gregor/base/types.rkt create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/info.rkt create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/main.rkt create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/private/generics.rkt create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/private/os/env.rkt create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/private/os/unix.rkt create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/private/os/windows-registry.rkt create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/private/os/windows.rkt create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/private/structs.rkt create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/private/tabfile-parser.rkt create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/private/tzfile-parser.rkt create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/private/zoneinfo-search.rkt create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/private/zoneinfo.rkt create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/scribblings/tzinfo.scrbl create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/source.rkt create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/+VERSION create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/Factory create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Alaska create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Aleutian create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Arizona create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Central create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/East-Indiana create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Eastern create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Hawaii create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Indiana-Starke create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Michigan create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Mountain create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Pacific create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Samoa create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/UTC create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/iso3166.tab create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/posixrules create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/zone.tab create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/Factory create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Alaska create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Aleutian create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Arizona create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Central create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/East-Indiana create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Eastern create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Hawaii create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Indiana-Starke create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Michigan create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Mountain create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Pacific create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Pacific-New create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Samoa create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/UTC create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/iso3166.tab create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/localtime create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/posixrules create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/zone.tab create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/zone1970.tab create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/test/zoneinfo.rkt create mode 100644 icfp-2016/benchmark/gregor/base/tzinfo/zoneinfo.rkt create mode 100644 icfp-2016/benchmark/gregor/post/clock.rkt create mode 100644 icfp-2016/benchmark/gregor/post/core-adapter.rkt create mode 100644 icfp-2016/benchmark/gregor/post/core-structs.rkt create mode 100644 icfp-2016/benchmark/gregor/post/date.rkt create mode 100644 icfp-2016/benchmark/gregor/post/datetime.rkt create mode 100644 icfp-2016/benchmark/gregor/post/difference.rkt create mode 100644 icfp-2016/benchmark/gregor/post/gregor-adapter.rkt create mode 100644 icfp-2016/benchmark/gregor/post/gregor-structs.rkt create mode 100644 icfp-2016/benchmark/gregor/post/hmsn.rkt create mode 100644 icfp-2016/benchmark/gregor/post/main.rkt create mode 100644 icfp-2016/benchmark/gregor/post/moment-base.rkt create mode 100644 icfp-2016/benchmark/gregor/post/moment.rkt create mode 100644 icfp-2016/benchmark/gregor/post/offset-resolvers.rkt create mode 100644 icfp-2016/benchmark/gregor/post/structs-adapter.rkt create mode 100644 icfp-2016/benchmark/gregor/post/time.rkt create mode 100644 icfp-2016/benchmark/gregor/post/tzinfo-adapter.rkt create mode 100644 icfp-2016/benchmark/gregor/post/ymd.rkt create mode 100644 icfp-2016/benchmark/gregor/pre/clock.rkt create mode 100644 icfp-2016/benchmark/gregor/pre/core-adapter.rkt create mode 100644 icfp-2016/benchmark/gregor/pre/core-structs.rkt create mode 100644 icfp-2016/benchmark/gregor/pre/date.rkt create mode 100644 icfp-2016/benchmark/gregor/pre/datetime.rkt create mode 100644 icfp-2016/benchmark/gregor/pre/difference.rkt create mode 100644 icfp-2016/benchmark/gregor/pre/gregor-adapter.rkt create mode 100644 icfp-2016/benchmark/gregor/pre/gregor-structs.rkt create mode 100644 icfp-2016/benchmark/gregor/pre/hmsn.rkt create mode 100644 icfp-2016/benchmark/gregor/pre/main.rkt create mode 100644 icfp-2016/benchmark/gregor/pre/moment-base.rkt create mode 100644 icfp-2016/benchmark/gregor/pre/moment.rkt create mode 100644 icfp-2016/benchmark/gregor/pre/offset-resolvers.rkt create mode 100644 icfp-2016/benchmark/gregor/pre/structs-adapter.rkt create mode 100644 icfp-2016/benchmark/gregor/pre/time.rkt create mode 100644 icfp-2016/benchmark/gregor/pre/tzinfo-adapter.rkt create mode 100644 icfp-2016/benchmark/gregor/pre/ymd.rkt rename icfp-2016/benchmark/modulegraph/{data => base}/acquire.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/echo.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/forth.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/fsm.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/fsmoo.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/fsmv2.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/gregor.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/htdp.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/kcfa.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/lnm.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/mbta.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/morsecode.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/quad.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/quadU.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/sieve.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/snake.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/suffixtree.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/synth.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/tetris.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/zombie.tex (100%) rename icfp-2016/benchmark/modulegraph/{data => base}/zordoz.tex (100%) diff --git a/icfp-2016/benchmark/README.md b/icfp-2016/benchmark/README.md index f2c9aab..ec4673f 100644 --- a/icfp-2016/benchmark/README.md +++ b/icfp-2016/benchmark/README.md @@ -5,9 +5,11 @@ Format --- - Benchmark gets dedicated folder -- 2 folders inside benchmark folder +- 2 required folders inside benchmark folder - `pre` : code without `trivial` - `post` : code after adding `trivial` +- 1 optional folder + - `base` : contains shared data files Test Cases diff --git a/icfp-2016/benchmark/gregor/base/cldr/core.rkt b/icfp-2016/benchmark/gregor/base/cldr/core.rkt new file mode 100644 index 0000000..33841a3 --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/cldr/core.rkt @@ -0,0 +1,104 @@ +#lang racket/base + +(require racket/contract/base + racket/runtime-path + racket/set + json + "file.rkt") + +(define cldr-main/c (-> string? jsexpr?)) +(define cldr-supplemental/c (-> jsexpr?)) +(define cldr-key/c (or/c symbol? string? integer? + (listof (or/c symbol? string? integer?)))) + +(provide/contract + [cldr-json (-> path? string? path? cldr-key/c jsexpr?)] + [cldr-ref (->* [jsexpr? cldr-key/c] [any/c] any/c)] + [available-locales (-> (listof string?))] + [modern-locales (-> (listof string?))] + [all-locales (-> (listof string?))] + [modern-locale? (-> string? boolean?)] + [locale? (-> string? boolean?)] + [raise-locale-not-found (-> string? string? any/c)] + [cldr-ref* (->i ([json jsexpr?] + #:fail [failure-result any/c]) + #:rest [keys (listof cldr-key/c)] + [result any/c])]) + +(provide (struct-out exn:cldr) + (struct-out exn:cldr:locale-not-found) + cldr-main/c + cldr-supplemental/c) + +(struct exn:cldr exn:fail () #:transparent) +(struct exn:cldr:locale-not-found exn:cldr (locale pkg) #:transparent) + +(define (raise-locale-not-found loc pkg) + (raise (exn:cldr:locale-not-found + (format "locale \"~a\" is not in package: ~a" loc pkg) + (current-continuation-marks) + loc + pkg))) + +(define (available-locales) + (cldr-json ZIP-PATH PKG "availableLocales.json" 'availableLocales)) + +(define (modern-locales) + (cldr-ref (available-locales) 'modern)) + +(define (all-locales) + (cldr-ref (available-locales) 'full)) + +(define (modern-locale? loc) + (set-member? (modern-locales) loc)) + +(define (locale? loc) + (set-member? (all-locales) loc)) + +(define-syntax-rule (get filename prefix) + (λ () + (cldr-json ZIP-PATH + PKG + (build-path "supplemental" filename) + (cons 'supplemental prefix)))) + +(define-syntax-rule (defsection name filename path) + (begin + (define name (get filename path)) + (provide/contract [name cldr-supplemental/c]))) + +(defsection aliases "aliases.json" '(metadata alias)) +(defsection calendar-data "calendarData.json" '(calendarData)) +(defsection calendar-preference-data "calendarPreferenceData.json" '(calendarPreferenceData)) +(defsection character-fallbacks "characterFallbacks.json" '(characters character-fallback)) +(defsection code-mappings "codeMappings.json" '(codeMappings)) +(defsection currency-data "currencyData.json" '(currencyData)) +(defsection gender "gender.json" '(gender)) +(defsection language-data "languageData.json" '(languageData)) +(defsection language-matching "languageMatching.json" '(languageMatching)) +(defsection likely-subtags "likelySubtags.json" '(likelySubtags)) +(defsection measurement-data "measurementData.json" '(measurementData)) +(defsection meta-zones "metaZones.json" '(metaZones)) +(defsection numbering-systems "numberingSystems.json" '(numberingSystems)) +(defsection ordinals "ordinals.json" '(plurals-type-ordinal)) +(defsection parent-locales "parentLocales.json" '(parentLocales parentLocale)) +(defsection plurals "plurals.json" '(plurals-type-cardinal)) +(defsection postal-code-data "postalCodeData.json" '(postalCodeData)) +(defsection primary-zones "primaryZones.json" '(primaryZones)) +(defsection references "references.json" '(references)) +(defsection telephone-code-data "telephoneCodeData.json" '(telephoneCodeData)) +(defsection territory-containment "territoryContainment.json" '(territoryContainment)) +(defsection territory-info "territoryInfo.json" '(territoryInfo)) +(defsection time-data "timeData.json" '(timeData)) +(defsection week-data "weekData.json" '(weekData)) +(defsection windows-zones "windowsZones.json" '(windowsZones mapTimezones)) + + +(define (modern-locale-set) + (list->set (modern-locales))) + +(define (all-locale-set) + (list->set (all-locales))) + +(define PKG "cldr-core") +(define-runtime-path ZIP-PATH "data/cldr-core.zip") diff --git a/icfp-2016/benchmark/gregor/base/cldr/data/cldr-core.zip b/icfp-2016/benchmark/gregor/base/cldr/data/cldr-core.zip new file mode 100644 index 0000000000000000000000000000000000000000..4c9b39c44f73f386f45132e8496bf50346968f00 GIT binary patch literal 103857 zcma&N19)XkuqYba*2K2$?AXr4wr$&(iS3DP&BPPi$;7t(_Wbv~d(VIGJLlZ>eY;n6 zS9h)5Rn>)Fy_96ZA>cs%UOdPy68`}IZvh8F0AgZm>dau`;B3aEt_BMNu5SjXzGn%i z?&b*(0t#^t3IYOw0qm^=q=5kf1_JXBjc{%v4O}1!4h#eY^ItR=jU7D9oEfcM9PIxm zxz+!ZTwEfHVm~uV*yBeuHJNn^JB|ENIDkvb5CEfh*3Z(gJ0hqls{VYwEUg2eY}pg& z^?BTIN+P#H#+%biW*t0_#*H~<{SDoukSWM(mV^0~WfaeJUccYtDFj>!vig@~zi`2r zpk5?B)!eg@Qh7a<(({BVne_|aP(&JEHWw*MqbG`3 zeJaMiaU8*E;f}nj=04U*_-(`UvZxz8ez+avX~W7oX3`=1cfMT){7SH)0K=UhlQHO8 zK_=IaM8qZ~i2~(mr)SSJZA~M_$yLLH$IyTI3G7g91H{P&0PZ$4XC zxmsD+1I6|ao1ubX)&GCk%=C{m3``vC93AY<>|I@$;F#pZO!ByOpJg-|CfmWlV_i2$U5vu;fO!J(-l^g z728{xvox|L;DAvgaqh8XhQV^8)aA4|Sz6u)5Tz)5^T{p{pQ=QULhLAW^t*4VwDN1YXVM(YZ6OXq;gpJUv*T@q4_3b z=@PWo6@#-vo=b~z3brW9QeII`M>O7f;X4jjkhKX%p!^gNH^`#(0Obq` ztJ-<6Ct{V(0B^mRsmQ&oVF;q_m62W@MQ%3Q*J;?>Rok8o;s)JLaZ{nS?;~dx`29B8 zRq9zAo95JdBs%=yxvZBox9(345pEaE&Jo|woJTs&4jHLJ`g@$0HIYuw+6H8(^G0%A zxlaie+lRj{@sTtn3$&CE2YY8vG2V9A=8u88t<*EZJFkQa&g^F2al;Xol@DusRefKg zXvh<&VNE!{|5`Hz^+KSOCw71w70Yj!1D#zDKGkNSpXG+%z$zwz_#}DHm1q>TWwdTbr9V+%TwkI>>db0B_*A5 z0!OvK7{#{L$Fc@1`G=ul zoe=)SNmwuSv;o#nu73+Oj15wUz z-8}OOd3h+aij}1)Z%!-*ht3rhj#A60+`GN%s{Zzqc577wi`mTf?9+pWrJS+~c}epl z-|7xD2a;zjmHWZ>#`qG^`n@>xh3|d!u2$KVHQDln=yKJMtnxxL_3UK0KR9#g&&k!| z5DgoY?5g1Nd*)g^k*aQuY8AgF{M5@|T^6TgJ5s1{Y*n+XVl(uEX<`aQB66<@szJVs z?CIicP-}L=i~gaegr9_2>JE9fJYYjyh-FS(NtY&`KE^&)l6R9(5jO{_PitO5hknBX z8uLmsVbvpN^5=K4pIkYVk5naukCa%Q&%#g#MDB9!!Q?(~KWO$DN5J^sEb7k%JO$B{r94GPb1^@^n%+*s$Cvf+fc`RpV(&jPN#P|aT8Z?ya%^J?6j%0amJbg6Xqt#oo( zX^n-iUeO*hrr#xq-|NQ@uc+4%)GCCQy)%p=q@M|)c(G=fxid`Yf%IY5EqV1SNwV&U zL;cbpX}+$I!XbcD1Kocwk5`kF`#`qhuV@M?Kg36%ea|D)2WmLh(W}AdQ7G{Xza#N9+>$ZzA@B3-PFkC~_GBJ$O%RJQZ?!l#!#~fj z%EEEb=%;t~TpjpPFV(YjntRFF zscGsv1YA~Bq7`|wUEQ$Kr-SN$*o6mOVBSBR^(0Da2Dv_!sb#ik;QKN>FQn*~ackI9 z&T%=(YJT{8J??Mh{o4^8uzbS_2YS7R|HJeBZvn=C;(Y|-Sm1yC4KUuK6P2y$8H2M7 zTRYmK`#A)Dk5bS`uZq82QX+P2_z+!owkE3Z)Rj-F;1c$4J_T0L+((lndxQ}vb}ZOc zGbkMsK2O4G5QhiVKSJRY`4942(Z-JPvuV4+KGjuHryL#>jDFV)NXexZkqHW?FnXi8 z*x2_zZTiw$@D$1P?>RxQkLSujf`GWdgMgs^%el%)i-{|!ivL%xJWgZ6ewP!a=avSl zXCAc6y;T@_Ba3u~Mft1qedCXWCV&ov=}i7!+cEw<$BSuB0r_xeoClW_O4Q!CZ}#&6 z{(jQcZs3$K;DbPP`<8nDj{rq>t=G4o&@f%&Atf+gaQYa+cub8JOxv-bAA50(azBU@ zb3#jM)Zsg5PS_YnJHnGwAMKylzx@`~q@iwB7q_U=V5sc4xU;Hn(`CGMxwN)FGpgsg zwAQ0HceL25NU7J0fi_j$bWxcv(L)Iyd=tnn2^wy+MW3M zW2+mODze4$*CtOk+Qn3QSeR5FmV;NsHqmk}(JT=7YCB8>KsNKM?RD(%rbl$l7A`Q6 zG&pgLp?r#Ac}fNOh#Mx`7xEt9Ftp zLc0%<0TT?)Az=R`9IS05?Ki<_@gJvGP#%7l@ z1ygHHj%j4o4h7{i;fRFOYNLfGHl;H!aH(}j-@Iha;IS*xZ6g>SC?4&V+H`%D6+6c4 z^mJD@*7MN;;Z9|upL`{mbQJ~alGk1qli=@m$xn?io*?KX8kr^GD3RO4k#nE?SfEeLhgp(^lFGYE`n5+bRsV_3s!!aO4F}R37mOm;C`1= zZj|N-3MeHzjt1m`bkUsAB7x_kynWDonI_XhW#Ix1pNX6!!`L(#@zI^ZdYeW+#YJ#9 z4uAaxKSPfK`^cs}?3KKu_3KYtKbXV0!1bLqOIQEx@3C1N7Rtc(@%~tqR=FLHP^S}0 z)cCls1})r1TBPGB9bWoQc;&8=$N_$Mx~_Od=CD1J#5;-wo;yiXwY%6hfzPqG-|nHf zVbQlsSuk;{O%74~09}t#5RPAqw!=EP6Pdwnro7zHzilv|eD216s+X%uhBC>C84LL% z7?IsGu)7f0@6AlWdd>a%{^Pi^s#*!Hd@FH|JY_P7-r(E0tL$pDyiqwH6J8m%bT)_N z9L-_tcMb{R%2OH%<9Kru_?E5jcPR^PzV#iab!B_Fn$;g`ZuIzoN1JKS*U$fu%KpuG zR03Nr(158d4lw7!`j=65G%~R)5JpH=OqdSS<77E; zXdM#zf>cW>HAJ$j-n8WNMH*Hq@Jm9kJv%DEwl(~q2u4Nci%LPn4$b%8pU@$UG*e8@ zOph*Ki^6*B*$Sdw#MCL2BrGuWMG74(Ouk4LDYi61Ic1nR0kEf2qTJnAR=IbE`89&gnR{8vQem zCoY08gyfDa#3eR(NHD_C*Q%TI;J4q}K9m`+)V+^Fh7?p8e<2&3ZXonpO-QQh_ru4r zem&0vW`wm6O}N*YERB?T)6P#Fj(SA=CnP!P(WMG!=0s(KKIO6vC^OnY8+_OD!o7&e7or?${F=Ip$m+>RXr0y@TLZ@7fG-z+l@8ufUyv_EeY9k$9A zmK!p2w%*^)nHWm5%y|7TTU&+N=pTC@`ak`XQ-xlvST``{t_!479D1J*@&aCat9D%E zGW~_W5<%IuPg)Q$OThQxSj9@t#!JRsH@#+GtNG3+s`D}~_9A>h7mLGbH%@Ce5(L3M z+(O4Hb84HPeoeAJSa~8-q6xOFtv<+K($KEOG&O}wVnM@g>W{_+**7-P$YVQrC6jA3 z*3qlUldwXHb#2mkH;2u1b39jB5=d!(pl2-&WLd!Rnbq`3QjSEhW~)`Vfl;beXWBS$ z*!u9fFUEdzY9xHfQ7G0;iF5ke2 zvFU@Uv~Yu2$w*~(;>!PoW1iJ$R)#7bvSehHVWq`05de*C9w9!TPW`P6%D*p_Vph~( zty4@P#Q(XyCUp5M$!AQ(RxQ9+XIc}VKQ6HqbZBr9U&o!$6G9p1{zHLxq<>1<#Et`B zF=#uMqaSxFXoz4+9Ey4JTFulnk4^vZ#guSL1kJDu9sd>qC-aJkDd>>tQ8JQsxKft@ z4^A8W)S%09LjtR@zQr(p)R=P-tMPgaU^*>A@^ecI{$q$-;bmG`bT=3uzWyfUC(xrOnr%n5}5m?ypNUF81hPL^Vk;Yx>*`gub3K5Y{#Zb z1DmAoM>(^wj1h!IWDN@&qc~Ah`v4X{MnJ&KTQG2iW2e|z1jj~o^@&7oCL(vU2}K^J z;Ob__+3k4NCIC?9&0n-KEix&y&ZFex<5Bb{=PK49%GhR!`0yeeKHuVpw$mWoCV71; z>(@V_$G&R`V@@_p8RlL{*{}~qX3x@Y`pALHJI|(*?d2Y*8cN-&`y-%n*K;iWD(9Jj zaAELcozgHx^A!?JNP04<86>*J)RH^Y{=>r*NS$uOGU+S%BBSGa@cP43?$Sj0pZ0 z`WEcv;+zb#iQ>4XHNkZ{H}HYC9O7p8oD3DP^CZW2n;aLEH5Ol|nl3M8($q{f7RWWx z#KEqUh_rSbOssPTK(Ry^1(;^ak#$gJm6s-in`M<4i%}ZOf|wLtEP+V0W5^RSx0v!b z5i|RsiXpJp=c*7}aZ5Czxp)U=>|a4?&Ikz3T>lm(h6EXt+dADK}iL@{6cr3VmMfo>?RBn z#|MomSw~FgL~8~QzMj$XQkyknCPFq^V;&!!>-?1Q5bkDdx}}WCIe`T+F|g|#2>3{_ zP;K!`B_C^?r(8=O$uOg3?F-en9_l5(6pBS6)NRS6Sn1WW<~5Xd?PJBpHQj6WbZ+;< zbmDwtOIy${y+38DNZEH_WLXh+YOY z*|%svD>@-f(R;Ks-!s#xb*j^NVGz)wOf^<-dTCi_et=4RZ5}m!-RJCNU-?}j^rx!7 z6^+iFht8csgZ9OSS)mg#eerk>72$g}pRUztS+=R-t(qx+3>6%R2}HJh&5s~oFn7A! zs1f2arlu0MykOjHo6Z`Z_K92@6*el1Mwf|OvH>Z_ug@LU9;-e3Q3MU7L|Q+Ij{r_O zXIwD&)z}7e6~1`^(lHXoE+f8l<7}K6mY4w8R*Wi`Sy%uUT z@lh>jc8|F0K*%9-E!N2Tvdx<{s9fwze;o|BO}}L9(I0+YfS&r*{ zDx9ut?cKf}c%7a~YNA+!O<+XS_Qr!g))%;laTImYZ*j?YG>g6wVX(7w4R`xcJrHfY zSp(FB%B_Pce;s4g1^3X9ATt(J5z`wx04yBNKKu{3QWhyo)o7z(_^;Ob0I092dE!I5 zw$RyqI?nnImFIT0()Zu&fNP28n{DFc^zu)<_Lv%E)_0qrGQT+PSTpju>lTgrSYt;3d-kcsM8TpS# zcX;MC_f?p4jq=Q&sL|=?kpo*+EsZ|a+K9ql?=0X*TX1ZDnpg2j7hlIO5GfWT69;<6 z#G$fbrmQsXg)iRDJ73v-KA)yMHrRe}K2}9d93lW%r!uR&D6__=GLJk-e);-_Mw>9n zGE*~Yli!N+o{68U39^PY0)YA|Gq#5neE$C`W z5w4G2VRvbPfb~s3gli_N55p(r;dWIrS$;`rYd=Ztwx}>`qI$W?OCcz@+HwcUo#{ zglqnsS9d7%rqeQ4IMQ-z{2382IXXIc7%&l`ymq(|;Oq>JlRLx>3}9+TxL>oC@uOqu zrsK6tvXgo$q7YbXc}YXY=`>BU^T5Kn4-O6Wzb1_k-&T~dFphM|0HD$}TP%sN4fR*# zvh(!)QosW`nf^Aob0_7I(s`Y{+>>uGo~!0(MM%N z)qCT>#ga8mqH2RL`)Ja0CXwiYnl8!6ePi9@zAiS1QV@!XjbPyf~F8GH z>;NbnwRA6*cs6Ti^ zw^(P4Ol#jg>rQuWG+3*i+$po8>8-KfuL=uT%|oME!P2|E-#?5MA!Y5ma|e8N5-SZm zvX3Np2ef*Ly~w0Il(iD;OsnAzY}^5$oVZq~2*{TNYW|pTECSj#)5u%PSfGq6e zn2?%O^4`P-KG*t766i}sO?8@uMSks$PZB7?%tDLli7>4hwfwhE z_E)!Uq7V#;k}N~Wv5DLOLp<$@G^~AH(F5%#d!c@X513x<(rSo6khB8I`IjK7rcOgtA~|UYzXZc7vGPJxdEH1< z5#X+~Rd|r12WU@!qv8T1>y$7q^4(1raj5i80a??)xyzmdS^LO}kMmQj`;6`* z`L5UKv@47G5d*Q!WmHL|?tr44!Cn%c^G-3vj>5f85=n2}`u<4a9^e{4v2FED5+M)g z4vK=fv=W&?E)iZiOyjZ2EZD)zjsd6@!*1z*+JLaj}Xisi{Pt6v;?xWx!&LQevCv^nmxTt0s zX~(D|Xapp61yLMIE2vX1Nu*^PD08q9dwSMD>{Cio@TWR&MN<&`vrV9>57Cx+Pqj^R ze?uc= zre45yBVEBcis8LZ1@=Xk=3oBX@CVqCWb1e*p5rO|cZex^3DXI{nZvi7rAo}#ffw3v z1$l@mN*i&>v)O#?9H(~OrkQ?sIFMnA^@F;7e`SbHN9SkShD%Fu=Jl^>jYQuW23NWY z{H^;|(k0JhbGnZG0v>dy3R+)+>!!=8v21?`=b}SvuXzp3;t$X*f)< z_K2rLvQ2Bvsn@Fo?i+0S2dg#ELpA~{_sdUo=^&c3iCbI!pEvLt`sz z@~j7$4y`)!yUl%eQ(XROQxBxO9Km)DmR$<1=Z_#jZFe7L(>K|Sr{8s(JBNXQYhhpo z19m?@Z)X1|s95WFtmM4xAnO_`g++qTbeLM(QJ2QSC2dU#H}O_z4VoE3hp=~*JA9{v2e ztM4vmLr!9GJ<#o(iRlPsmz#ApG@+kbz>a2KkQ*biKpd|O$!hU+L+@T%@cQlGG~czc z5r=c5;1*mvZy}8`N2#~jG&50SYgLL5!4oZ>2;3rImv3ga;4NNg55*)b`i^;y-e^yA z>U(!fXz13{d)pD4GbRNgj0Re!>U($(opvs51YN({xsiSuh~B?%vwE8d^(Mdz=r1Is z8ltORN-4djy^qr{?8@{E;nuIG_3pR9uO;3(O0FLH9l;kiV8J2vp;D#28QE8m7=G{v z-!wqW7rS)^yAuvks@K6+Sa*z5zh%9dY!^Fy!+Y4%$~BEXd}qU~)e4ts;Jn3lH>^!> z=g*+=Pz^R76XW>{Fyye>2sxU@0ArLVMp z9`ugYO2X>p+8p9$RDNPIOM1)`_1T<>S-+{v ziz%0hRJ2|lK2{UM;W_9UT2b5dCVF8>=L?ERYZFYdI2KC1wO35`EDBv$Yhleb++}t8 zojN@$=`QA`&fY+s*7p14O`N7dZzXc9P_FAzRIH{%FFg3J`raj4eJP65g`JIMmzrM| z!6D|@Nb5$y_3Y6(*AyWR6WJwC>U9IIex-evTK5v=`82606QzqLx{y9t3#@>Ax~D+mkB26y z-?@ zKQx3&4;IP`D$sA>+)HZ=Ee#~(1tO%@n$`I_f35&)pTfRTSW?g6v++P9cWa&hTp4IO z3MT&s5pU6D>#LLynnDBEENIWiIud^_PszQ->$l-JPJXh`$>3fZ%UJ?i9faNrJTA!#qZ#a1q zTr-6rIhUZA9WZuOhp2Dz!2ykNh#&>`d}RhYRVI@8Ut!EpRzXVesQsJRds)9grC!1_ zCy^ow)2I-SwGGYPnwyJHUxz9UT|@djF=Op<@M?o+&fViQe;!FBUDM)haC7QI7G;tD z?crmLieMVroqMfJ(S3fV|!OX00UBpL#$JC6PM7NYg=~Yy! zRhNw;HBW*#(}0XB{VI`(DzT?tD#ez#e3BHXXTp7<`3*E?l*h9E#ak}^_h6=Dq#iMW zF);Q&KDCComm>^_ZocB|xs6-$NEp3cuLtJI<>)@Z9hu|$meOI#ZOUeFI#A}9-8f=K#&BQ?Ntc7 z9y)I)&3>JcsELFok3;FvXF!q3EVpW?NNN=W^ixrk05oI>@F+?_bRqVsqriKznNXub z&XAE9auSJhnu<`V^iRf%Xz#i3pesJ1qJTj8)x~=jB^hlnzyOPaeqt7$F{r%aWnq-7unjHbNainvvU$S#&i}q20j=F;)Y^|&40H*(ZEpA%$+y{c433Lh5JD_ zMLbSdT*Dv2T$|W&gYc_M^yGgcimCr15)1z#M5F&f(EKyvKOkTYPg4vbIg)2EqQG!Q z?mB#8pG?TTlb^(3#A%8(B~M6LuyQK>OA;A}XzVW&jUzy#eBj!>vUZY9;G}7PxTzdB z=j*-wk#JV`3ftR9JqkO7BrGN=9ZpoZmo#FIIBJ2`XYT445QJkvMq|wrA#CD#n}LH_^i-`&%ID#jieih zz)w)D*ktwLRvIN46zSZ~#k;op#{hmo4rz%{1(WOR!b!2zl6nuE8ws&_IDd*w#(g*M z8kVj=8)wru21=w`N=^RXlm@~CD+Gl^`?_|{j5(n*hX?u7c^Zmt`9)X(ui_+I2WiIkZYdjf> zK-%}^=J^4AK+iHgyb*(3i6(qT``66Pt8N=(li(@%_5($QKM_Em7SfG^|D%oVs9<9x z!t1ufY4?dz-LLuQhhz)yR$$V`lf}*cp(5wp4O7%H{~e`(p7uoNB7&RX z!~EoJ`od-s4 zeQ3v;xAB7vlDvoWkS-l+nYz<9>Hd98Cpy*R@izp9#SkPA3fkXw3V&7{Sc{%Xh$uT)*C}h{PWzLBDW{c{#O=58$ zk5eNSWOQL$cOlKql^B16P%b@IS!d_k+P$xU!^7D9@yd=#z+#?%dTZyx#KE>mz}@hM zxto&<&*#IHLD{~ZC$_?tU{`&6r(j;|hmeDRhEUa8b7Pp)w+>Gi-pvl7F5egb&GEJU zk7r3;#>ZQ&57p1%715AAnxkT`f@}KkjkYl~S}-w0{&`GWj4!u&hqu?O2~$Gb#_hRW zX=8S2O}=lqhaPEZnw1+LGmVlCpD$DPLI$01omuzJuXU{-GD{whrpf_WxdK-LXAfi5 zvO+n|vounlE-y#lUsDc0I|7*h3@%u+U7DA!cKGZBC@C_mCcSK|Uua^>b!WXVyop!1 z@$~51WQyiA2`ZnS?=A#$K3Mtr9Jes0Wj$6pnBCzdKn!;EYHzIj`!z0U;&u~S+$d&c zrY_z3=f0TNz?YHA^XE~tF= z<@@uDyY&Z zqy?9Tvw`H)Nrv-qNmA6CzSMAbKl3$`XcVZ~q$$A)Jv?BNi~+x{N=adH=2qDPNH?nh z!DN|jji{(A8&Txc;BHfnmOMY3upUE&5n;-GN+Ro2sDHY;D)z~vNDUv=gwmn_hPP#? zgM@hxer!8eL(JAAagzXOf4bTV^ycs7L(J0nZk`FI2&3c_mT{AV@-~{*wgp?elP4++ zas;Bm6sC~joeC4@Or+5NQYBBnaF1-$6%Rf>>+H)VPH*W`F(psuG=gM8lhP^NBu{4~ z8x}P{kxM(_&0h|$p-!a=GRlA{wz+2@CL;$s#_G`Q#Y}N-$~6;x9Se%|y4~$gBSFmW<|C%aQl`hxQV4@W%xu1+V8Rp@)gxrU7OLhu z5=SbKH6=ktU!=Q z&~>(LqIVr=70&dD9yHt!yhymAc=YeWt8a$kv!WD{oU2c2V8^+ca5XL8g*)O)!FhuX zI}mpuP6AnShPg2>3sGPR(@`-qqgis)wUTS&q{{ z?5~oTS;bUI3me+3apv1&p-@f|BSS}KZTs^lzswhh*+R_QA@~~(+Tbiu=Kk28FELWf znr*YhSx6oF36pb4Ojz|;Uw7MQa(r@Vldk)%E+Lh+Kma=7wIbKtbcAW9mivrd(kufLmhRj0lMS2aklSe0)k+A>cy*WB z9|1wEeLUu05TBjM<)S=nqKX& z?^pmkZ#=%(`uoDosG?^dwBQF5aM3h?*x&l8K zCL&{!)+<;BqS-(eFw)Zf_YOq*qR{Wi$By)%P5egtVywyK0k}c3+`?{kPsJ}*` zZ}HziB14mqLz+Z|$wPgqqnH^&6Og;J+z5hvrJkOIFDXz21!Gyrl|UM=cep}>;9+oy zBsfI#6qMGH*!&XVVX%o-w{Hk$gZ{K(xpoL1X%Wns^X&D>m(;Bqx;n@tHPQ`GT%uM3G!zsym$L(OhlQg ztFzdt2r4je`XU(`rtdj5@nQ$P0z_U)%478G)HKv3jim^fBo?d>UP6fApbqJcuZZtS z1e?V8k3$tmExWUP7BZGsgxX-U)mk!ra0KdndS%o;y}~Q@;QP%hLfJYn>fhsI&UV#w z9cU8y+P|ZHR}_5r3vdp&`QMH-zvwoUv;a@fiNk_`u>SY4l9IETxtX(>y@}cXRn%0i zA?pwjhZw;QmK*CTfkYp75$F6bZLl-f*bnI+cAPa_(^W zczqb;W8%+{W+ejF9w4$%%zp;twT}kE1iCM_sLKQQRgkcq!_a6kz8^-b&=wIen#2-f zrJm#J-e@eaz_Mi%S!9NMHB!qoDJF`L@JruvP+Z24(9BPzM2ep49>0IICaG(&3UJp48?0- z>ik^pZ|k!PItHBfoZN2~rolF8&*1-#riE-g9iAb89}v=mfH3|S8e(bWY-HkU<}6`k zYikTVdHLUeU{V6u`l;!_3?lxBO5~%?8SeI9)@J(#M z3-->q{d|t6Jt+$AURG{98Ow?cu0d3@&#KLzqrcnpahob~`o-oea}4u*W{6ZpHJfd< zn`gE4kA~FlOfpHUGb?C^rXcRWMaK6o+Fj&vI(de!b}nc%FGf+mp1|}M9eY&R*o-Z# zp3vn<dYy*}wHvdS-WXet54Mx{dFLZaE6tWfHrC{Y0zcO+yWN>8;T8Y6fo@mLoeJ3l z=3H6p1NH3J(zI`$_CH+h?0ONp#Qor`xPF#kKmFp_^zCB8V`n*#Rj68WChUI5P@!0q z)T!isamTP?NLoajOlv*p&R4vW{m~_J8Ne^_JW^=A! zbh!%69Pw6%e~=BhM0utzia}Xsxudp5a@&#F4~pk9=B$ZkyQB4TMDgo&u1L=!yzo&A z`dQK|rX`jAU|F&vQ+yqj+ef%*D&qgVe*V%RN@bx~L}I!2dKPa>H3buFw;IuaMJ`h+)S6qU0e><6V1I?2A%^a{uHF7l1o#H z=5kO+#St zA{okz_W?lZqj38`c%m*93_&t~k;Z^ykT3R$f?A@%qeDBAnPCr&g7Qbn27*3m z8uAeIrD=tD)>h67bs}>ISoyYucqX?>_saSLqf^+x{*{HBTF((XOBYw{g@5AlMCG;jX{dr$r%KzwuOgKN)aT}V`L>iu#A zyX_O)E9+G#$)hbGwrlJieNW)xQ#5z!b8&0r_GQZ(u8U0h6Fcefo=6|q8UWm$*8kkb z-1B;m&;jC+#r{HVNA*q`-PtIDhTu71=-afAA20@nwCTX!p0cH)!`R zU%aAT+Jm|P@4oSWi@(r1K%X?gfrKfkw>2qkWQ%V^cJDInZ=pGI`%d?U=c!2gIdj`c zmGpV^ypl5Vd6}3t^4SUO@F}oIaq}s7gZBI>04#drx&R-SAO^*cy`Shii=S`M7h}Ch z@d*BpL*6Ezp#L_oc3~FGarhu0xHV1E303JSmed{0Y^?T}g!oJwP5ZdZ_{g@LH3}_G1`F!6!R1A0?=5iQI zlO)RhaJ?#yhvD&PAjI$I=Sknw;nmen^Woz6dXNBlLA3SJ zHyT`q_`hDv8L+OV_1~tg>`4-RKAeC0cTFkEyq&-Q z?Cl+ItqOoVv3NIOxO3n>$?C)p_qO%F-U|@)dwoBjxQ`0#cO+1pLPn5e1}iUOUB`zz zS%%BkwmbNC^uvrTt=xtueppgQPluHtCeUPBO7xIL4UD=hkat~0f(LYdMC8jwyDkN* z3;z=XQms=WoY*O(5*6e;!x#I)SYCMU;Nablcoog$jdH}tq@d_{#7FW!QgHFmGRYZE zb=i;vjS^_Q2|TO>%6;|L$(~b=YIOZ1UpL}*+kF1;QU`Tdk{9rLve>rO_6{o3d>kA^ z)weW!`Kf#l7BACCA-7sdoL(Yxs|?M%p88xaGhP1Mk~^JT!yHAJM)2ghZ(POAw8a!F z*1v?ib`4)4xlf9e+G4>9DiGFfL75=9NmC;WdT>T7T&%8hp|UWW-MoB!#1V!>p@e%| zlJOjzZA4lHe1dPzu+W(;OOou5()z;$yn2YRRWmF%d+WQD*9COA*zC^~^E>2khryra zz_tNtQt8fv7NT-;_wkLNvu{`tzzR(~IqZEE4HYB@H0XRGYErOvXnCzRhmzWYhPgf+ ziG2j_He2uhiJW{MinB&$QCVf7bsICmhJ(|5bWv{!sxt$_&WSeY{m6WNjSuU(b|kL# z;LMgF8@#5^!I90+nWboto)ROwxG<`pB$1ZYUWa8CyvQw0RgeO;n3rz=@YD_yC*v*{ zZj4J`Me(K<_@72$Qc%wMSJ^vPYBd_55j!~!KRjyq4xEJ3wsssdE0o)vgX^m#?b@=N z$6=R}&8{*doz>BO?F44NsR~H1qO!-Up2N@|R6>^N(d9lohgBCEPq1InJL$S4FsW6T zlQdOgK6=Wkg5Q%Lr*y1$mlP$>o6pG!epwjmGGu}cIk2+o`vsHzQo1!4)2MTb&qYqg|0HPX|#R*P>QP;GhqAZs{F||4oIg@idNI zckp0yhPm2_9>X@2x%wIp=^zhpO2fU7+OmK+Z#c}HD6DPxtl-a-|I%s~PJkQ(Ib1B| zD0{y-=@Na_3 zA5O2vF%EGcWdr8N=LJ%dO;G4Jl~eRG?FD3D6N)mi1B~)HNo?j*Gi{82O{ZeIq>17z z((;@h@9&Bmv;v)TA zYm$@?Pv>r7(=n69Z>v5)E1$96MjPRWK(xa&aFSf2wWB%`t^CT?p=()9P7y*$@vTEd ztE*WXMtmu#y2zShLig*`rYiEHc1x~Zn3*CU4YwuC0#Y!W?f3QTFRfs^QDJP!x{z@p z-_Arv)LWDr-^PcAQYpR{nfj&-iSVwIb62=8;)ws?YxL~EY^l*PLwp;7v^NzMfc+`$ zvnVCX&`%FhoP(ykK4%wHgKcYER(>mh2+m7o3+a}*I18|nRD^O9EuXRaL7Z879Bc@} zD-W<5*q}&NPnPp68)e);JvS#IZoX$qGtqE)b9I^GM6(?1-I_y0!`Et=gAu7);75_y zUmhW)pxe8untS7miLXwPDja2(>(~A1zzU#@O_ZAbB$ClLz z^^KWD1)G8FlAaouH=4`PFseCb^#w|1+D z`4N|H`@D#39x6k5S@V5zG&LWoks3HQ95Y@Xlp)GA1|P$9(lAeTgv#ILH*?Ln*W78t z%0n@`G=^NGh87On`UmtkS-b$=1}^x&)+Me?VPFy86OYhKM20_$rJxt%sp@qd7^X=q z0Yj)|&nW~!V`m!hkf~3pWX#?~_LnX2@!q}rLZ0;1|K6j`u`mVRloeYFmLvxS;Y*M% z;icV<_T$#83XGquk!HdXTio_C0p%6Vu=d`Hv_qhBKnQ79Ebu|32phGWdcWZKvLxu{ zr57o^M7{IZYlR|E!pm>7rQVUWYONAp3WnhjT?&{Q9xG&Njr#E^I+$P5RB2{L2b@4;vnmq${}Glk~WYU{6Ri?+_G?&?J^-G*>c%R2UpeSbROqS52Xxq@&pH6 zt5aWdo6Ah^UCan{J`(UB%vPU6=wZK#l}@#3^HFgVjcW6h)r1n$X^J%5`e4LfSCnwueUEWuklBLU zQcW5zZC2D+aZ(ZEXK@sxjSTLDtJc}%-K{7e4BqADODDZ?7&=O^dA%Hy@ zAZUp?@Pzo3mZ0sNW{uZ!jjZD2+vG*`-*Bqge}ZF#$GNOt^(r}47va_E&QPLQ=xCXj&#jjkbvRgT!-!AflWYp=wW2*%W2V6_gUTRTc!9exx>%bU(lG*!bzNDUXZf zqwAY_Yp^M)ud4om%t&bo_0C~llj7y^<@^Bc#;maTi_5&Al2soR1efLfuWe~)@jXMu zrPoCB)8KSLs)aAfws#Z5v9V$Y?GP;-`o(*}dorShqERFILROip1l;KhaH~XoHiO$K zOM()HLD8!wA_m#RgMLc`Xm)n%tPtF>j2f?^de*4erxggk)b;v$S%BeEZY zgmk=Y%#b}&>x&EwZbU10KI;pt%BVP<--*iO`N48RN~t5H6= zNoj`&5p&dewEohSD3KC+ODKX|%E)jtyOg@i%Fg%!X`-s#y!@652}}JAoMhhb$gDK& zqQ)+%!Te!mh4?LhNo&XX!zgBJGXh|(P(qs22eLg<-zi$E>)S|sYI3hIa%icvV&Aji z8J^__8G@i+q;&qH0=<7Mzho0Ci#sGb?Ir1WIugJ@bDN*l&baBNAlH(Q7f*%RdYJu_ zL-<0AUs*eOCHZ8Y$%q=#So6f=(MkfvW~t^+x!^-hKa&>P8e5tA@*?-Ar?}GouZyj+J?mhXkkjd{fnt!nC}BQ%Z#_&d^4*d{MGWB+RWg z{a5(;L_|ioq>H$143bQ%bAl6^GuT#?EjSHAmPVAV9kiKT^`+Cq()sUNEoEFXU$u+l zf75Mv6E2<5EzrP4KmE0|_DxG8qd*t(L9e>ap2_ZYuZPOm7jvdnaH;OuW4{U!%9(k2Z$g4v=Lv|`@^ z5d}`GLuU(V9}5wc=xYNe(2fO>@D2-4 z-YTE)G;N*#Cw`;a(6m(p9yR&tN{zF;`|&^j=&7gNf`CU&eG<|nwB1M}*$&+e(@1Z^3Dczbx}6VqR7D* zoZ8SRVP1>9(*vnx!+x5^Hv9C1?B0_BWT-G3Co2;}td>Hr7xcjV{gfVqGyY8;2`}oK z9c?z=ifN_C{SJ6tDKPG_0RoucJBvwt zL3T9>^pnR&Y-=nB;>X~NN~rUqoOQ*@%-dk%*jR|`_|0xaOKmc@7&36|CMy;?uhz;z zIl59bwOUdh)_7fa#I#n*TXfYkB%sr5?&5Bv6pM0fR`qL-@9X5mRN+*_*?kHE(K@K!s}Y6;DG;~?9f6M0HUreaJB^nhqGRjPjw1RD@}-!**JlYfX4 z)&0%fux@5gKWp8xAH({m`&5Dn1o#KO+C)0^A1@`10APfpIEY#1mh)O%36?`_J{}cg zMZJ0^E?F$Pn}F)9=lONh3*B5;#T{;50$Hx>1V~uzLR{zgfwF5a_t6yJjPDDa`mU$3 zB4A#`b<5|CHj`St-Ywqi`kt(bTkY9*&Cj)$j}xZSfAkcukj1WJfH71z=ow!h|DKa@ zT|;KA70`U}#kB|hD-c!4nDs-Q7lS``Q=p>Yt?;1b9&SeTnT?sC6A&1hp-y8NB_$Q% zy_RsOAZD=q`Plh#f)IT7u0TRKia2mnXp&Lf8$Fg1sxtFy3r0>rhD-^gtvp>gII=lA zG1`{8>WNLKl|aX^ZJG*C zq{f$0#bJFn412^gf>Ro&3kjlTQeW)ZYYT4K*a-y{!PioS`@lA4NAvcQU`E(zR2>*@ z(jRSDSWQ1>vh8zFmpmuw(0xl%k>U#N!!kD}d9L@%6d zXtV`bliRQ&p0D%|1q3a1`cUmC%VvUBEd@QIXpQ=@E<^a6?4FoY|2Xl8D0VFfDQ^<9 z0Exq}VS>5hE4Sgq%)p^U^`PN~t*uvpR?g6ig$D-oGI6+xtiAR?LWN!9FHMUb3!a>O zu4u1Kpgl!Q8nJhjUm7wA^02ckEdjpWcmc>?W<)p%D_|4C5pxq@Gxx1pd!soR`H6T! zo$eUMBIezC7l4-9D2-(L3Xey%DY4w+3tR2AklyTg!3~aBID}A=sMH-qs-KyoaZ0T|MQ4 zUD<)Dt%0UlaDC8=h;XWq)dp3aBg-m)dp%h?{t!vl+U_|ju1D0?;_lnKt2t+QQi`<7 ztWqBc(`W`z>{ z*TorTP%yvzH@srGc8lf@|0)bQWzM@Q#=d%_jgARdi@vJpVOawi|2uU(uYdUQG!c+p zRYKD!5!Vqy1+_Zb!i%8-39GWwk=W6b-bLQCE7W%l2dXZs)uL!>HVe<_*qAP(B`Xr= zP-^7HrAtY^3s314F&d%>4!&drb7Zb$F2YKrJGgu~vdnYE5#KRx&R8|*jS?In!7G=~ z85A+GBsPv6wFX;?AB7i9TRz|dg%%Wu*PCWi`zvZ|9D(dP3n}{uCVO&OcK|%SLqyhF zX$F`GKQo$*=F4zDlt`?-l=!7{jPAwsBM#Pn3NIk%sCpV!Maim1P=4ZGpIJ7yLEp%LW?O-_--7!?bxJUS8hTbVQd2(O$7`Nt0D zjT$*B?JN_9UF*s3-l-lsK*!%qq}d2d`6guWg=mQ}HC+eV znSY69R7f__Az=?pj^YwbLtU5$=ucGn$B%%>q)y&aPkBrH8Ay0-6%@hH={xZcRy*eqDjiXU_I z^y~Zd;O^lSP=DU6|Muyn%BmT9+3|nr+Po`sW7SjfeQnVH{&rH?Nqtmogs z{i>^Pl2S&6=s)dMV8ZxA{k3dH2(nEmjs$+Q;GSo>q(4t*72Qq2l6)c0y`vWTN6*a#XbyzEdTj zAk|oN=jNprebV#-X!aHG+T@G=WSc&iOKhpS#>)shsdG?MzIu}4EH^jk;pvd`W1xROUB#QXI9LBHf%SAK z5GCUr7rX7pcOG84m0_dRN8S6~#7#fdWsiW)i@ze{&2B}b9juN>-~>oS&>tZ{ZYXxir9b5V=3Osb$W1; zo4ur}&DCR)%fI-s3Ke08?FetjPB~9xzN@Y1?4Nut2Rv}#vS^u*6or}c}Gw(#p z!w26yy(Ye}j}P}_&h<{h_1pNRjXV8Y;MxJtfBW$@{)yE9zr^N%r_u}U-9m%mib?@c zf3=_%dA8`bO>z7gaHW!b^Q^=fw;bQzG;8b($0m?1KQ(|De$%4EHyYn|0l2uhnmzC1 zd7FKD^o!U2s+PEbT>M%&lZn0c?<^vC+JU|Id=hET`nK%amiX1?>HpnL;@_|gVlsz{ z$ZZddZou@~K&Dow7O3^>uCm-BGeQ43JyMo&i&~WQ$~bLJC8>jb;~0it&6T<_=CT}; zj|#e0#g+LNb7p0}yJ+vMkiu?Ij|y;nYcZg@B^o6pMg0irFMWl19IUcfnso*zTl*=O z=p4_JmmeZ+T&0B-hBc9a5PYq?oN_{);}R@*KfmQNGnq29_SG-2EQ6X==zv9eI>>SM zrNR|#UdsaV$C@#ri~8vp8@U~2vB788ad6qt~W6caC54%W#zrdq*X$#vducA?MyIr7i;G@>n_WPEV6Zi$KAA zmrz~$V^=dd5Dags$h|>J-z&Mcfwo&SJK>@1s<1YIhWTxX*&XY6;CmsuTNZt60(j#y z@8HJGt1_m646oS&u^cCQj;TQH)~vS}1w(5}VL*G^RzLLfH?iRXKylT}gj$B(ZrFD) z!z)eVtswr(RzNh0lJVFgFb^|I2RwlzT-KNrgd9B6TVMgl`OukjfIP%Y;rOF1CR z34#=5fT=e81lZF-{(iim6R&j&Nk1x&oC=sZpu8Xw2&y>~2@1DgDHtg5T!T7HPc)`i zNaPJDdDTiDU+^ZobO(6QehH3;a2eh!l_y{bTMhvfZmpcl5D1XCDk0R3_t<2Jj>1>A z^n#ney@c%!s+gsuVi%xS6h}ggG+i#m8jz|qkNT#~bHyVU349p6JcR+&&MD^zO!=2V z^;dwWZ00fW)Q^~_zTloC_5g4`e3cXqP`qO%K5$Hgz6fyurlPeePyjGF{9_PMx3t<^ z>^`q%jzzd*=i-^mczD&EP-{_h+wyM*DBa0P-csGi;^1YZye~2i2%}T6vI3%VTUTW) zZ8+`)U}$qR?IGWBRuFho^YtzlF}2nZSq`2X0Q?CSJipN;4LRiDk3o>ly&WYXugffD2K z5bYlJKO_c!6htLzeB;}>7ED@RH`lsA`{({Kpy0so_bAiITIz~BGjVddmL9>P`SQw{ z7+G_1@oo>~+dK>n4F&<<*AoH%uJ_ODp%ae29v|PwywBMufzQ?LF@>A&7se06@1pP5 zyZz5ift~G|FoPbKuhP#SWligsXhZ|Q@3HN%Ck}tAo3F>-&!67jPW$ugWdnUT|Hqc^ zgY>=~-}d*H`1!#oDjVUhn5~ z>+k#ZZGldK_qsBc?$5j1gYEFP@16LE<9*ydAD{cyoae=0f@^6u!A@lvdc%RLC+lA|Uc{?8nXwtn6u&VUvr&Z<27brup+oM^?BR98~C>3W7+q4%At_0K#|YIQM{FdO{;{Y1swss{uN3<=fjBip3F}o zk2zf`r=2Xu&376L=)zWu60pgpNn_lhR?ojTcau6XMW$X!i`E&zX{A(?(Ikt4tVZkG z;E)-Kzm#iGqcKXN>a~z+Q0FzQ@ak^?#3#w4s&S7()I)JVMQqoj#8-Sw(&zwqw_2-PLvG2U(ezC# zKL&&XfZGxQ6!v8s3F|d#xLFtq5Pq+>*Q;X*&alC)hO_@phLYM zyP?MFUr>-AY_{9kUDKd)ttKNFX)JKN@_A&DZRNy6PRA{MxqDBL;{}KLK^7@Rf0TZF zYizbray=o;bLHk+4;UOcS2I0p6e7ZJC`0Z%KJ+6#(_KR_2%0eZpyygQ)j68zc<%wW zEMKYzlaBdx3+;E48*t_~3 zFS_||R3#kzisF2rY0n0f+4~Q>sJuXJflRlpXX}4#hr9Dt?4@(``F5h@wt`XAP5q&m z<Pxg9XVF}Kmkb7M@*dyhSp zJ$4Ce;hg;xxw8I+ecN1TQty#|zGfd_!m|Up`}um+4Lz2g-hA(d^**zS+lv=YHI54W z<~BTZqOdMu_&$|G@RWBjaI*yR31ypw%kPR1UqM9z^2E+c8AN1a{kDjtAJS825lap7 zf`l*|&N(iHN+i-bN30K)2f_A3&|Bv_Cx0h4WDRQZ$OGLu4@J`B?N`U(djC+^x>x}i zXMLK-i*q)Q5I|<;T?)hx@Qh1se%Fh?E3kU_0@)r@Eq?u$>v49?D6g$@zd?OH7Gv@B z@cr2nVW8bY^j$upL6tTS-rc$Qg-Hx2-sA;H!PnpIH{&ta_)v0d;s1c8uf}AK!y95| z_!!r2iR!!o5&0PeP4g&O65;Spzr=vXnhXdT&)_R?ex2Zk&l-V>mc{qu;s$aVvL z{1eItaB>`29z)YHAMK9obBg$bxnfuvzX^oN_OCPe zMhpu7^ZwZfkWFw$9#;g#1R?oCD6a58MB?w@Y*A!lFo_m&R`Frk&L{>Z`sjxI|BOiA zMo7XB^g%Dl2Df0swCn&Muj5RJVcrNIF6D_H@zxF&D9%khMwsx&)&^q!^*N`!^eW>9WaID|rULcaq_}hd417 z{g1!9ZxJVh$o`p<6&rSu00r#%OJE{Ne+(x|(upbH2p@12#wMGN;f!GCk#*33`>jclEJ1q2HZuUsTC&Bc8P~3kXNRZ!5IaJZ3X*)wpFQ zwI1Y#i34c{ihvD$sQH{}(;L4mcBXc!#RkF~}$bmxbhj8|(mrpi;q=UW%gatSC7GY;lVb1YRoSAo9KbNl6U+ zehRTz0}V`$lk5tNQeVWP-I7KfQ*36MSVwII>88E1$Dv3DU}r(%du zKSW_9e$D{eAnL$V-l>_!;zp4;nbV59W8nb85Tmd{5<1X@09L+}4WwQqqWt+#rBXug zp(~K~jS{9`gPQDCqpjBsvhx|h;79Fi`-#BY^T2RM0$gA_)_(%L_nx5lLo%A2&B()L zHr(;sI}so?dJruzMITXwSB-xj%&p*a7-sIDIo)+juUgt1sQwWp#eo+f<&IjOL?dyD z0hm(2b^5i`+q%BL)^tNV&X9bhUx6fZoY|HD)xk(ZA*GSCMSGBBSd4l7 z4gA3j18J`YJaVDTj*mzcPQY0QB{I`ETb!@s>}BpcHG^>$4pFGYwk8{ojXA4}= zLYL~IwAq()PG}P5-?uDP90^?*yW;;Q4=R266avO+@#k|v&0TcE?yf7B$s%lu0_#*) z>1s&{*yFJy;(>ioR@)5Chls7$#MxK4&+eGuZrMOvrMlw`dy#mpaaA$X!t^leWmBN9 zpeu0YrsDBKkhcB%eYmcj+=~a^mjw4u%n_9pM=L zT%5Rn^L&i}@;j=X{h-D%eIkf^EfC$C48gdkpqRUJ9C;)4gMWFxJcX?*oD4 z1XuN*Z4nOt4}t?TKZfi?VrKipN>xwp{7t=5vh%ND0cT zG*)%I!9}f3$^(Pa=Md|xpKWeJ6SSZ*?kQuk+5%%pGm^m1lxQx3Q-_4$qlom~SWt>c zveO8270M#7?X>dmUu-N-a;XpEFa;zB0m*Mnp^|ng5bjKFd><>!Rg>BIotx90N%K1_ zV{tgJ>D{{MgBEkuiKtd|H@JYaM*gjn+L~vDe#`(%bDuDK^7@HxRMI&)1yNG}CcA2v z_J`KHf`5D*kv^9u6I_5%j}6o|fELbUW6~SWi zx*Iyf`dpDBX41XNVPqn$ard?LULu&%P;3g^}?o((cQF5^cDJ9=1O;7v= zaplV*0p0Pxs9SEJqwhS&D>u;^{NmDzOOqo&GgEqE?|lJtU*L-&P zAO0$K8DK0% zT46gKg;_Y^xpn#=R8O2oUKiR7L+RE@#Yc}z41}LtYdjI6$*PSjFPB3zLt!X!#wBj> zY9xl_DuC6wxHLSD6P!0MC%P^T)R8Q_W)<(;9pW&|2bs|A_zRqU{UzvP0;%i{oS6^u zXS)#ph4RK8W$eC%rd3S_rfUTziHn>}-7X-E+U#avG{Y4QJhX8IX*%s6bO)?3JkF$B zEILnjbfz42IZt#_>-kKPj0wLhS^n&p*EKTnHwiwmy-<nWi{vI3n{Tgb>Tds z2^*k-v57e?dpNrVqHu@~DCSEbj5|x6fA;9Do(%Dj2D(j|RK?F~>nw*`cBD#2%4)OZ zmwpvteYUd`wi!O|C9|(}{V(PLuYe|B>*0I#sxJ7hznERH+>2^Da-~f;BIp_ zDK`UrHbpCjf-kV+(g!aBL(!{+AT3{voqY3i1kwsmDb*QJwA-qQMw9>5n65L%eg`x( zmE$D*xlV+JQkz22t%uH41xFfyAr9&kDMC>rbkwD@_Soo}iN&oLK44mnXsM!}JGbfX zH%padXX5aX^{OC0RvWa}s`TU?2}N{@dpwE^(@UK|3%$C+a1&G1xG3)=Z&340EyZmu zk%<6N%`h$D%_&pPB~wxN;B`F>KwPH`QQdK356%=#b0&b|Z&#G}l zU5dT5s1Fi{ppf?bAJCkNpdfd_7-G(@JBviU6OFy6X8#@2_EB?m33r1M`hr=Oso=`y zQVtxi?1)JUEejPHAy5Za9c)*xqEIPGFEZhAy$u-VpH2)ea{sL!6b#ybZ>z<6Twx@RP%nT-_%}53d<=cEzaalkn=x@2^Ugcj=IlZYcSaNu^ty>ce+wB0wnk`K3g;RLy;>Wug8TtqRcLUOj|Lh!-hg z8N{_uPPi^2f|2>&%qn9~o^)Sb^tT4j)F-f`gdT{`B%mJ~PUKuTMF*i5>`W8Hy({dx zRZf)ae7WOJ$r`D&&gke;%0N$a>j_j|ujk-w%n)T|OZNN2!5|OGB<|&jZBbO}Q(BK= z)z7lj8R4r$qP%1q$f7Dz=q+YQDAszGqQ}r5#Q~{fIk3BIF?x1pq|cU`)tO%(Jgl@* zQSYc%bH1wK7;^L6W4O@=Uhp{c%6Qmr8@>K3^Y1!APE@Ns4uWWuazrI?yecR`MH+z= zG;dAmZUII5qR7BbiIGuNQwz5yF#0U@oe>wYsL{E$rqtJa~ytEfaKEiz+6Py8jLaUe}Ds-II7l!U2(Cm%^kXW z4d?`@ajf*iX=^-6)?bh(N1>AO)AdX*(oYnc zz1l0eUP1LfW7n+Dw3fP7;Y8fyy&3%>Ii{?TO6DH-GnFD;2pNzM)|2@P{K<-xDF;JxD((bl8vc0yM0SOJgxgBMtzzeNGuCfM zf9~VGuRp<%CJ6X(oG;Es#$>@5Cer##BnbMko--HL!vk4N4D;qJfIYJi!C?Lji{kzX z^Ob&f_k)=}QE1E_0eTDUtjqw{7r?&4hQGh>?c>P*pL*dWV(h5(!+xy&nV3fWzvs4D z{OCmde`n(TZ${Sm&datS2v2w72_?3M6OG!sk70|N+Ydlod4dg zw#GBrg)EAB_Vg4;5+N16+$g20AU;sTDgz)H6Ky2AcCwoghV1ARakz>*kc_lBbEV(9 zOflNEkb9^6g>`-VlNP1cs2eH8OZq6#ahnFGbu`OkI+2%zp{2{eYboC}2Zi{JFy%W-5b6=h#5E<4!5l;u-vJ-~$=WA$#a1CS} z6$C`E9MThvE&!Kp))gAOADxW~=@hOX65A$ReRmm%x>@1~2vc>!6^b9&qd8o{;Q|&6 zT`+vdB)&E$jHcoN!)z7HkSsH33k@gn)D2} zEgDN1RRdc#Q`1^z1A5jb)94i7&!={&`DFGcM)ov*3Rho%!A()01Ht1w$NySDx0N2J zxxxkl;tcyg7SL^t>@8e>#y|XD70`$Ew48CIocx~a6e*tu;`VGU&H1`;?jZsQC6Nh< zKuF2BapTTGw`2K#C>g;x@4MSccz1+E78pqePCHAeuWBo)sqS9~20K0825oAop`Mzo z>)6?_W4#S>6SoZvy_E zupEC^4c@P|X9d2GPWt-Z7vCNF9%sK_kDiq@LsnQ_BKleP+XMt|zHT?W4ER4jE))p- zUeD4Ec0cdZcfURz`aa)Q-35GKF2WIiitkKtGdr#VeNa6PeNPT9AycSIHih*f%zXqy zA72+2e_9-pD=WJ4zQ&&O+ywG6OFh0nA-`YyzTZyPzxO{(8;{GlA0~+z-4qnF<~E9{ z?0(@B<@tZ~n(p?F$++Rp#_r7TnDfS^?EL*R<|~eDDa3Q2b*svtWhelqbQ-PJuPS;O_bTLpNH0e>??-9U$16(WCBB(Jo?XCAJDy?5BUNX`DDGY{t4 zacMeqUb9|F)Mig7&Z$@n>_#&3$=3oU+L1z!>>5SESwg8b{%F@%3Ve^M!LXmn8@t0J zm9sGz6<4rPgBVnyCi;jq+fcY+V#5a!Y@Yg&l}cVt+x-ECSi`PY+wDbBD%Lunqs z7u?aCJKxc}bAwA-r#*lG)eotwunRsnjqir& z)knNM$-6)Hq?G*6H3gl)$>)xoT~;f94OEWpDWw#ff)WOW4n~N61VK`I|04;KUdcwY z*BBo0>h*cpht~p9p7k*SQol`F@jc7(${}bW zG37j?osl3hUs)_DIy>lkI-dsQ*MhA_!*NQgfT@j@*4?-i5=s4Csb;K=2 zuVUu~ndAmqUl>VluXX$_kmoG4q@IU-3S8AJ&K#H6dKc}u$^JTK^Ao!tPqJt1(Y$Scgi8|tj&~0 zjc78ABs(+hw}PnGuu3mShyjWY%Rjm3hEae|(fJ9_$=FKd_CL7*ZQN)OkWjUka$W4* zI>sb(NKzv^lH^9BAioGt(?cn_?%i!fA=!y^i|&7|L;@gu`gjTQ8>#=k=3 z&y1tkrrq$FxZq%of#5Ylz(?5U3VSba^d=_qyHD$&JWu$hO{W2@Q_2IqV)Lug>x=(_ z!2OU%6gqmls#*9S1glWOD6=(CgScs_20Nt&(I|ndKo_9z;7JlBQN+Ffj$li?M}^7> z$ui02OeUMziUwA}Ny`4IEk#xyG#|_i2{kUR$`qV{hmTkjAUyJhAmuZZoB)THdd(wx zeJ7&gU?m-Vi%0>*jvePfev&Zlp0_B(O?b_jeQ}b;DCS)R$GQpn_zaoy7oI?t8-Gb@ zlO6X`pyb!Of#%{#59y^T9MwbS&Ak3CHbLV{>i?aX7ES!^FL&BU{<0dfL$y9jrS(n4 z#lX_&_j5FHy_Wj-9WLsaAM!3RCvcFWeTB_Ai=6fqoUy24k@*Ys@k-YSe2`yol~ufi zeDU1%5S}+_W!xlXkNr$`I0Ahoe|Zl1dS6ex z^Z)lLc$|1CK447$EMHlnmX$CA|K{qi|}@AdcHOJ4_|tut&+;{iLa4L7dE!%UUf zfiUZtyqHi;$9AZgycChm_GTZK>w$vK2KSh@p@WOI&VTrMNUOVr*K-iwo#D5er`~yE zy{2CcUY7C(3yT)Z z1x8gMA}KA)FR)KAmIC|z74Y1--#2ZLeqFeX=Egi8UeHne^+^$~Us6|5}KYO{x2nk2M(Dw`D zEHA;r@b^%BauJmJ1cZJ?nnHU!U<^GRE!J~OmhI0;qlIH42F(PR)WXL>r?ldfLyeat zf1^oyrOED{NfD+om3f4SpKG;sta2rPvW2yz=@t=_9zq#ksT#3P9MqTPLQ$^4ZRuLC z^s~e{OM!#%X~C2~^NDN3B$>ghpVw{?f(qV2;TWsbiuY4RStG(gUqK@;mV^9hAI|fi zFL8MseO>eBpy{cA`3xWAV^Y0?le3e@c6kst?c|4ip z$WoP+?^Kf88sL)wISq62rzgAFdE%CItrp57RKgjDFeiv!!NN&)zN~g58x~my{JAyJ znNw*6KXM%w*JddpctvaNW^oVJur-uPG`2-*=$__r2!6rlgw3pMk4Cuhi-4Crh(EFe zgRCyZ=P`HG3(F;SPigUm=}Hp3Q#Vn9xSATaY2M_QS68;uB8eiD7nJ^;ZOXljc_2#K z=U2Ol2b;x1y?H+c!HYzRUI>~b`@no+w%86OC|d!=H0usoOrkYn zU6_1f1ck)FRd{Ya%r>67222%sTL}%FZfmNtRT<|y8xPMT-9~{|gYL?Z6YYAK#9EFe z&?;}%g=tzR6%%$Pa0>@B{)0YX*Q9}!dgs{$Iz{AiAW>XW#3g9%s$+emQiBKGdL4>i zWQgN~OP~6qO=tbRx&* zZ_9i%hJN9<%4;8}oh=-B#aS7&`kS5+MAzUa7`Z&_R(Bz;ZHQDHJn6X?-Em6av=qtu z>uo63dlxs(JmM)t{|f$XXSX;RKPf5|%Ak^AWtbe3EVae#9ByWk=m@hq(xQwlB{E;5cAP?l?D}Q{C7rc-LLgo zc^nxZ=ssLDL5s1!LNPVdshBtu66rx+o2A4A+q}(O+@~bl`MGV=2&NLiWTPcrxTapa zk?}`K8VYV`mVckDbw|{a^8P)v{PEMu@a+1>%l|^o(l`o`GV)jhLP<*~s0=Y9AH`ij zkfh+D5b3DlA^c5!6#@zII>e%IKYU-4&cZOv>xY*x!;f z(O@LZ(U#VNIUmj`UGc=vWWy5gKma%v?_GTWaHKR>n3yBC&c2Av9a4*D!7?(Q&1Lb~s;A`(maLBo#RIiac_5fzjq_6lqp)KK6m zNc@(`C}d%EEC#=T6h%kw%EX`q5RdfAP_hETOK4AJ*J0s@JW4xJcXI&w=x7GEmbRG# zZlh$9UNQ18_nyLi+)UHM`IWUC6QaT3(V*pnB3{ho9{-Ym9+ge^+Mu-B*dPr8HnE!C zMv2}5y!7^SX)Cncd50%0upS)(vwFdEFa~iX<{~IPy7-CEGR2ca z*zfaAd~vQ^56^d(4l+!p4})i5TktcHxzxf|G4NHmO2gGi@HQe8SWTZw)nv{=lIsP0 z^IzFNp(vRG?S}WWM1oBTxxv+jXmp|2!g@b3Iz0r=CEKwPo{Sc3AhdmS5^z^RfHcp? z4|&8-tXKuQT#)TA{h?l?x4k+X^FAsQ<#UN79E@cwh_aoF(-2JD2)5}YrD_!-JU(LH zG*JaF|A*)u|KFQk*}qLP)X5C|_s%MSbFQcX)Cp!-9(HMQs+>?%{=dzj3%C9lWaSn5 zki`$BX~^O#bkd24C$)66h*e3;s=Pc-4ZTneAgH9u5m(F#AJGP76s%%zj3o8tdIx!k18a7*k{$=G%$_#%knD5L%g)XP=8(=;A-3id>KNFH3}%TPhAc*?dra%$T)Y zG}016BbuTJC?)8`YFkj3b+GxwlngHTB&}&QfZ|d30fiKbixj( z!F2zbTrA;Ms|J%nl0q3vb~6=0I$cB%vXb}=I;`>r|S z;yqX2+G9WkP>_b-@`~ z)(6r zZ;|dUh8EJl2zKPSb?_Ch(MW}w$s@h1B>HZ1-x~%Z?N@pBLh~rpvSLVH4q*{`(;8sQ zSy~}{_VGZ^sMN@l09Yy&_iXrW)UVuwp?lqHSPM~qYevQm!m@br`(q^&DHUFHI`eV- z?&~h*ky{OU56!-6dS<>2rO5zs@v$w`2ki_reV+g0v*o)kv>P%t9X|}%uy^6(0BhX% zr30!B_znFo9>GT$u=uOw4spcUgYwqaY%E^RF&A(xdiYsNn$jtG<@urmB}P%DjuSlSQA(qu3C@rsw}*g1ni0arLKi=_?|K>Hlc8rjGtY83j(MX2bA z=j`Z2!cmge(SEl9Q8)uOOs-VS)PvGJMrP@c8cbfVO4>16pAPlTJ>(?Qln6_M7bTkO z@K!pID8TMB{lIZY-VZU(hE>q#X5WQq%1J7#+HUy`;l{+4aT{yXjG1o&hPzpsyEn!N z|MQ_r*+6&YsuPwcPuWN7%3rwQD_PP=ZhmM9*C0dft&wNUvPl)s0cVkjT+H)QrhyV2 zGSY~bPJOX%CU-BFc8&mADkDV3jZ>@Qa9@7QQE9f2?e9MwEPXhLcm-S2+tXmFILP37 zkVJACOw}!G<>;2ZtOjS)v*PCSi9Xcu*#~`~nc!@EYF6sfNn{REne zogu=*2h4$*ts%@X+@V?WKXP3_>$Ou&m2RZ7Kw z>|E#%&yhPf=)`Qudlkzqxccui@NteS-T<9|4gQp^1(9x6;w*8>Vl&0GOD_6GW^ z;}=Z}m(LsB$N5pyXAsJ9tpO;P=fM8LoLz6Nf9f>XHVQS2*|LfD_?uEqmUqO$V6RSvZWh8Fk6Q4ahj3ArnD);$? zuGm{Q56eWGRF+@fze!iGICOu`gX#8k$bZ~J1=0m}GK4EJy3s>cf?DxGZfDAk;f|XNdnm9`)u5qH*P8PDrmOk)gMP0zhdnzPQlr1kFx07EX%|(dsZ?H1Q{lC|;yDr& z@Oxk(?X3V0C;bWyl!Bec>Q8P@qvG*u8(M~5j^dCnmrITN<`*UA_Jwl0YcBisMYjfE zq*C5GlpC$T9=U*)rhG9&*>ny&F;T|4S-9jC2I!Y&T%A%&<@OyfZ|0`{Fsys}+QEn7 zY8rTAOaClg$~Hd%RGh+02ySV1Q3*HCqU-VCp*?n7G|(z>DTRuE8*$D%$_2Q&n<2bn z4G|-eJ-D^iw4%h;x|9`?_8WA8T^x-Zpp|9s(d|1w)w?CWZ4swYWj zg8_7q6>8Y@en(UAS=`ZoirT&zH4pfGNc zjKC3FPstr<0XBc4H(CLMw2%jvAqJ^lj%7dbDN`)?Ip(QMn|zW{DN$|=XU!p?yoAMFU7*3BE&S|bS~Z!}u4hD}N`wCY zU!Y-d>d{^jPb3Ocea28_&?-Wj~8jvXUrj#LHjeV{yo z8(mLP%dPV9t$Ulz^SwPhW@5N8WUm3KM6eXzbEDh@$eX~4F{RNydgW-f}u(-MWSv z=81dKJ0Uvy{>Hc|kxXrksk1%-%DOyEDfLjYX#vI?${pvu7zIYV^mad4e$ZS*hY$2q z+OziE2T!Nhjo@yOY}J&sErL;;9D>>LKE-{YoB$}=@wU>5V9j}ZX!KD``#CuhiF0C8 z+7bo2G5!rVB|ir$Sc?M^Qa13X=d8It?JRD#G6w=-XtXo|O(gIVCF zkSAR1nf@E%a1%8A?a6-v^5}et=;T8s|r6a|}*jJk9IeZU;OD(Y^s3u-|Iwe+tH)TE+> zpG*KZ&;eS`W^M_P#c_@;Zwt)vTr@CebP-z02Kd4iW>iapHBXa7#P0&OL)n0FZdDi7 z%+CNy4j6pfkv@f%Nv8yE56uaz6>71M=8Pc;)NJGdd+A?N9;P>>1=%FGiAAaP?)<}U z5~bz$MD9=gH3QmTOa803RH+UeI_;nSZ?wx>-8m?ncDH9t@t`oQi4=#ze_Y--bC>>qW$5wd}OeGKdY5p#P~TlXDYqz z1KfPv8biN^dsZQ1oDJ~WdI6wj^-b4elNd8z1Gizls81;xif4m*zeQcoi6vv zj~1Fl%JR-OuaDErpES#p3s!j!+ly4_lZBsW=N>DS@mBP+>)RiWx7G1Y-<~b`mt{hE z;QQFxaaMerkB8~=^N&T}-nUUr&()v(lU8#DGRm8gTD4(qgUsA?eBT~-SBG~74tMnK z-*vU^4_@BS@6*xU9U-#b?5wW0+uQMrT-&K9+3|s$XWm1$B=`8Fj}M>u;qnr?@WXvr zdz|edZQN|$&kNtKx-r6xYh_IBEJYze1v6)R@w(#c27 zO71%D_xq=KJvVJ6>6VVjnjQrZU@^3Lp>%z&EhH=Je3qRjM}fGy7er*;9#iy z(BQy`Guv%mQB_~Ws-^{fh>b6A>3TRdvZ$&CIn-=db-Wp=WdMu2A?x zC4I4u8xk~tG_Wei1o+d#o5EXf*de>~r*!+UuJ-Ex=lKiX1DHJz2i$}WWl${%dy?6W z{zQN~f7Fzh0xVt5Q_qnj6pBj@T)${TfFpy{8B1F}eJ+mgn)uGYN80dJWGIj91>}+y z?UL2TsfkPz+B$fBd*8Z~okOz4ehnGMn$8Xc*wK+QpL<9R*D4fO>OlYXh25+JEY9_D z53gen7TpCVGOblZ?cpy%Q%7fs8f?`GVMmyz9?hDArzivHRC@L}@Gvv|^s);gFR*7! ziT!fu+5l7!fq*U=wjTC=`s9|ud7DP7+NI- zA$X;TDpfV3`6s=z0F`y1IRQ6=5KMY$kSc%^si$p{VJyAqIk;FS$M@)8lNZ^^0RlGM2X zf147iSbKm}g=s$SRCpulBBXF1)t6CKI4j#+j@hbIg8=T@GRr`fGlpxcuxxpvDkh#71d=(-T6lPC^ZhlTD|cJ{+VmnkU3yj|)E}?gyUXnr*Nto*oiB zWNK|O?hfNgjB~i1{rRA9h3cd+bk#8ut5(*q+@Bv#1g)U5$si`D@U(dZ9`VT~#w7&2 z?v9*}7@aw?0Th~Uig)HxjQ2EU0a?8g7<=2osB!w&s$;}aM#VlQ=1C;fmQBCaOpFOT zY0*}GUDgu1bV!c!eKoW_iG4u;LL^D2#(j%+tGUUMDZWJ)ev}rg>H-YHJ4|5uuUJdm z7-?$&YhoBLmEfS{J_*RdHf0k1vtoztu3SWzIMv5o6u{P|R07H?4{$58uIk2^Ed*qK z?C2at@p?4hb!dkLQFP-h4!2j#*P~+PiDCpl+Ujtfjz13u@6i1cQ*=W!H53W}lx=b~ z2-%neyUhYPRuCK7iNi-0=GJKhGHqdd)l~&GSFj74GdLcgeYTdAZrBbb@Win$9%zr6Z0=6g7HJu=^`cpe8njp;J|x zr@Ights7=x$Z8vt-tbexu#2)Fjr+$J0J1zJI>hR0Dj|32lGId*L3E*s&BrMOTMlI9 z$|8bUx&^k9FMZGR?j5$kiSa0X5#CO?sqT4rka+5ZEnR;^APf$QgC;85U2=yx!Qpv< zNyMnhkVnT76BU8fmt~n>)WX49o#?t|!A!z+`4o6u;4TU(XQRygCZRAj^*6^s-(1 zv~F)9Ygbf+S7iiwy-CB2M>jYN=urCGu-IxStc|6IHNq%Y#lkTLP93T>^s1L;xE1Uz z>p}$8JwuW7x>S$I4ssF9aeD5ZxOI8OJ&D?8c zD-Q7sB+v#UGY*aSV-8#BIXjte@6ZfC_dRpTNY@)N1c{!V9{@;+nH7Z*z}SBgcS+G? zE~378QmCwl+$Cvd7=V~hKOj*U{e5cil0M?vR*N-<(Dg0K#8acwb2A!$Vx##t)POJ& zEyMA*m*|_=x^Gxq0})JyRU$20K_v*jmVmvDC_m|*8e<}*8hOj4!4I_845-9Y_>sR90US@yfEVSzTC%=QP zTtN@_W$26rlyVD|^V+qhYh+7hOXy5f1d!Pz|1sjUl!V>qmo{l;jBHQHv>c%WXj%~H z4r+Jt73u$Af6kCL`6hDawt-gNvQ>_ z_Loo0<^RVx9&VJp>?l~!sZc%ez1nwys@hd0LUt*11`Q-6STH#;wga0T*a4;j?Ol$o z7k$UW$3ww)TB8nxv|z3tn8Pff0SVnVC4Nj2e*)ugK?+)tF7nf?SHM*1knT8|Iz(-v zQpt#(qm>ZH+o-~g-SD7{D_yq6&zEJgg@kva67!J8xr~!;BIs6@MTgdhruFT}IsX=c zUAyH`$%VS1ratv>CTjC7$MXj~4LUNn>kPnIi}PVYrk+5HG4AhFFo>RxsUKrc) zmaW1h^sg}NsQ21EIsRNZ0v8Co^6~OAL zGo(E@BV_oFy9q<957bJy`A0U4*4MQHx`vd7jj6qa@(*k+WYP=}4?Smem0uT24;Fqb zGFTZxuuTb7vJxo-;#L!_FYD^(Q-;230lHVJv{A8&LvOoIZMqPg@Ix3Vhr}oRBiewa zE@M*MU##~opGUg{J?s>A-=&^!NK-5m3pC_Lgs0Fk$H1w)E?2vVrY=Pk4m8VQzuV!C z)yfhBiF=52F9Q@qBxhNGu8~YnAfv}Go|QP`mWsuq6}aW_yR=S2^(X+R-w5O2Bsm7I zpnadUYt1h?(?3-j`Bls+0UgxnHe*7Z0R##_eQmEso_$Y^;nNdmsK=BbX!2x(%j_?_ zhCx(t-G{1Lrea&&VSo%U>j!l2IzBxLhobNGBAkJI?er9F5C_uqEE?Lz-pA=rN$QYE}U@d4Snx=h>c&z$VHE~Ks zKP1iEvzhSHB`96#3J3)Y(AdDi&RWAN0(ze<0~*z9Jiwl4QUFzhF|}clrjLj1NK-FN zQM-;*T!<+v$(LG+q76U8$=$!y>Doy~_Q$#Yto@JuT_Qd6YWwr3-$g%RG(WUK1131M zOye$~mV^Fy$&OT>UH;su8biod9gkL-)_4i0;qlXHB4H%HffD8RH9%y66r>NM z5Iryo-boNOgDuqsT3~I8cxVP8H+(Q!tH5NH<;kp5UZ~Mr3KqeT_s%*^Nku__X_pl+utQEnTm(JW^mRDd>e-0#sH)Sc zJoE9_%E)zDDS==FFR^c6CVk+o==3o(>585ue(x{UbECLz%~b96l=TS=LA5rMz&kGN zc8&7=02l)#Wdex$sL-^90rvDkoMn_V{>Mlv08~XU%Y9xRJZ`yfKP!W+!H7kXn+SNc zJr03jC2v+rV`oY|7gpbF{VIF?7Sq#0%@cmcTkWb;pi*|qs0Ke1quYg{vJ0w+|(1l?E31O@hBVeNKo_4?^gh@nLm4VTi9(2`V% zw|&L(;5hulHr$K?8P|5IjR z6|%_PC!QR{`Xx%$au=*%n%{T~zp2%x_@!($EK|WstrZD5Y@Lpj`z(>`vIzB6X_qPL zYptDDe2J*e!CRqY5JtgZ!U}@G%o}_m(d5Wifu9hjYZ8(?jc7Otx{Z{Guu0;rt=Qo= zzu+rX){*SFf&{1wx~wAPqjt&a|le&UZm4wirc9t}trD02C) zjmuoin+2)3v!$)vL;0=;cKju$;{vieax)YSAV;L12mS^W^sB>;NIn$A=1H;(bK~-o zohJ-KB&6dXN&zn6d!8s2Oi6UJd5eX0Pvs8!t$YN|24atOtTIVCPFS>9wnus=SxX}h z8wfW^s0lbBcN0EKLlqIJ@?}ujfesi?|NeI7cu!HI_7duvHO zu=2t8`k=75b|q8z6d&)wgwTA@`TUbtj5f_#s)K?hpPWPVyJF*X*I zVY&AQuCi8v4fD|s{nM+rC=>vw0{HU#=3-9VLEuh`Xr`M@b^-!K(fQt3fgPODTqOiv zR#^KL&-;|k@>u5}*Nc!zlUQVsu=@oy@fP&N9kCyF$dYtbwe&%;TADPgk~L~r*r_29 zM7k?|7UkN&Rr~7p(Hpj33ZK#@%9@E~!2?Lq!o`8^rYa+S1r>u|ID;?l*Z4f2IQ@Hl z5(fUs{MmPI3S?>TM$@he&H?4JL0h3R4tjrMdsr$Ao9SYUsRXP^bUwu1kcIowm}7d1 zNEPygLpg?#6{j6ju!03c>^95xywSIniab}H!9@( zlIZ`f=v$uF-BQHH)2;I8%Vf9HzVrn(h*?|5yOf-La0~a1Ql6A3sm9e<5b5tJD?2vU zP?75_V-;5oNFzkY34X*8nT3k3cs-R{(l?+rfT?l4HV<+quatl1o|z7!|WLX@PPek$>$P#7}uZypegteiKYhd%6^`?;W0Z6 z$#(;68DU_h!8IIoXZFR3t{G|y@iHgVeI!SRQnS)0=TUCWcV%@1+JSvjOV1%K@l_N#pXwL`7@W^92Mf>lBn zc|z_O18j_GatH)jB#@|gI+UTPQFlT=dkBC`yk%1FxEtU^^EiD$GE81LsT(N zIJ0ukJ^>@ZH{i0JL=*6N6pxIBuYABt*0lyB)Ib=zqBJvUsQ@8aOmQuoVB+aPrOIxv ztEkQ#bUb$QmF5wA&Kf3L`+|Ucix4lSyHx1jckt9ivf?t%&TloRj0WQt!FH)<5_P(BDV=T z*n|f9ypP*{_;yXEHOSO<;1~)ByeM|^VTKX>2O)AfXpGD_U_0~JJ|WO$(47a+ML4|L z3oe5cf@Wa*qWmU%eT~Sb$R$)ce4E(Q{Aq%WE{|ibc3e2mre)X<7Wn{rUD=K`Wf=rJ){g#y|_So z8tGo48bn{$KJMaAtUZzx9~FevW1WMX$Y=QG$HzIL6cd47zb>nJ@g(;Fz5`owxMKDe z7gcw?-*fP~3oqgN@MD5O{dn;{zG3%v%`LHT0KVC-v6jvHe7h!6TuW;QedqkAN37g^ z8T%BTfcD@=V`Kro-KwDQ?(jz=Mrc0&eN{3&{{s%b9g+HaL}JNb8t0eAA@!)#cJFB@}g4UpRd2Yy)c2H1xmi>r;d2VdIn1^)x~dKBe@ zqR*I7KmHeY)#%X*W#OF?B160RY`Q)NBwN&u zeW99cdf7uj>Q!OWSDI+3n^k|dUSE5s_LybS=VXLXl6!`EdOr3?itg7jIbM*e)KyBf zBU2k=d`k2F*X=g!d@&OM7qj4;h9)yT2E^(;cq8F_3_`kYU^0JgH=_~3rmw>GHD~=UvzM^H zWn5m|Vq>IzYu~i4sJ?9=#jnl!+-7Wh2#z zYDNco(Zs)QR%C#u6JjpDZkDz@Gd+6O6SWB!^5cpWVo&5CO0bR2T67WW(wBN79dv*P z`}YNH+}Qdy1YFmR6*Fez=xV{tI$H&KV|>+Y54Z*^Hsr(=_!sf0RS{HU?r2Yr;ruGk zP7t<*_Z1O;pZ(d<`cB@x-m;DD*uh~g=K$>ZzgzNkY^*Eg$XvDtwx;i*4!f!CoxPNV zQ9>zC#QhAqeVkBBdM4zIeLPM$T@8mL#hPB5Hwj&*f68sfJ|e0G4@~b&9w*!vVk}>ELT1s&cf?Qf1kkcC^8Tc@^(VHhDEZq#2+m<>NoUmh98G@}IiT)n zv>EQ74><{v3pY+)Bl(o|xbQRs{)U+d+P|m;(HI_&k4iGER`@y^kAM8p(5&bRs|f)M z&NDZ>2h1SrKyU;oOc!o#e}+k!krAbu5(g8P(=wF~ zgT^Ji<|&_qD<#s(TCEy*L1CfDBb>;FehN?HlPm!P%g=mDDn9bZQ7jjnIIt_kGmPus z@6L&Sfs7Lm2-@7mvms{2;=X@0;HQsd%w+?c=5R2$s9)hd<#2}t%_)5TY{>21uNW{? z(7(>jojx$&FCSM7AEgVEi#Qn|ULw-GY9CK%9u@zYztnARB7Y9E8A@Kh6tUzd=$KW` zOZ^!4E6O3j>HGUxYmI%lkU(#ayQ1(AYdIE$l>f zBNh#2`fX1(j%#Gc1*d``qqqCO;>-OaO9ow|mS;)<+zZqZPims+m1gx8@Rn*l5Cq1N zU-QUEM!Z^Yr!Lxvf*<`hyF8EZ)=tuEe$6nR8}^pU<-8dDi(OH=M*FMFNpYVfu7C07 zwH9WaWDw7Y*zXqKK{CN7IbpbERYB7$mFywW43U4i)L6r2k}^0Q;_=WYG1vWf3_48# z*oW2AW0SwLvTI|(`7 zFm5?Q_)d%__hqS^=9QX|Dk&n)esghk)Y+okJAZw1Sx*>GWUEg5V1c{$0|OCC;WPY} zQex=^Y?(dK7Y9ohxyv`y%(j5K(M~+zxQNpowYGZPLsx%1CXQhsu>6fem%~u(BT)aT zHiQ2rjKh$u&cGkxCXqniPV8BniGOU5IbYVz>U7!06z1Djp9O|{RhKg!KBF(G8C0_L z=s9{dT>W0uOI*vp0rU5y?5gqb_WlZ7%0lR9kr?v}2hW5Xau*J#UUW%?P7(by1#^00 zen2p2gmSuNqQG4Mi9~*2;ImJ5yRgS+{eX!JM#>5NyJ}j}LxLV(h>?VxxOWOuE-4iO z6ZL${wRFMobjk2^Oia#*`{5KN(RX`<9MkKi5W!&)W93Tl#VC`K#rNXI!}w<9gx3ux zaP>+)9b0KvvO%pW3k(HL2h`@=NG~_2w)FS)JZx_e8TJT`UW2%7iE5y?t zz?saFV7J-hc*22$<11~#fylRp9}ZL4BML008pq-c zcL>$g3Sb45`Ns9fBL^b{?pt^ z*tW>;SSi99*V|$_Eax4;AD`KCg}V!9m)$cL@dSYN&StlN&|_E$_q5$WQT$`s%9!y4 zMf8${$GYzAaI#~gHXDtHKwRNU^3X%+ZKm1Od=+4Co^??NjKm#%)K1E zvb#;7gV8f5*cKGprww!c=qzq^;XW$nVI=Skw}9yu2c&OW`HQ4Ggzl zw9`;vV=X#=I^Rk3f^xiHL=*_*2EnsF$Hn5zmXn3c@rq2J*U&*%R<_m_NwfO730nf+ zMG$c<=TtE)HGviG3K@IigL;{Vn)zSJLSm5-J~7E#)N6A+8e%OS`|>s1zl6_Z*5I}f zX@XajljI|{LbU9EniZQ*vZduM~Jhz%KN?Zh&hT zGT#}f*X_R(QjmY}SKA$*JD~hD0c}9V8dCwOZ;8omN|M+F7h~D%2>CLIApYbM*_~Sa z8`tnzz;thE^-e-YRjcDFN>Nupa>;#`fgX%4k7M2gn9NM#ZhKfogc!~Jp=DgNDwHvRRNP} zR*s*^JcBuasIEKGbu7Va^gtsbCL)&=k~rS2Uy8}z00pHX=|WSzODI^I1Zpb%cL<1C zUyWoCVBp0&FmIX|Sw=pR_A+cy?DY5)bBP#D&*@K(#P*M73sq4Sz)ZZ*&Qls%}`rfJF_*Ynaz z)&QN9$cXAYUdjyV5`L(qNFV-J#)oh-!eyY5*JsTOA6nHEt?r3rD&juF8y1q~HB-boEa;5CF-4R~09H4O<)I z|2bOqO8Y%{s1A>EG@PkZV3 z#91kHAu`PTv(BsuE%V@`MG9}fZg*K(Sq|c z$Is$Ejz$l2Sv`NOz8ag`pI%`}3jq<|>3&{CNR@oA2SZNXx1UFNSr=`;OrMXZ5%q=m z8a|PEh>5>;W0!rs*34SFwy#w@JD1n*Jn&syc%3w`H>+(boB!#qCRkaQ&GN?czc>Hr zd9Wbr)UxGzAM*BgKi&RpY6!65K$TIk?v~pB=m7wu1T_L* z`UbHR1So@H$CMqo!sOu>@3|KF7TM&;soGu++wMZ(ozr=Kc<#7JYJ=GpF2B!NU|v~H zBJBmu0z7(b>R5JeZy9+Js|I;EL?u+!s}P z1RsQjfoVMnhUraNQZmE)M-vMZ7rY7647gJbb|A%%Fo;px1-DAV(}^h=Fo(^#z3xnD<2|wn|*4lp(DkX~+6O#gs{?dqBke3Gp{r zA^2m!;vMyu1n|J*}Ex>2nnsoA%46LKoF=nkf5nM~~nHIIAKX>k6<3Cl;UC1M$3KSl2ZLQvgH z%~ebdmo%;88+{HV!es*>#eq;na8t{K7oTClZHkn(3sRE=j0yV(4$E$J)~HJA;Qf&6 zH!Hz!_2+7KUxu^`@-Zqr4tCCI)>#L*qSz3Y0^eWukZ(noi0f494ieNfzw=qK$=h@_ z*pmQ0j}KPqmJKmN1GU^Ie~={*jD3psQ!@<0vQN>IA9cf17^{x^R*z8#}ZzoE{UHYdl*nnh=#XGZJd z)oDw+Vn@)r1+Hz5-f`9$sRM^#RD;#?Ce_CdSJ)U;G8s>v-M(oXxWorIK|CaA;8ar# z8gO<>;o2As9~G#cLse)*mX*@q^lXYsu|9~=eq;eIFvo$`XKmyi@^yl3W#18&6%0rF8 z9Nx&-X7hfc?>AFf>;5tF1xg>8f4x3v)_SoZf2!D;sPRk&L|%sJQLaReIb zf7RX(kATG-3DP|oRx8IfLm805xjKvO-PQ&e)qrL!&BiShxcyCZLcI`8@4h*w-fZ!N z(`iF?CJ@Q)@s6R-@b9?VSPD>q*!6f*@ zCbp+Sq@i-$1{BY50<7sZb+utv5OV`d^-dO5UNc-wF~CP?pI3p3(BB(%m0xXOYfw&zEhUTZKMy`ICe>slhNO@q>GJPP6^B>fIz z0!Yj63kh*NamrdM(6DDAo2v8>_Crn0$ft8Z{DxUOa^Ugb2F_tbF@d*Xp>d7B3h$DyJfT$p%aNRX2$<~qRupm#OLfmtU$#N}qoPnu5EIEy%?k8OrNnTl! zc5nimkk<4!woM)+0NAAiC*%7jo*WX5^BXkv-AL1X4MUD~-CVu4>&nilVXE31TmQbp z=Q_N+ck79Y5%-wssV21^_`z##W(qPYw%5&^cl)*AjBa;YT&`Ot_gSj<)C)p@IVor1 zTS%O9+>&kM{Rm>ZzXR#-|A?FMdy4-7@?Tthv4+>h{K5Nfrf@0fRdjFq-azG?*|i55 zmU%$6zM9VJUWmD8w7G9UHmj94rY!+ z*i-V(O6)z0NUiZ4=MIm^9bX4M>K_<=j2f!z-%A1FN6nW zxbR@Ld_9~nY)JKxa)CMI@Q}6fpfxUQGA_DDeRsI$tmUach8lo;)ne{rejO49B5*Hr zp4bqF5bO$TBQbX!_#*ZLj2N-jt@KV&At`?jKa^3~gwikzNM^I_Z6dieA@~vOyMjs5Cj=4+ zGS=x>RM|;LNbB5_pq8J!(h1IU(E@6RD}rvS^v>a@m~Q*cH@{!DY!>cTdGV>PJGGx&EN z3?ar!6p=Ggo$B=|i)e;}QA(8a@fh1?z*IJ*2Z!30-&7c#l#H45g3t5Qdecj`^sO3D zodMaBEX1)zg1Lo`az^#WFeD^PbI7`g@s{e73*o80CX%%7adp-Tfv)a{l#A9(v&D54 zyY5e=5y%l8w;Z`O*3ylBHzWPrpl##k?uf`HAn2T3g^}@cjZ|{rV;8N{zOVG2L3nbC zlnKgArP(^JLc|ClXYrt_C}~$410tjZH&jrT?&pdjs{uwpKBm4QG|QQqwv&X>)}o z$<9|d?Who=*|PmUJ)7CL{G@FY>iGL1$Hs2&hlaw0(pDiZ@XbqV8%OlP_!P37!0Y4S zp%FaVZs16Xl=3x6% z3zl9qv>hGI7w%;W?9NNpCK0y>5XbG17Qg8wN1hd158$k1N7(&jt<8;d35|b38C3S- z;Rr=PugIkFL)&bmVl~8BogdH4axlvojrt0=<9HkqrLzr)IMwwsWwLTvg}cE`4D%9! zQK-WCD<$WkLktQ5q1xO>0b4IWM+RFUWsfm2ZpiOnI(K283*+38#E`Q?Hk?XLriHzl zK4GgZc|F>8{px-Noir&mG4zn{qx3njp&lv24q`?S{MizvUF&m+IjdYi?@&59FlRMz^-Qz>D*5$g@Fpr|&ZoWV zc5NvF5tj-+4_9qUeIYx_ssTF+fjA75h!dh$nkh3ZUC>dDwL5cyJy4fXc6PWhS6J9> zcM0;zc;^8lhz=#7vVvSz=cqsT1FlG~DAlC6xyC>K5W!fE1QG2|SImkiH* z!}a+DhMEqUWt?RXhM;u*6`=3r^yvG5%(VA{7^>%S31by{qRhpu0gQc|Q&%CnaySX_ zu3S4Mh^(sTUw7Fp3vtkngtlMPC{6TQ>0ESO%6LxK0c5bQHQ$4sbs%7_bdbMTjDd!O zFRC%(yH+WLE9n}L@KW3sF5>H5S(Gy1?L9hOmn?3BOvqzemYM`>z3`XK9qv+%jfaX*bKa!$GOce zb3JhZ97bAK+QV#(vJ1~WBv&3_=Sc25689SY=z>_akw6R+o;&vfaEjK-g& zgV$B`qwl&QA^00)(5BQ};AY)>qIfk1S7tm1gp!*xlAW$5TYKP<;S|RYc^P|_2w8}7 zu@TL%V@pGZ^(W2XdhY|K2IZ9&90s{L|+A-%KzUo<6nl~DaX3wMp$_?Q% z1t^nz%z~5#%Aa^-V0Ff}7G77_yKE%SZf@U6;W(=Tro#XajBFJXn`1kh$;z%9$!MB< zEdPy!7u!~w+_VL<#EnWU$B{#e&E`?~FsUkzbsz3R1t-GT6GE*i#t;pXpVkd2gx%CG zC8Pq*JF7d;!yz9~ZmELTM|s^_Rr|*k#HXh$GmDsE;JN3~)}fk!pQo@w@`A)(DMHUYAR{enQE#kRe9?JNV5DL+uU{7m3nH!I$$WjuKN` z&di+ywXpoWu|TbC(P3&Z768iaH8Jig-{EXuu3CUx#-6XkLD)+a0nRu9V1cDlr_&Ba zj@Ze78o4+UO=FJpfz)HBfYlv9I310CQ^mN!k;9LEj9dCON`qXQ5LCOqoui=%l1aP=TnxG-^Oi;qc|Es%hecG(84!$I+R=vAk)~j z#)kW`QUJsO!Auuzr^bXm0K2ffMlwu4nZ2CV&eX+#3$FWOE+9E2Z}5IyL)G6Bf{2iU z^#WgMB3h{kM&}L1)%2v>V%M5wR>`A@t0{4Js}z;t0QoOfDaj?LBXRk^s$%JFy`hK8Y;9P=wXBAbq;n8pAoE}B`2)r3#70H#t~3zbH5xl5L%aK$Z+ zJoV}T!sr}me3YhjzNEnY>lyDcWwlj7-xQyq0gr5~j z>i#Ec>AmMC>9?S2rFLYXjB1i51FD2ZpA*df7iQI4w~82INm{LeneiSTrW(S=QS6|W+;pQ7h~@fBuda_jkayuwr%^gPFtsK+qP}nwr$(C?Y=#6pJpOv{_mygp(3gx zBP(|9T)8l@XB3pGw={yY0LaP}%!5k9u)3e3VBE(?tBZJcg9tb1xK+N|sHThFc-U|q zHUHX8J>FKu!QlVaF<095IZX}EWx#W;i-fkwHS!#Pv3&+JTya;3j-}1JBBojsIcKEJ z*_nARWzfs$^{0&>3G>*8piiN3g%qh~!SkH~w(a(xHp*A_e5=yCfXQKn$J_IQU`;c} zbw)e~PMKR|yfI?vc|uU}E;y^Rj5Z+dp8V}u6?-am#R+Fql+tMl2Giu}9f@?TPh%e|L2^V?6U8Lx%;u(g%_9s(c=PZOtL1f;4nYAdU*3 z`|)gFN%2xS%w_kFeuU@*?th|foluLyD7%J@cxwzP)fCu$S?g5c@}63qR8oSTV#7R{ z>rU-FFVR;RpoEniZ#90~dyDT=s@0J;bYo`o8J&*4oa3^J8n`-eiY$`0Fq z4zd@ZHeq~;#%Cy1+$4kvZ2bdt13~i;XHV$_ATjX4<`4O9$dIbF6g>n6Igm313mZOr6zskdZ<* zOPg95H-K4@LVV|vM2W|0fXmijhE0C4iJ9$!=+HI^y(UBw68hKsp-?Eqe8Qtp*^RG1 zH+S*6fGYjgnqTWGMDI~@wrRmwNCMWL`Kh_yTKR@8=W+oP02Il4&Y?@E3++jH_wBkD z!I;#cv-qTHEmsz^jOgcWu?Ytk+UJG3F|rl?ZfbCb2gh|LDK=)Ai_P4up_ZMQcW>pHa zNLtoR9eFb1u1a_X*b{x;4D>?>KXa9JpmdNx*4&~~LP&8SPeq?_JS4xwF>}lk-@su) znOsOUBb)>VYXC(~7=cpp8bDR4ciWJNMJxq_aj`>I z2LPy#su5vt-L8#y+<$;9{;JVO0B3o#a1sGJraIE(N{#E&?s-OlD5MdPSl~$?i}QY5 z?1hFj9g}uMOSmz1GTA+Z9yn0xYI?CVQX{#RG8aFtK4HT1zs;?KnsjVZ{U~}CR?H$w z;~{iUOGb3%s>^f#%kv}P=`;kXBElrSuhWiRwvMReg<@pVCv7LF8!bxZV0@=@J#ahs-=MGmGsi%J?b5amNRV zC=$ZIX>&Iul`gSF8FT$-=Y;}`4rUK#02Te`>^WCoE|7i>n_BKab1q4pWhUE~7hwZN zgZ^z(!6_Euv4d?Q(Ci62Oq=r843kRARunoWE%pf8Ko-8tpOF_T@)o#uNnHDDKP@iS zQ&xwqK;AjJb*wWcRC3NUYhwk5BlW~%Dl|iBh3CrXi?S|C`Uy}Sl;YLvKi!7X_q3P| ztROOORP<$&q@yOafItKg={A*)T-Wt-SO|OZMGeeu9xrU8@1-2>j&#ErzRZLTeK2Iez3IG zN|o}I-8z=Z)qB#|`}=TpKPiz3u5^cjCeYuz^&kFc?u*wH3sBqC8pzFAVO){dv+u4i zD4hc<+!$rFBbmqVmZ(l+_`hi9(8uPC9*}pr?e35^no$->)6k?ky+b*W5Pe0TX~9F1 z17upr+PfoPGJM-8ZSzzcA;Do+%3T5M{K8;9e9QNnb}Ivy+QPvlAz(tr*3UZ-ba}^= zoxT}Z*2;&{r!cLDLiS2m0ZMKiyoEkr503|wlRFu__g8YbO!Or<_qWsn&S~&}(apJ} z4#UeqT|LbcrKhu>IJrZfVBIbzB^XvV=dUcATyz{HMdcyoB8*S`gW>v zzRpk?(o2SZlL~#fDhe@&>3tX+gqI1nEM?@B0>bI!cB8qmj2jhGYRA_ zc9u(*nr`E*L&0}TWzCn`({iL%H}YBk^o;T?wAm$)Ns4irlPwULks0Jq3elS4W$0Hl z>Iv0C%PVM*X~!#+?sXZiPN0YR zp3mGK8E{A(yE17wTn0quoqZX8qHA#<@&thf4*NKB51zPH#j)yDMP~utYt9!YZ)CHM zB|%k_hCAv2O1IiYD)d_ic^Hd4E6Yop;-^AM_|&x5;FPZD580j()Q%G=LS{7q@^5mR zG$9#~{r$S7SbtKP+4dHTG(z9{g?dP5?l{9upvNEQpP8mf{Lb%@z8^8JH7|(Wii=_} zrlNr)T{+Gu@~v>V>@^U~P!tk~bZ~?~S$9$((j{**CHsto5BEhlxb)CH*+R^@9Y9yU z9WmWLrI{imvDipZ9zTm+o-+vJO$TT1o4c7~`Qu&u8e-fjUZC5kQ#AQ0LiL}-z5^#^ z!isdVjL$YWZsnoY3jIWZhBbIgV?WgSr@uvhbDjD-62F5D#)J@K7Pp6JrxFO&G-`J1 zxN=$f!MpHV6bI-A`_w!FRb4O+F2?%WLJHh5{xMer6ay{4pG?PKo= zyUNgnZL_tBKF*Wk2QH8#N^IJd=aO>(ZHU7jFMdoyB1u4R&JTc;9rG<$bTiE|EjDzO zbTWL{8T`6mc+6RP6eln>PObqBnZM%#t(FwZ)LiRZStF&9z*+ny;O0~(%vzVK<<8&J^#86zw-1>hW1I8^!CB zqAM9kVNw#Nau8QkJDW!^$b=}6RkP^$6xMYO@qOzL4=RZ=WH8gG%5t7O`*=Gy)}dcP9Oo8TlPA!7i)GbP zVFvhyh>y%nyFYGEa2+Tand7azx#GUXF{xxI$ByJ`+Tr1JKKpeeOM3I0kyh-uwleCsR^l@8Bt>e?Q%V|B$DH zsOns5*L7X#nsGpg`#OrlS5yI2MnG*CTH!Rs!ZQ$h=F$=4TZ$yRe&TuxTQLQ*zBQEr zb)N1D1v5ljsr*7?W>Cst5%_!C`Y}BVud#-~Q9b2(D+pJGpHp6%Zn@_bT+7fD-Vp>p z>^&aNdzs_vJzmFthS|=AuRXg=HHhJ%Jtuz@dsp78TCzo&dW`TbOI5ZMKSG<VY>fxZn6d=MRw3W(cq#ZV@*lCs2RLH|C%P-d197#{{D8>zCHfX252!eemE|o zy;t2bz5hDp zdDqhqZuPPkIlo>XoT-;ny~POjhj*;s40>>L)eu@A@mT|5nTH+3m#f9OpH$4fOLQyT z^C-9*9>(vjQTd_-tulDG&=utR2~Cagw4RB{i-mq4lXdmV9kL_0#F?8!?O-Z3#2Iy) z-dmpR6}B6m%aNU=L{RV*P5!8ytkD)kXrQn>9&QE3r;9$#kUba@WLnt5hjN$L+8F;y zWbc7dW6?BFn@xSHzlIX6nNvT~nvEfFfxgxgVE@4U>Sz*$c`}F^kjrcVBb{cbGn$amiP0nk(K&c+h zw*ShEA_fl7Jkw9gqd{NuVD+pP25P|gO>ydNc>cN?GY4YZ@;h&yHV;L2z4gJnMdeIK zwg&who2^O}sLQP)v7C=t-^~<+Nvd3nH<1})DzKv-9{8Yz0XW=&J1gp8jcWm_|8FeIOJ!>#4NTrf|G?v=39c;IR;gg zR1F{j*aTsjVo0!1S=y^L=%9+tRADfB1#KSihYlVXrJR0fCTBtlQ6P;H0FwXU{Hvv> z46D_!1py-ndvVDb(3cTF z55Jzle~7lLxpY$Iby6Phz0v-RmWz;#uA$OkiJQ*D3c!MtXk}fK;(mT;Ah?j{n3 zhG3jxqI}4uAMBb21e+$lwVsYLt3;qXDB%g6()o6d2ZD6`1sGC&65P_Z1_al}3YH9o z1~Kr~4XR}tn#}Z)&c4&})3{7qvqv>)=Teqp$X`Z!Jt%bwoxg`F zFy2tCjP5#2V_8%$Np(xt9`Ac*?R1BtVCp!n*J1G0vn1lF>@t7+X8c#0Etp+DiHXP^ z;oIblisy+gm(Q@|jvf3>9aCJ5W}g_Cs%2$uHx@@TX1fX|s$L9V-!Ez$yM=6Bl|8j9 zc!q`dmW3cJ147n^2tyYaK~{#~p@&Kc%6F5x$SM4Rz`fwL9jx$smYD!J;dL~LnzcQ* zUmq4C#pQ*PkQ%+YL+A+%{vwtR75M8L?jaUZUXrG1E*thsqoyC=+4(Cp@Df)GwMD`X zK%Bq)1!Uq7??4U6*6NL%VN`@>>PIGhD6H`xR_E;H=6nsDpuw;X%X!H>Zz~IsM%Sc7 zA?!4Kwh^F$?{t}=KoFsE$>cztf2s8c9g@Z?xxTYPlp1L)6JQ7z$Fsj6V9=7qF9xCC zeaw@AE)5u{_^%gYSzaB+)2TPTsp6c0n=^}lH zwbgc0qs(@>$HT~&c@gxnn$o60kvS$6Wr}&BhVTwq{QWgNz3v9I zSb0*;yBf?Z^!?awSyY1gd324CEWu7GV#ofWX3yYw-o=Eefh^ z+;Gs)5C4{O%F~e;eoJc16SR)V4?e5pj!!_g_Rr%REV`6Qp5S80(v&$Zc*d>VeK!)^ zmAI0SDdtPRw_CV=szFA~%%2g}*u9J^jAKv;JSi7yu$&pXOP))r9V}aFa{q&e1x6!@ zYERM0-g{#9eoT6wNVoIN?XZ$ThkkepDPz}<#6IskR>1*^eaaYc5eU_~Bc z;!DP&hu!%hL-U5ta6K<}`$=|2k38lyXK+ycZ4hG(=q| zJCg9|SIzkXNXb`?Hl=$cUG3{hy(n(pbenk0{M5+FW#l`5++pmuDH1 zxQ9eIXEwv_Q@lZKfrx*i**3klg?gAN`zTKY&S*FlR$zedi;gLSj~KU8ZT;0R>+-sZ^Mk2W@Zu7m&l4Y1($+9bV1V>{U*z(+Mxf{iS&xq zCbNfC-(*kuIqiX%EO7Cbk+lWwJHw}qbkqhKiY1|B%>AR zpzLIPa=V|KNn3lQU^6`{a*Y~z)PbH3d=Fav+s#Qvrc)s%6cd8 z@H8)yPn>nByD*?HnOdWwJNeBF5E%{Zg54?O_9|>usZ%(po4ej=R5}S-`FPa+07?2kr$rrxcsHTn3}^wIPTJD2W=XYYKs`98xKO| z)Oc?LkMDPORr79nB8SKjHd;*IX{~`c(FZO&Nc3sY9_7b6nxCy9KJ(Sgc9h_Jdg1Hc2@?yUl+rr*CIk zGL7+aJdcb=rB~R7A)9ZXcH%NiXbL0jgx%Eys;T_3rPy4`w>mWUd^IIcBdPvEct$0r z<{0>#n$RSv{2qL!$wU;Mi9nZsSu%XcY>+4*Wcoy{QPHL%(0F!*$jkHG5;1j)ArX~AqRMh-?<+I{!jm-Ty``|3mhSYrJotmefTZvZU;YIqlbJn%OJl0hDZ8Q8dy8j)MUrW2y|is8~1>x+04 z6d{RkYhvMB4P7;*ayk$?K!92nRIQ!qf%Y}vxVBj*1sI}hmtFF26DYM&2|%{};r|&! zFnL11FV#ZHL$u`2HUMSF6Im`=FrM0O5@1LZgZeDybt~#e3$!4L#9iZRKu;zPN=VKm zQeuw1wF%{7uf0;+^&rS}h>Za*>(B1FW&y20T)(RzaplL?3NY+P;d~xxV@PCHJx0P3 zG4P2NT^ODYgUdixcTorJ+S3VCXpG?y4Xs;YjP#;|kasR`EQ>A-0U4^^?dy3Hvc^4=zc#;_yGQQLbcCwx6=tI0Dvjl|LGTM?PR5IWdCavs^sS2Xk_*O z=2bVPPFZh=A&lI3L-md3f$obqr?=jj1ACTMi=`NhB(I;=(LcWTp zQ&0(A zC4>#31-YKtNrT=@#e-ev!sqTH8rN5r=Od?q4(F)o84e+b+){5GJalP7!h$#4{>m$dJ6HZdYvl&UL&*7X#ED|&%JwsgINJKdx zxUgma(&{l^I-$<%0WJTFPS!dC^67PSgJlR!b|4ivBqkWk=U zz>xq90a*e#6m$@5|JE;AC8(A@^o+8&BrW@&d-54)@kyGFo_pLG)dDB41{ynvPfR10 zDM%xiDVHgjDVZtkEX}OtEC;VU4t!9y)I>hLlnF_^XYE*hA%-EKK> z%0flbYeH#{sxhn#kTI?dt_-jY@+4R)S}I#A96bfr3-}r9Eaa)vtkW#)tn4gyu4e8= zu7ke{=o<8PJpIMZRY1eSRm027j9d&~r>EO9-^;%lF7B^LA|Q88sPjubPi%{HSYD;3#V^Z36mYECJCU(}p({=%z0#r}=q5Ulw3 z^W|H_lpI~>=wAetT&^}>t2}_zr-&<^*=8-PgXfT$&T5Kex|~-gyx?05IR(Z-Yq~yr zxCu`v_za#`7bON1MS{g`dYNArGR%hsZiYbja(R`L@wp>^`BpHwvSp(KoeYQSts4Z(Cj*(u4rldA=*dA;`o#v!AbHpBS zLX@UL?O5xzmMB`1bDH`W8tgQdOW?FgUC^J_Jnl4@rgY%AA=#UG7H6zjSyUjmo_ngEM%Fc=AJ{bAEfLa8WJCmoPWb0@PV=H5ewX3$fx@$|9Koo5UWeQ6Hr~zIM%<7vifGt3q%Oi8=zF5h+XA$+TmC>J@6K zw3V&STp4BMQ=bQ=TP$*>$qR^wDkgAhwQ#?ua@)I=E?6k8^K;9p4sy;&5=}_;0Z;lqMR?lv+`p6Ltv6|GEXMnGlKft+EqUZ8f_vG@&Tc<|tr0ax zN5QZL8oA?9WH)9%)+LJKo84Xupdjw{@YjC(D}KE60ZaWzYm>YJ#)cpP%A*M|(9HUu<^OvTxx!kD-WR*|>dr^EDy&@0 z<@5AIp@di9)5DJ+8HM591z@}D3ssLwsu>G8l2+Ve;{$W9y;Fpm=S!Su+){2UZ*PzO zz84s!7<2B3S}$jKVlTja12SM}SG7YD`Ns+%>|^-v7K3)tW~m^K`yVn}{u1`T=Bx@e z{HSPl_yh?(VVc!8%=7BUm*U)u>St~$WeG(sY!DEq~#j=-4)n}>6@b9#OFYi zusM~9mn1f%^Ob;{c5v3fUTppp&dlBUfFwOR3Wj;Q>?gSM$u*vvEq6FHd%JST*`G^J zcO*=Yp$(2WFp6~3ZyjRC;_v1}#)=XeBMlW|EDiW8WGJL4)X=&sNaP^>X@CL%9>&w^ zTHocI0EI!#>4k0S)N2Zuq%J0D!n(v@+lv781*uInj#f}R>CH2ao1?V2rKGI$Wg&o5 z13>d7)q`A}j{)59wd#e_1FwZ%Z8D#mnDE4Z!UG7YJYH23l+H{(MoYCUTL)wU01^P| zcE&(pgpMCPJc^d!?r>ClB84WMmM5@d9v!g0AV2|bO zAYCx`@z>(ztn=DxUG0rvX*(jPL6F*K&)~wx&-x(3Fj`j8YL?P@n<&N)|84*jasuH9 z80OZwu!NV^x2Q!90K6CU*0pA~T0@;w-A+iQu~{9LR|-H{JRJbe7kc+hAR#TH+c}bg zy8b?}(y~eom*gBk0X&3@VNoy-4uTg~glUbHfTxF2tqm@!W|^ivLWPoR2qt46x&6Qc z>Xy>lT|`~`W&DAS&i)!^m!%tB41QHgE8m86;u37Ub!BqgFv?$>ehSsSvjM96;s*O1 zzDumVKSotmy#`3SquM?Rc{!+MQyI3#=*^Z~Q>?ak*%%>TNhC%gK$_8fA;eaW_dHF? zPPV5~Z-4>d!U~OZ^}24B3QXPpHj=iJe=cCBX{U*P&Y;P==+kcqC`>XCZu`}_k>HRBs9CvGM{^`jQ!LpW(qH3-+8M=(6Uq7SD74U-Kl?f z*{R=M8kpu<qLC*VHUWmb6mnD`R${sX$mv~C$EM@-7X*?^JsN+uDr&EBDlOj=_oW|!A zL@^Jrd6Ef#)%_&7ugSD08aRKIMS(r8T3VEa04{^z4GYOfcZk^O*&D1}Mwz;um>PKy znec&8^6-RARLU9_Ju{n*vDIg4o0A+yPckm-Jb*hXnC$r~Ux1Q1_xQqTJ{i*jZD7B#%hmJ134*oare{bNMhzAA!0RaHy z!2O?|-nRejek0gD;!KfsgLuGRD9~RG*vi@g&Yn5tM@twSCdAq{GW4THd<qAdyhogRLNjcUy1DB>}@%*@pR#IGQwIe?cjKI zI!9JgX6iioboubXb0&sQaNtrwcCh^;WN(v*TqpcnXmH5r*!tL;ci~BQy+AYHd}D-r zS@8p9I{OJv7!HR*RK@I`qB*(@_;d}r;YXA$(~R+EREv2rdgx2+2m{Fv<_9LjYjPymaiJoT#Q~AALBf zuKoR=|L|%41H=yu0Kn20008m--Z$7+DI zx@b*=;G7Pc91VB473TqM0*rUTp9Sy?a!Po~D?{RpSgrlpjXK;_0E{|LG4L#gpo7$G|2Ka!Hr^O%D&$%jYCb8ivJRjoC8oWhn`;=5UXTG1e9km0U0dU_e-vY&nY z&vxDVnwporYir#5y1;dpDAOL0z3H3}Y*V?f5j|FQb3?;Z`BA2FBoQf(Endjbc)B(C zvp9~+lTLVIssgHN^@Ew8Z+c7s;UCjTo>n@}c*L83B;B+Xt#VjpXg2kDHb<^LgE98? zrSQ>=SaFk6v6B!^ehG*NBi zD``Je?qAToWAAKhlT!cw;X#V0FXjJBZ5uJ}H=?Dmq`;xjq8OHU-4_g-Py90#iI-+> zSRwhEjEhBB5O-39VDt!dCRBrC-HY&4c9%5E zi%k{~!L+L$AT(eIi;RV4p*CBqJ`fzd0Qy0YHJLzLAET&7)~Z20yS7wrzAdjV&gkk!eGEYszc_XereQ@GN41}5e2$)LQKWr z(~WUIe^@jmosj}ZudNeJTug6Mg?2MjnO;i}Bc`%Pwwf_0<-i&d6^ch$A>+=XZdCW8 zX0%W+MHSKy;0kDT?EFfUT-m5x`Sb}pzQZ`geh4LfG&Oq+ZPkBpsm&urAMGOuTu7FO7oPf^;T{4#Hh9lIxB4orwZ zB0%^Z^(V|%=oYy@`~M%+NMq1zN{W#z*~Gcd9-42Ld;0{{$^tL3MHu6nY3d>v5hX<7 z<&hu5xDLT(eKY6|Kv;@&*fFGVd`gOSS&BqUu~RbR8Ca^=`SC7&NlNmJNrA+5nlpC- zVoKJ?>`WY1dD;40xF#dNk2ql=R#y5kshpdIpC0MW>BsGl>~RXwm$kqxiz-Ml@dFJjokjxaJ3N#1zJjm6*RQ>cPl^^>GLek$ zb!6u%+}c+}I^L@}C0pd?tB9jM>m$pDm2eE%$a=D8lit~yWwANK(>OY%7v-&o<|iOW z5H3sq@Qs#9NQ`CW9q87qa&GZ8D&a+iDjS#iER++f{!pNhp`f9#p}?VBi&KQe8zpT) zO>IjpBasOkySBo>C++=X;t>h%uTrLR*BU#3!c)C&)hAEl0*7j8a#zhe5qqw?+`4tK zZ)Pw%1bRZ&K+zy;l=&}+A=gNFA~+eC7F>g_QEPyzDISv;S%tKEx1TgH7&--kicU-D zwAB_e@35aV_efyEFBzIvb=v-4bOLJ4FN(pK&g#RExsoTIKV~7x8M2{HF(gL}G_vY;Z?nUlkA{f^HCl|d zb)`ISEQKX=Ndwpu>k<2NQOyq+_XbzdWcK7?#Sdn{`pXV=wuJ%J&BcO8sEXCpq7LP-1}v^3+vNG>N2v7h8>%Qc<#THV zqWLJvsxlSkkXw6^YPXl>D!5x&QJ2;S_Vn$m)JSrhLL^R_Evu6AsVov>~`j@T>Zj`Y^SWL@Ghr)wjp?ME~l)*ST0SZmT3cv zel%Gw;4BD&ba7vWIkwG?&l1%fu}rHzge}eM^|$KDpS!40VgoE#ynnztE_vWxSL#nV zhp#AS+xA1ZPnL)k#aOvQ_T=7H`ry3$u0>Ee;7xDzD0qmYlnWk0GxR8DIlCf8PK=_y zZ9z|mfWj03;h0!Jxl%uB08Cmx3g~Tp9u?JsEzHz*y@9E0Z384xx&G*ytqcGL`qDF0 z3jj`2zdOALf5M*CA!QyJe&<~>){~RsRnf7(f08&Ck<~xEg)Bf>Rca5RVl7lav$a_ZirXzT{rP)UNsWT+)RWQ zF+=rA=Db(-vVD6i^em;tM4btWit&5O$1OJ{J1UgG8xWM@e>mMo5}>+|&Hw6v(!HV( z9Bb9O7C&QhNCymEB&3(Zy+=920`=FHot07H%~Ewh5nm??vD1NaL^CNgHb!RLxbm4* zV$wWX*oBtS%!rxh%qD?fXWYv7`2#2y`n!ZQTpuV?wULH63XBiS>KN<)po0uS)JzPj zvTIjI7N~1J(e$|oY_Bt^H3u{SRyyPNYbbsUAE7X&Z{;zlH^Y=}K?!!M*Z&Iac`6sd zAQ9UJ3X3Yy@mPBc2WycqyVQ; z`pUq-|D-DVIt+Ex1eY3?_Xxf(8n6>1e+zZZL!H>_-$MR;kY!QdbIXYh&c69dDd8D-H~RWW$qjYa zVJvK_KPJ9;5sU3Pz$e%5J0!Zb@_6Po`R>+AXw z_6Yzl-kI#t!zUmyrRig z(`xgVm1|?6Pa!9n)smmW(Tw2F@#K&Jl}d-aidrl&MxRT|6(fHEC9?Tf5z*sT#i61_)|TA;@x7@67qvvY7v2^G`wt@4p? z2?h}9S_#2Gbig;#Md^=6$e_YO)qTXE79czdp%j1tfy7?jl|B`=N@$zGz@Q~y)?>c- zp{^*_GYE@>T(PJ%6FK}EL8u7^ts7WZ@^A9K0mXEn95)rg_G&015@N*kDH+ud1l$!e z92T9rwH#)n5^#!0C2$Jgn&aLZLXpU>wd-#r`I~s8oS+=gG7bYQEe;T-4qeZqU)=V| zQnqlWc1pg;Fe)&7xmEIj(|Ace=8igc9j(iwgzSHFnY9Y~Z&KST08FCFHCefA`kth= zZ3eRLZU&slyKn9YT0oL*6y6RtVr+i?N9I>3TI@sUFD8qN3;;m&f9$Pn931~y3fmYO z{YN%dNotxl>k=s5H#GtZ_yXb71`xZQ1Ut1+BLN4DsnWAlTlrg3TaD%!-H!)7H?EUL zz2sY0!blHOds@eyC;OkC3+7v%9&h(Y3)eYY4=*Ku*k7u0kP=Q~wpMKL`T27IAiwVJ zKksH{@SP(T=B945-ljX-cqMsyJ|Dbanz-CDZoEA!2d_1^s##B)x3?+Eyl6ciR<7M% zp3Xj+!r=exxSU^fd$!uB8^265&=y#sdT)495s{Pja_#kU1({( z-oIr;jwZlKYyW9S9jTGw_&zuY$?5u9^CGXhb+%c>R2BF7qEHpb9tkZ5n~8jSrcnBK zQMI^$X|bP=)B-NNvD}*vgq?mu(q1V)VcyzWT&R5#x_wq!;px2fF7Pt*B*_XG7EFRg zd31F>%u-3qmi*6#J1N%5OhVhtOLWcYf^$U}-qjZF|Hja7WJ>)|XXD zm)YOIs;2XAIpdRyrCFu^nWWsDkn+j_jv6@G5y6hDR$C0MRyeJeArr9sSn&|*L&a7n*Hk$NCthhEQG02w|920%9Pa2A1d z0;AnsKvxJle5PBR&cVok%_7GH(6OSU81e))r&qG9ubXL*kba`N_xoKk-FeoHVHxeL|n0iR{A z9DFU%x^Q5_QEqO(w1;bw4BUs6uBA7WcrUih(zH6v=;p2qA!yW)fu*1NDlgfmwCpYU z5z76bwK2b_wJo;p#GiJ|!18>N0=$0z@@!k3KN21bP3}omsud(OWgFp&NPqpt*yeED z6y(|v<3RD_m^q&*VHt@Pj&w4=jr;ZOK?ckJw9>uM+pu{P$U;-KF{TBT>F=|=%CeUj z(&reP3`7AY#ddK*mboT`CN90X6o%vJE5_?;Dv@EdG1j>oaM3xJuof~erw#76_q~W` zbeLcGc{Uzlv1~fC6~bvz9t``Pmy|L4O|Prp42LS8_4k}My% zB|?K5m8Mv#NQ*Sn29rl1uFP0uT_7QusI-T6n5>w1B5lg9TYqABe!Px7U4fF70BbHc zJsG5=)MH_$tQ|{hfw+=i;H(KZ>}{kLJyz~x!(Gz@pA^E!&?){~-TpI!JneXGi~j#I zEc`;vbFK5kH_L+Ra#*+0Lrt@0usK}KK1;J&FOn4;{IOn-Vsll1xOvFzlsqjON=+(b ziDD3o6E5zPtM zm|uUE@51zi6A7zfFF-?(2El4|CfR}ldMV|e#Vo_T|IIP4Ch*Uy*;gJDQ?s7B3xkqF zgfRG68a{od+#nww<0k{lL`DN!Umn69jVAxf`RsA1_^htN{_p5~XYFf|ASD36{vZGV z+5bKx_D04=zxcete*n!d@^08~h$Y{AplVN#{zm%<_@c+Dl-1W8a;K|BPdLYCt*`5| z`jV{?%|@MpNhm2X(|^!@)Yg1Ja`QKzI0mqH2uiUPktEgA`sux#IrKb@?R*EtinmWb zBpS(}uy{R2e!^z=Enq68OV_yr!~_@Z*2%2WSH$4qdeGK9mDafnC#nykc;A<}SPtJc znUFxN3+8;D#kpPFJRgZ0kfr7im1vSQ>K$L8-wrS%HTzpPpt23nL2k@&jm)(3&Rafd z(B2=aCbK~B_>2)ftS|g=k+&Q~L1tXY;O>Ohs9GKd-gFdOn7?#aK)VYZoeLeoiJe<@ zEm6kVNktK@&UyRxoRzRQ|g=Um%%U%Rj>r1(-8)85wE@OHqAYWSb88cO& zIwsdTq11N0qxkr~-+$zA9KcxadqtY-7*-8HK^7D9gt0)bmh4B#sSAuuoRk=c&UNV| z_>rJvV-Bfe`vLO=t{qq_b+IRS^&MN zN~}=)HR3#4j|g#8WQ45<%(9|kLSRhu^h#O5bO@||C?G9D~H!l!%5Z(bhr9Iz{u znjf_>yN}09a(0#`yy^8r9^xx&i|}|i@8@_=aiAJ;rpCoyR6{v>w8;H`eM1hxe;+qO) z01t~WF{?L4<@^^yG&tQD^p|32c>i%Vb9SnY4-%@|j#4my`C!)D3vdd?3^HTzLhA!3 zxOEvn1;>EpwURM79H2q_kk(}`(c$?9kzt(HtHe)~5u8Ypw`Wj>MIor>#Z**yK;-CF zAa=A=QD7Ste}mGetDE#7MZ^vTrHfYI{%mh?5YdoY!TZL=T$c7y7Cu!BA0E~Iyc+$p z;n}*d0dMpZ=G#Xb3o#$!0nYAi!mt2Muy*nuKa=P4BIM)SipVZam+Z4tNSQ4ddRF(3 z>!^SMn@%VzhE0wVf3nAnrv_8TNrG2nb2SO&NbB1EjSssXSm1kiFqn-V6EM$<;I{4L z@yNKo-qv@$?YRp;Q(8yRW0K@x=*AU%)>DVo`u*Xk5)I}aCN=7Q&@E$E)rI!JK@*3T zG6;*PGi))`U=sxUv!sA`$ghy!}?k&jc>43ndxEIv+ZA|o~yhlhk=sg3-4^wAT zT?Tp=3SW%}w=kGUQ(!6#Qi(>Izmtvur}JDs7q0&wW9JYf3J_({wr$%se%rQf+qP}n zwr$(~ZQJgipV`eMgKe!VuTnSfoIAODo*A` z1~wdJ46njkgrz=%+|5$pEii_%`kb-qT#%*6@(2k86kmT5d2YF+V^D+HHyHeJ8UfxP zOm-SMk(>iS&4is}1E79BSV}h;JT&XR4GCKNV)R%e>O|QYLxxZe8CKuSp8Pk+un1T! z{PP4{`<1|up&$gA?^-jh09f}qH5;Gp43F{xtb8@)?fg+%@w45-yL+||heY8u3cLCa zPCw%fbt&Ea$(cKWX$5?OsMq}zthR@|%<2toyB$fJ(U@cUp#K(<*82_kSA-JUOBMAR zjQNC{^~+PF<8Ce(0KrI!{;4jv52IHlophGzA*81XS&Mf6Z|5plQK^^cY(L1aMrAORENHpw$fzQX(Er1eAlzHI+N+jS>bY*K?X&}j)%tEu&L79zq|9jOxZ zKayB60{@aogZr}$(ahrE=%DOzD(be@q-q6^+Xesi?PXyvPWv7rnJnWm_#DT|#!d9w z5tg0dn;uTx)@~oxv>Cq@?Aw!ix0Y3Y6_&SoEaAda{SWOS;3QT0{2ocNKES*RMa-=d z=Q-XxChPX32rM{WI5h{_T?(ucl|3-%8#83iUVu>n7m>7S%xEoIXcMEB-x>OwVt|kFrf>j< zxhG2NUn)Ao+^jrysF=GguF|RI`8%a`%ja%x%npI-7UHqiTIf*@446PL$V$OmZz9M$ zHg{%qOOkH$^ky$2nK#203i@%05;GaB&MjS9G(+NH!tH$N4pil`RXUvl5d$o1pa~DA z(L#R$4U6D@d%t5=g3mIXSKym6qEhlHS;PlpS~_?0oGD6V^$LbY3>;P=F^QXVNJv3$ z@4+#c>0aG1@32avW3Kf2wmHw>nj&z;jT}v>mrRTBu_L4fnWwhs+>JBSe9+)l*ys`d zO~TMDh1|m5V?_I0qBje`NTo#OS@;8{Uf)|@p&CGMHOnFGZ*Za0z17-huvl#xO_w_T z*I975ALtCJ6tXj+^wb>0_DZ%x|B&XOa67t`N9mo_A3<^f_P8g)$wtTq*heU`_0i|8 zQ1<~UR+Bb19EIk)^5CK{M3B9xlc%@J z)OV~}Y@9|`^tSz%GfQHdP&WC!cu4`xrM&+VylIgM$Y9g~0)?auA*j9A%T{fi*FMsQ zNhG3oY=K^^W|lWiKJK>1=YxA5m*0lfUrC1{ua=N3VOktPk$H<`;@ItRR@@sKWX#@De{bUb1IG87~0OU zNMuD)W8q`BAcE*64LA^6xAEFFjGzFfM$e)e#kTj;Xj!TIqG?N;gQ&~&_Y_DPG>E4u zJW8V|2TY;Sj~w!YnIv8#gx&1l`wncV!|4rZv~!*BRJ9P&*T@CEeFF;BxxBupTJ|2y zN=@G+I!Q53U)>}X$|Vijp2gkm5ECDij)ty&CGII$f(*R}KZre_ zfx9VRxms^}D+JM+k#20gFwy<fLrFUtFzidM0r#<$=;qH&qw7>oi7t2%ILhNU}-0IdML5EBSo20E%ILV^e9IJZX zz-8>GghyG4wngIq)@|_sJ!4~dr!#!EE!u_~PW@yJPVlOKJZ~f)wZEv$)pose@`dMd zTi&I2N%P8N|3PkI%;uxk@_YzBh4yO_lrDjb9cKSN{PPj4A?szSI1x7Bq;S>$cwYnO zO(1UCMR0z*c!^((5p>9)pomd1hT&JF(L;F(1e2uiWJA@Ndzvs6h#~(3lAT~k2WcM! z2u1In&PLc&PT-^~t>2Pf<$frtimr6NnyXSrZ$$k1DNwX!nG>(Kmg-c|HP76FcP1KI zXh~#APoFkF*loc7@ba7wz-7_X$!OXA`ucb>H`%6FH|9{|#&Cw45Uv)`G9Xh?3UFa? zAde-JbNA%7`2bJ)0|lb#kr3XdLaRTjqL3L%quP?rKEA!3?LD#tQ3zojw)qhXX?%T* zz=CZjd1I3}4AIQx6wE18TeTRa0Vkg5z_y$f@Vr?SS*rbVl!#&$!qUANvC%q=bd!EuIur4Qcb z)YFT7kQ;Fv%SPNBvx)oCTiX>{13|#nhJ^clSSJIqD=WIZytBAg_s`skd7S$uMDNdj z;bC~!vYzqCGGQ(_raY#+(K8@eK=4r!{e9Q2Apvd1m8k>vYOir1DSPJK*`><>ffve? z7_!w3I~cZsuMPeBa~-z1yK~Q8zS1TqI{`j9aoH&FlVcl4kB z6L~ta6x7d|v)sSI!;q_*1|&ME(~S3o7s{mEg}RpCD^#zjv1!UN(nwvl#7UIrX3=Hx z7=t2nr|1r(>SdmW8OX=x4NW$>8G5lV7ipvxbHB1GmZbn_TK6QGCp2#R^(E-Tf>Fki zv_ZuMXwzLk>v?yPa_kQboO0m`1pJlk?pf291}Uko98loH%80XjNxFRtote*$&H^dM z4e-ildj6%$AhQCY)Cxs2S@O>76h($XJcQIrp_ z0X40_3Yx3GQ`{i>Kc6T|P#?|M!8bZXLD!wzR3Hluwky5}p1(Bpe0yE^20g-^DrWN? z^l=`DA~(2wn__*YPBh*%^h||R6?mpBCD3n5yEOmspGRu7@`y44zeuXnL0?&oOh6xdHg^~N`RQM^y0!j>Bu-+DS zHtanQ>e}u3NZ;zdc#|_zJsG!|FaR^({mhi13#!T-Y?;83OfbPa2CiUsx95!GD5>Nf zL&{CBxCwQefSF$=%E$E`XA*IP0${eV>^7NZS)HtIAD{tc2cVSHt#jEs0;uJoUqwM~ztST`~- z-`+*a$*+V`_4W%wrQ+>^eV<; zXDF!fX==lJaiJT*$j&z*!!Xm^=~)`FZ4YbO44VV_8(Cy^y+S3T71P2kHMSSx55ySz z?5VuIQ`VsjeGPbp*9lDE2}rlw^$1*&zr2mhz9tva?=FU}vH^GWAV!8Jj$mw6ltCCc zI*1=D!uE(dJQc+iF)+@9tyK|9)q|N_v1?u9IFn;Esv*)F<^2S6dLRO%~a80ziK-Xw5L3qQlCnIHwIeLEs=oE7dIWPx4 z^f&w-cY22Y8aLI{r|iaR49FLtT1dPrlj<0(L@jz)vD>XrELnHe?nh;zJBoTA}zwV{nT z;b6-UySfs$sQd^pB{L^Vkm8GhZ5h6+YDonapJv6{7JMdr#;Uyad|-Ngbkue^98n1B zp&E-tZ)URIh$)rc&VJ4)OY4u`Bi;)YR;ib#9K;n~p>HQ7O%`nc$f%6RtJ zo+n^?I#top6m-p{$VFw1z;`rcXM#+3ywONe*A#rPBQoa~G=DpM$?Lqp&qOuOYj2xG z%LL-u%$ccSDjp^FbCW@_I$?-D@7eSM#M1$TY}y8%H5ec=|3ao%MRZxGC78P0K%-K1 z)XG;HGLm}^aUdyffZKas*0Gv(oZuqwX0BH(Gq**kj6A4y32f;ewO;Y%m8(}hD}#lp z4c8r=9?N)kzs4Zt5K)fjndGDRa+6H^qMk~j;vNua?=>dZxP&nfy^GmI|JN2)Z|Gq*o( zalNbj>^5cd>{Hk~m%(Y+TqjVA@b2R?fcGWoP@L%G*iB!pWMjt!n(had*?G#BkILL# zIrruG*bONW;Ak__##SgC<~btSl1|FMoFXmNYf0m+)K;LhzkTgh*A_SugS)S4>e2cb zlo3W@@ka=5hF~YSp;`Uas+yD+>oNxsMrPkY$i=ujub*kJQni(vu2=ImLb@0=V2y+g zU0XXVDl2o3%jVgS7a?p<$(%&cYE1b~>TmxHIZ)WlNJ3WpSFwKcw7XJ@v=Ot4OXgL> zj4&<9!nHMl$Z=iG*du#b`r1PXlU~S>ET+6-_s*Bdapvh%Xb1bmc;F5x+;}@fY~pi8 zMR6Jc1?#jW^!B~Nwq$DI6HUR9PKRB{>!J#C@XR>oCi8s|#99nhu`E+2v&r=n*J2it z6{)@EG2Kx)W6*q=*PdM+T2kbQ5=w(KdW<1FIKF9ZN7R@iA;(5#QYNO%=9w9V7)QePlrrCH%GPpyLQ9UMyd zI_1ZJyr<>Etbrj>5y!#f?k%`fov1VDjXWEst?;zbx(ewp<})FQ#FrY=VCY}A1US$h z^sA%IP^FZyv>bEAf6Bw^I||@%dtowd((4!E5(8)|I1-r<5;ciH2TAah^$`gb3<)#N z&ox5R0?^okINcpEy>|EE9`God^!1dMz-n*=_pt4iAB}FRMwrJuF%I8SLyW>!;*)Xr z>1aXJe-dsG^)Zz?B(8h>!iHmDknDEoo{4&NW1mjFT%efqZp@>kXp^Ou7BGh$i(3>Z zx%fq<)@f5W_JDHrxd3O!6XVH06`pIRqjkB%o6Pl6nXwPwExY}kuUT;`2Q>~V~3`xDPw-1Jg`$@xHI^&~RZ zt0_Vp)~V_y+xBoF<20}S1&(-LDXQp`qxtYQA~*u+4e92mg|{KlJ?x#CP^ry>_ezdy zA@)7pZIiHU(5Q;Gh}E81OG;zi+Q2h|Veyj-kl%7YLkIfn@%ii}q&Y`NL^dGUP{A)S z$0N;EjDndw+X3nfgFC=;Dc!=ATw}BY7R^NH2Mbsg1}hcw1`*;_1p3F$qe&o)QazcT zl2v9m*3$$m-j2X^r$r7p$}9=t#A`mzOq&&^q61NiRTL=b#S79(Rjku=aT_pEsm3hV zeTLp3^_+VdNVk71VFUYxVZkyHKFl&2wvM z2jh}jiLK)1QFLEjX|@D^LtSN+umc{mfE)<*1QFggSw?lq-K}IvWp$+J%8Z|?mkUP>Xg z9X=||n`$~Z6B_glm;G_mt07H{*XLRF#wN{vF&Z)3iENaw^}HQ0*C#jsbm(Q$H@OuX zH>X6b+AP=y)||VYp)a6-rwElt&0_4uQAm?b8J3~l%`;gA#8VlGqn_UGr0d@5`@j_& zw?d&MHadT(?3px1S>Pe<@GTab>Cklk(Si7K56>IxmMe$#yiw6*;`QNK!3PS8C!H%lQ5X_e!B1Jc?eUu)E~ zw#}>a>id>-@7VQ7)_172^mg|HP0B;byPxRSDzcEo@-@`+Za_c{7M})phbgYJqcqXD z*BFNHlue^B1L0|RrT~5SO}^Q^gRW^=#}1AWAe>_BT)a8wDXfRlx{wgt9O*}Jg+nB; ztMj#q!0Gabbn1xGF~$Wnu#zcGCn3nFK8GDFfHyXr zi}`Abk@O}=Zdsb9R3YOGrj?|s$b9j|1n0<6(JmtR@*$gj1(Y-=!x#=gxiL%W(o5QH zPO6feRWm1OPezHJP#gJhICl0t0=d*_Z2^u(6C5O%q>^C7;sbqE7JTqB$}>_=D`(?H z9Ip>lgIpm}b!kjZSU4m0m|v1GHBUQo-BA&&N3txkE~)}$`4eNKgmVN#rT-qg0HTFTh>JvdK%gVpdf=L6 zqenhOr;n^%YxtO6E-)UzCF{`p;-GBUbF+PxOwXmWc;)n$97tNUr^ z=DKn9!Yu;(-30gYac}$mnYtyE@0LMs1)0?eBeB39~4Nwm1_d=tj$nzmVTB?K2fLviKM$br9EMT)b z(Ru(*fvi+;vt}P;L^W;RL2)_S{UU-Ibp|pFKdglti(M`Kxq*!q`Dz+a0!b^$3tUeI zS8nWfz;y~oD(~GEdR0@RP6~s|rin1JRIedCAsos9B=`%pM@{N*GCP$W@5HDC+$Q|A z4mAnyvJb4BnaEC?ORh;Rd(Q|JKB2?oo(%itRXTo9jNuaqmT)Q%dcvmqmY@04rT+%^ zH5}sj9)8RPO0hDTDiX&o_w~0iLN^;N4Cqf>a!GtRC#D8$(CU{T`@Q{pjq~98mv~o) z1l$f%c`NFh;_vvGwUo6XN5*7c@Z#cikb;Aaa4hLT|Qof#%tCeo7qU4{rK z7Jv#feO=&7c>9M7f|qvYCA)-={;A*ZyB%O;u8bEVd_hjc7eYqbu+Vr7^f2MaYS4sx z3|*8f-eEypRQLOr8=kZhi~YEe{|@Ow=<~lWuM2w-O`hWe62ksLtm1e*9Jz2PsHOEU zkuHCeit7SRGl0*P3~L}brHIh|f&5!=p)ea!+iAG4hu+HP`D_J%*0^Kp_(BW01RFWC z!~U~=6iT_aj1#m(wYnWBg1`z@9CrZUP#%)4NGr|DdV?!VVLW8sTUYN?hY4#HFzO6R zwhvD!EIM6V+*-FlD)@qBK`?5Z*qB1Yzh1|VXSaq2iXF$h)S@{0| z)zB9A@WzxK8^brXfD*ivx$8PCnJG%b^-jq&XnOW*D!)~l511nrTKOT{^Va)7iq$ip5|jNv>tOb^%yPtk9A+~#k?Nc&mpmVZVHHF1S?(Rpsg%|8)<8nR)2CZyxK3n4m(m`?1ZXoV51*Fq#|1YbJp zM^~7>nZ-d+C$^}~NWh)8J$$D2$FAL8#cWf{GoRx>WNOW%bm35ic77|XK1agVAG5+v z2MyVf26dl{`;Nhl3HrM{0|8-oySefY@VeBd7?kBc=nFWtyf&M2RCKMFB)A^p^?l+h- zZ;t{-A*6DWZAp2fxPzo^NcWOLEj?46EFp*R^#D)w(Ec*xW^1qzY-Cni zBmd1Z*vaIsou_F%?5_P$X}L|7FzWUodYtu(i?!z-edT7rh)~gaG*n?RHw!o%Nu?`v zPH%E*Wxu1OUCr=r`F@--N+@?KOwVF2gaZ#~5g$9oc2S592dIA!7rg$KAGgT2A7zZ6 z$ZqC!HmokaVv@yaOm`l8Trz0csN)S6=bBu{BJRDbJb8Lfv;Ik_m)z=^kZg<-?6jU= z`rwo9K2v1}ocA@~=QE7P|Fl;vI&Vnf3FN8;5%voy%P#F5n&mS#UJR;d;^3HwRIUK6 zZ7LJKlU+*@$Bm$12;UPY$P7n)(8%we&!^`4UPe4Za>X6?`t5Txb^BL`vYIc0AxjR| zkDpu@FWv87-J!k1d>hV<#?Pw&{`3(ibicf12T9n1c7H`i2zmy6F5X)R;3Ls*_)m77 zwWKcrG%Imk^4?*FGX`iw$kHQ47oKGyp_CJ6+n?j30J^@OKo-qS`SqkRk7rkn&I$fjh#>!bZ)rWXzq51ay{Y+9eRQ0S6e^u z6|(*nWPeNhV_1`1b!pt@mT9ykVG5q4ViVgeC#~sr50;NK;JcY&fq?iL|6ymeBxObNUD6;@5DQl6qB35mpTz39=8x=Kw&LSCiv9vQK@LN+9>(? z^l6wlG-ewZaI|L<#JOjsysi+aoQEF+0%bc_&sYW7{zkPD?J5SIH&ZH=G74XqU^fAB zg!g*Q&h_Hf6pNc(B4b5e|KMpSwx}A1kg?UBz^|D;Bik4wRfj{`Vt>9K=lmi1DZ6dz ziW~pYV%bp;Cm2vNL`tgw`XroEK1zXvD;D~{;q54K%ZDpa{NXvwZZaO|F^d(PF#W(y z4*$Hl&$R7O==6N=h0W+$a2oyki-~V9wun?TwBRN$k_zskmzetQYvBfeDPZiX{r4** zN+IW&5D{fd5*b~hHzH@s4;e&?5}zWjg|flAHaY0+orA|pIcJy~&uZ1*~({23?d$jRTlZV9kH-1v1lP$&1T0= zpV?Tu<@&rDDoav4e;PXcd~NG;>-rv=xjq*;U)paOs={}B#sB;FT2Ggw`)TU%=i1KA z&h;{_O*X5pXl>zqV~YGG?$&o_hp+F^vf=aX<=qIqL{+&aMK{OyXMSlnkLTN`ZFgsv z+xrvN&KA!#FYgBLr=3Ej(D9kuGB@qA#PPWhO;7o<s#ae?&IwK<#EjS z>jfLnwXN&bZ~NM9!e9d2fnCo}0VM_g_vh(&cX0}Pm-oHhul@H?qyMq6(!u-Vp`)zn z5HGfMeAFN^&|LeL@-s46Qv8w^Civ_%ugXD3KW% ziN?|KJrVYAW$iC&2Zyflzb4!;*VhO409LsBlzQSi2jc9VgAXT@LT=H7wL4{=(72~c!0=bu846iy9u~rlPB7tw_-Daj4YP|RaCHm%vO&mZR^|wGiu$rVf?8zP z{j(B@^WFsKSPx+p=@|ayMEoQb8l;2jL;!`Or7Umq1L@MEgS(8EHg^FzNtk{{p5#CT zhPuTA;JQT>$B6Wb^WT3?4>sSxIy@R7;i4u~?ix++_PKukJrh*~4Hr<3xK z5e2u~u%gVb^Pj@N9-n^i*c)Q?c2Cl}SB20|q}{7e;veZYbyX24ei1K5gJ;CxorY0?^>aZGk{`_M51a&vHIdHQO^{V#VGrn7O+ zX+Qyu(xHBJD_|}ZxXGDE{d7MZa+Ps({MKMkPTV=J(p!xksYsb zHdga-@Axvz;62Oh@>L2oO(Xsn*6=bvah|eVSZPXR052=LUOkKqsNh{o#rbwWMwB*& zUz5``Y&=GS0~J$tlY=RTD6rLNw@n~Y4>LOCEHI{1((W|CX$2&q^k_#xFNT0q6X;kY z8#-vwC}461fMJ3uRf^l*qlkVd+nkI_RHSyQ$r#ngIF+sRY6JH21dZvA$rcCD)YU(Z zfY(tSLtR9PZu%W5&yYqnAgcjd=(h z9(9R}eMocrd2*&6El=aPXug`0eQ6I>`gWV8=PlN<)^@@vyDEZ7bvv5Co{xY%P4Ugs z%{G>4vbsGZ<|HD(+vW_far=vkfqkkCjMzPcq)RBj%Lvr#fJ3)P}c2q=6eKzvRXExB*r|kp{^Y?7r z6*JpKH>*fN`=|v=NkqO=m3;qKtXKBu{r3Fm{D}U)LI+xB5@n|#|8zhE000dC+neU- zXyI(<=pkfh>ug|QYx7SKL}%$_XRD$N2>=Wh2&uAZ4yEGa4h;YZ^8Ak~0YL!(0I13M zPw;PS_Z2m98J1E$>>C=X3i$V$+z+_e)3H zXIWK?%aG;ywd&U5rfHkgQcG=1s&CEZ=BEQs*P`oT&&T6dW1stAscy|l*6~GG*LDV* z-W4r3uhd!$v4h{+(p<>p&fVD1oo|VQTmAi7+4U0O&?4i!#bZ*}iNMd(W#3xW=t6Ae zr26^>1Bd-k035jO$Yi?wiAT$J?=&kxX*axamu6n3Y?)+NQQWQUJ;lj0LEZm&==}_In3~H^U4ngC_aJPeD0Lb zd14QLojWhnp;*akH!&5v>_fsI-m5zUv0!)MaKFGe65{cGAt1h!b-u9=plo@6X2~n| zKwji^=8&JIhV{8h?K1&*e9yOj8<-mj3_o~Bz^(v#{N1qH^;&F|*swmGv*SQL?e*(K z`g}8n;GA%^bBQbS8uqxX>rU1xJ=N!>THg#xO}3d4uH8yg3{3b0NlXm_6U(S)`CgY~ zI^Sfm)T682zdTeT$<7N7&SMB`I5x+hFz${K}Qmw+V!PLV2+F`y#%P0r`#Wor848_xFOln6!sMZKsjG&==T+ zyhGhr2uf_zpCEFf-dJBmezxD)lhv&OjlHJ0Vmcc!tb# zh3-I7Euy%ZC9K1(U~d=b))ODV!ktK{V>WOZ976@Crqd4~q=1;MjzGBf)0&X+N@Ni4 z3uOI^oIdt~0kW|GD1F8W<5TlnrNe2e=O!f5>GS0R!qw_e1p=q1ILAUtlM?Poq*|sL z0)kOGa%4wN%N<4Gb;O}wX4jwhU#dx7DplKfRLko51c#B2%z@}61IDGN8`dgS;$|!X z#AOTILfcKQBJX`Bx&X7eMtzM8P+R;$m71o`)V&9cW-Kpo_Ov1`B2pAU{U8~V0W3h| zMXh(SUFA2fCP-L8hP>V3sTbFgjDV7?_W)3ZLdFK&PIvwrZN=$)j+eV7Eq)86Zu zBPUD7#JtM^p5yGL=MN>;GF%%;pdi6h>fr@;rx6B&8z(R?&jfuAUzn;G|1mF49}C?3ZIqh-f5>A$8S`rh(_2_d>{7=JZnT zyecdG{p@cxis#D@WvN8sHAptu7+^c5(Qw%oj{E-U(_xO;_0z+y zi}3^auLCuEzUoDQ0RX_-4G4hp|1nS{Y)$R{&q=ziv*m~_mgtjLCr@!=z-}1&Z_j?0 zM6%F$0?*6#Zw|WXp&){FzCa;%aX;kmCxE6FoB65%StnGWTP`kzr~;j!Z;ZR(}l z%*eqSyobX_)o+{6nXz+^Pid>9_3!JuSL?4W+fK9+?AmTj+RzM&jUW2qEPXBdTGhs! z-UD}L&aba3Ymy2prr+x&{`bSx4E-qlZzI>qjg#MV6aMerU7qh(Hyph#X|MbrTJc>9 z{4e8I;viPGJ6XFK2H6mT4D1HYea)zGi zobNW?p7EEdKN3%eUnlq9hSjCE=%}(J>kQbyHOdInxQ}l@rESyij@%nCLOWas!yYG< zuWS@V-~Ce;xt*-d zcCa>@wCSqn!zWR_U(L3C}fx7;ahhduHh0OIBt?`AHM$^eFIpCg|yJ_NoZS1;%xp_?KW z$`^8Xt;LK@3)gkw)2meGCVCY&cBk)lPUv`T$hbb)d3u;XO8o^6ig@#Hd->tD8Ob8> ze*N;+{~09z)@nPw4pbI^XTu;ruZ{IBeCE-j>~noXeke9MkdE5(xwV@Lhr1CFYRJVu&eVc=~^|jje5cMIYrC=c6HCY8I$7Gu$EQOdWi4kMzsMQ>w__rm)~EhH6O42*ZF+%(;c3Tu z28%Y=pG9KLWgA{)Ip*s@gveHfFYDabpbAd+k1ea;JlfVsLc9`S!rjRXl+6={Q}EEJ zDRfwb0s}X1dkY=zC=RI8*+VDhoBq01iFpWIcUz_kn-uF)J|ovG6qmZfWx*>Nf=hS|oO zGXPRaRb9f*X0o&uinvARpdVbR6(OQL^%yTdzy|J*_fO zz@h8vk~Iqc*1|$!UqMy)PqGk%=ET^yz+RFwIU`25f2eyk-hC2l8mJO0t<##AxCN19aO!M7+At@7Cm(~w5ViHLJ7@K5chH~#g z8!p-!{V`!^I5d0`kxC?U`D6^rz)43YcnWCJRXbHuZK54jpS;P-uV5Y`lug83T}ao) zX7NfQ`^&?)I6=MxNQM%oJSiiTP{Jo5NeZ)`@kC~+tL=DF z+Dh(-ea}IlP5%H6Rm>g*L>gBR_%HPxN7Xg|_QQKkeMbtZHh)Nr>SWRRBG&O~c_#Bm zuBsAJf(liO1JW_7aQS;pt|4Llm>Vesk|ur$g%S(4-qJGPenj)}P_00_i%seWh9~QH zK4b}AJL|d5c}96+-JkeLgG3*X`uLxk;+9-3`+u@-_imi zq0uN=5Z(h{@3Y1MM-{x)AT*+Y;AJ8N6~*qL;G!8o*b@w$+gw4)Na-YApM=fBzIY6; z#noxDN&{+D&m6>$_;O9gDPbCG@?$-mniCDl7D6EgNH*POe9~<2y-^@i>bqR4}BONY_%a-Mk!|jW5(2e1vU6cYL zt;OH;IZT!nKP}c^Z87SDa8oLMa@j1$-*tsNmIGpNpo}h{XHCWI-|sOhrL|G{NbFxBxz{>c1HBqrO)`65B5O%xUZBHORVq=BEOd3tfG1f@gpq z%W@!Fc=JhdmSq7dcV^3RtSqlTzO1mMdGwHQ5L@A8<5oDR`K~lc2c8;I^z@UYc*g0)u^D3bBb7m?>XGM#Vb<8S~c3EfnXc=CgpkS(aO{Thx zm+CpX3ouzVkq5_CLfgrsXf9jbq!DP3TaO3IY3ie!ExGz}kKKsBreS&}OlLjXq0JQ6 zQv!AsS3JbmWW}-LP*fNI^}HIqxE3jt24&p*q%bGh8T8dFk=021Q}&t+V1T+ebfJ2* z^pkbhK}mJ+QNrqygou(|XP2tKTr{OlE*ZpzX2>?t>Nah)B}>p+3OC|1ExsA!CNJG8 zR#SZc20XcB=G${wu=F%wNe*Dy)hvoNc%3~532T8>VDv~HC>?x_;*V7vSf}}sspz2~ zQW@#*tX$}`Dm|6pCDlFM&kx^&SA(;(P=1ss3mnN;#E*hrGhMaui1&yUxF*21395~A z$TWx8^S1w3HmXMLrkE~U1SVD%D?L@xBx9=xf~N_QI=};Mwhz<2wz?yiyWqVEse$B( zhF$+suMnjcEQF3^xGYKGJ!9BFX)Bkk zoIqdr_2n-XF&77O!X{9o1-77Ib~PBRzBUsc`*03fXKVV&Xy%IBKSCqam~|+Mfaj4x ze7f$+Ud`P!Ss+r25PR$D+pz0Kh@X|11F!phnt`VwCh2)}?;?q&q27qb3Bz3+pGyg< zoiGGfl+H2ycMaVbW9m)=p{=Q8iGAGdOYK&vO*5k`?2q?rb-IsvNY#~e)VM&c zpz(F3a%!*gVsIve^j-ApB1`!YL1M+8U4DB$y=b0>JPA?no0O9fr$aMBOCtTO$-T|^ zl)+D*zmFXFLyy#nA#|I6in^K^EAYsQJo(-RjB_cACx!B5<_>prh6q`F?ABdTh+2Y9 zzQ;Gg7);Sily?DV;Q`Q3FWvOW z_P$T5@U``?sj}CHvghgi8e~Qkg>Rq%kAxWd9gw+qvsnE!O!4?7Nd5R*o>v8L1_h-3 zD;F+^UV6)g~)pQ%RYr9=tA;G^5pBpz!1Gl-H* zwljqDR~4LDtlO5;rS+}aY9^e-W!lKM6b&p=3Mcbf9;%}{Nm&dcY@e$Kenc`6CCjJy zo7)O9s(@;f65{10H_a_aUf7qf+7nWYDGf(#is!EM(=(JESutmLW2a^GcH3yKaUIqo zJLpC!&m;uh#D&CjFnC*yZVv`6N z;{AC}a@JVYlAN{<(N0=K{3Ru5J0w_>VR`QkAS+_f)kTxU9cj?Tne*0RWPAC9wOn;7K3J)%58{QBY05&@NjbmWx zFL5{*nJ58+d$gLLkdPpPYB70s1d=;4WzP9&DQX>LZdYVaRJtWrT4K^L@5sqShptz9 z-wMBa*egbxC%d@c>`#+pypQ3*(%Ixm2HHImo4L(Bvqem2nrVX3W@Oyw=UI*~Pbid} z8ji|U^7qUK&$&>&pit$gQ_1`%0k=XknPzC_z|`Y0k9m$iYr}|R5%A&$B_$hxj67e6 zR{G@QpYILS55H8+e<7Cdao3^OoI9W#+udK7_Dh||g^e6H{SNM#cTmEr{I$nAX;6@e z_DyLVdWS@N*CCA+hcZx7MG?hu%$caZ?l9m-5C%VsY&#MY#YZn=SG-}|13CY#HYZqB z&d#Z3Hxm#Av^?o6<~&7{Zm}9cRZp*s(ejp{FJIFhMsQD5EyKJnxC^8y< zENVazpJEonX#a`Z1aoD7EL7Bovfx|v_@SUz!fjWg&f>=GhtzJ?vwlgdf-#`xP@4RdJj?Pg+ePE>P%ERWx9{=_-BErBs1Bg$T3+b2Ubkr#DD;1 zE-_t-_nBN^-cr=B^hYOcA)J8S(4NcY_Cq>o5^sjW%F7$SdJMQd|D zej2o1Q7L(sqN&OT@GNq3UgT#E-wR(LtjqTl2S)B6L*H^avf^t-4{1bG#WVIml({#gNB>1=aN2LPnCgcma|={U;r#5-PWJu_O7d(#^LRhIqaeq zR7t5tYmr4~eQ{J0A;~miLPFXe7n4d*0lPjmwed(iP8=S1Ih)fw52Pxx6PP` zb*hW&(dgFiOnP8XvEQ(f=gv2<=1FE1amg05Go_$_Jqxnh&$!r_5JF$LXgWFtRo^DN zI{r!z1so6w6V0RFIvAJxmFEg0d3ui2&UB``1Y#FyUwVGi~jMV)yt=YH#bCIFmyn`FW&**pLp5Cq5*F>=?orf`{@U;>3rei?4(Y`a@6F z1i{MmyvN`XEjWf0oXUE7!SY}XC(sv&Ig0A5>8l6Q)T+i z12suy&|vU=i!NsrAde9^h}9Z)PaBUoSMH3{1{CHS(hAIrfFCyL;4$r7`v}CFL!f4f zxxiC}PJ1@NgEqu;miLL_=pmNMp6Z4qtwdHF#)$_olr2&=)=Y`SSZApF2?6=6I89-U zaiEaElXF_a2py3XC~fQadqcsp=`r5IrgOhqGuimCK?kpIT(6zXipnL?pmQSEUB6SX zC zQ9x7Bfg@DfHxD3FPz}mR@b!h|Du(1Nw@o1z%0p%yS_Z#RB*nO@jh5-4%cbLR3;5Nq zya-9>|!kJr*Sio<`%zYsngAiWld;MivdJXGq9e z_>@?1md>QIhz_;B`% zS0d16c$Nu>=V>4rwsK#zJ#|d{5c5FzlMX1^WzcSTLZ^pvI6q$8`w=9*r|?Qgdevbe z3QJ@00XOB%0Ee&WvhC1ZTl@?s9LOa)9P-=R6%hz^PsEFFFeeGZ7KB)OuBod*$!`a5 zvi=!ioh{|d z@mWYXAGGfwEZY>P&wJPKV2xWJOP{XmHo z(e{-N-n^PpV@wlhaAlLGu~Z#PxC0sD>K^*an#EaHPe>_EX(^553#l|ACT)Msxq73M z5C*9{Ym$stxpu6YO8wq$n*Qvp z<0J`%!Ypb!d^ibY^A^_xZ6WpX6%W%@sj0`iSal(34RZBgr_+&c@0eP z(YhrGu=Dt$)K1ELnDZukUZUSC_TWWKt|?xBS@l2V)k+{)_hKAsG6LGv68Ir{)MGYa z+PX~mb>|QXx@4Lp0k#QKl;Cd2)FMdY@oR>18yTNpt_Ns_ODUE)Y6f^mp3ul2jksi3 zDvveQd)fn5SeeFw0A69$ro`M`Q!F&$I39Apbzauac_+TkzP1k$*xR?^oLP0b4Ol$D z&Enlwon3b)BWzafLn=}%tN!DK(`-EMr)5dQGGa9PJ$qq$hdT|H*YE^d#L#e=DjO}qj2Vzx7 z#}nw-7o?4iVSulK7%KKB_$sHQQ;VVS_WXF|83Am^k&SMkaLg&q-RC+u6{yC$!uBJ` z<2lhW0B(|_VaMQmL6{zSk)i6o!mGXNu~AlN%*DGNc@o-jZN~MCnokja^;~f6fLwY@ zPFydB(#ubjP*M3gU!ugN+teY}D~uYq=%McDgq$z7Lg1_Js5c_{iXN1YvOJX~z}z1x zGZa`Z!Z1>krKiLiaI}xez%Fa-=r9^|z)iH~-y1EJ*YL&@qQFZ>bI1k) zMD$Dy-DD0e2>p>VS=U_LoxSr8=H+LVCsJtan6+Zcr9|X2mMqi#OSlS8s3-HBXu4S< zhX(MpQ#nPzcbM7yP$7iBja{L&XWE#TrjF)Y-ByXBHM@JM<4N}Ke>B4^3=$20``lekuHL_WP09uTZxaaV4h`a?{|EeU(8y9oGqo2 z-mb-S@#vhqYYo7oNWOgMo5~vRi_Wf%M(Gc*zs&)jK?4ma@APl)+ihsjOkZljSikEu(_ z^`<~PcVHbYg^wCCE7rM#f=%fjYWDeAlI0YFEJz{G`$O2$)LOqT#}_xUb;-0hl3^)i zpLD80gfdm!Y$JtY>|&(ul^T?K4ra-T0*lsrwU;X=>AFccgw3-alPUT{ksX!fQyscs z8xdYV_E`pq0MWVzo?cNWp63^3zM6eh69Egh;&5|`i1R@ckrOV>XjH-_cI4N+r%NV> zJ;s!}-tfnKxZ;+G`qjGClbI2G0&txn4on>zSNZ7~U?EsnPSd zesO)P-u0F0HZG0r;v^3HmUxRlYctlXRjHHV5j9XTMOC+G8Q#d@Uw!h+GFIvw(AH8}d-0a!vDb-$DoR-QozFEiY!163}c`|__>*U72j%}ehpu>x!M3db(A7Gsza|9Z3W$0KAH5?Dry zySzRKZ9o(H;;0RY0b742iUslaUw&+!0RkOd3#H4jA+!hw-uP2b}3qo)#ft64*) zD8bg?Nr6SgH=@0`DKr_WxGNwX6Lt2u#7`1c_+!l$NBhf4I$aZXeZFm;B~>`jJbfRF zS9=hVp!9rZ9AD|dU&%;pVn0dCjVmLIi5;^LlG|hTC~-)y)tc*wF=?)jpjPX{Q|BhX ze%<6csIxr0QK30Q&IICSE`ld>K4h8(DLg5{0-;q|LJg&ts)3?WYCio?Xy{sLExu;!#28>g}^l1+{>wHx_V%ipPmI)zI^2 zK@DtT>-20-rYE~zC8_gHVx~!+5EyyTq=!hogma+MArUhkb4b$GC_2vasz)0dgG~At z{_vtm8hEErlEif_CVQa9oDSGoYh5|cFsE6FM1xX_{6kM7jQvCHstnn)lm#Xv78!iJ zyr%|jToD@Qp99QBj@Zq`Qx^_Hhlj=#^iFyAj*>a!Fw^fT?-$e)8lo=iv3? z#zeW9dsUs4=>;F}T5XogQuR6hw?=YPgW}D@FhQ4Kn32NsODtd1=mDYa4OecD>22tT zZyVc(V2O*@EZvzYM`*Q!ccn302txMkMl6(wYSAj0pHFp*1#HZSlCrLbi})gd55ehx z(<7Q|>QEgJgNSZ$<~+Lu!_9HH3J%Hy{p5U64B$@YgQ(35ojAmA5;kUNYs~jNClPOM zC8Fa7RWxTt0E+bT>)gE6<3rLm>(S4rd!$6WWRk(j#5sZsw2ssvK8`92Qo?LFo{MKpWVj55i@+Bm`QDNo|MSUV;F3o_uM%^z zW~S@{xZ5f7oxX>R0q$H4=hv4iM}ORbR0a~33PXq$Zp85>v2z08Waoo#^hU9@(bc@# zZ21E6gGyl;T$*(dPwV(Cp8T|CHV>fQmzW0pkBeQl{>7-g*B;~Zdu3)qO02j4uR2R9;}0elms zGBYoXEF0Z_=3WFu8$VNN=9@2h>o}&e4mR?qx3B}F7|Pu~1~CvnAng}WH;+3BEs*gp zW(9;~BXl0Rb&N3Z$CANo@Txvu5;_(ym=y3Dm;1YI91P-zHdAo5=MbBR?AItcJ(X5%V&55-0 zV<6uXH~#&U15JtJIm(w+jUCabxy@CrcB&jI2uV>=;neIFh>npar^8{T1M;L+gOXVw zIeC1H9sv=gyi_;gigEp~#-mb#Vk5qjU4o;&%wOaV138K`5o>{*FXT9|O7%C$z2r_{ z>aq%$lhKAtPRloQ3#z2_3CC6LuDoqeT7 zzG@gta_Ej0nz8JG5}AOYB=KIg)_e)cRi+e%yhd_yJr2$#QuNcELr;+N_?a!jLwX-3 z1}ka<$JW+3dYvoeUQhiYQum(e$gCJ-fLm8un;_LZ%2sD0PZTB($qXsGkoLrQK>sW| ze&j+C9voyZR*GUsPZ4HruR_lORq$j>yz`u`BxJk3oAfL4I4O;$pZJAJQwgrzjyv~m z4`epUeztHmG6JV#NI)RsmkOy7fhm;%PYTj7*5 z;ZS1=`SsyxVj;QrX>X_W?86a(g!bd5g!HvjJedO`EN1^D?JP*rAHsm4%WMl-GwLXnYoc*TipwZ7(bqr)0%N`y4GBFUH%dy4VdxXRUnePbsb0R2X}z;(Z;Ad*L+tg7Qo#c3w1fHiWT3)ZOp=3k@@6j1vng1dh*6-Tut1 zh01<=|3$ptig0g#06aPLC?`V-W0L+s9P?@h9FK?3*DdGZ@eqK87*7|!%!PTwelRY8 z27dJpdB2G@s93_KU144pj1@P*B%-DY(1wM!w*nld4?TEzufV+N^|lX_3|8ZENd+l} zNbn%;XlvvH9iec?Kp_MAg(-rDqlT{tb}|i(h;qqxy*W!H)7#XrB!PKtV1bT8Z`AJj z_!O+?R%L9sqi_-vX%bonCfUI=P8ecI0`Fcm+TOCYLJHIBSFgmP^M1Bb-h?yrbbIyl zj}3vthupKOaj^T-w)U!z6cv?0QGdH7 ztkbYobcyP_+H=pdM@5p^pl7#2+E~Ojp3LqkocL2Ey125AQSh$26%llq=q6GvWi?ee zRFWQ(;`&{79GO^z>4{%oEkfTKI{y*cNOb*!lbzWmrjbUyty_&!Y$li1Zb@ta?-!)N=LX6<2f>dB6{3#Q!Ec#NOmC_4`K;Z%0; z+rj(|-tlUV_uv%lT4yQsimQj#yYVKmp+wypl;+4Pj8!_j_q!ki#)C87{pQQuc^$gY zEYj@Kk>)~SG8TtuIH{%@wZo)P{18nOtkQDcaF~iO%+e>g+?V*1!I@KKjASY>S+pd$ z9QZQyR8TDFh8jox(&|U;-2|@&4NJe!aJ_KjNwYU@pfuW=ti2Or))}P`35_7;k%aKG zMl(i}JU$+91~%NYDPNTo@|CJ1I!Ph3G+a!k4lSvLNbJziO|n`)#O3N#y#T#nQT@-q zH;9!bd0U1_A!^R~?B|*PFxga(R?V%QZ&Zg#j+(2$5W%3oBBdhre-z;aK%Se&y_7tN zE}`~39A_AqQNxz#ZmI=ig3zuiz^4iTlj|MAWFBt$$rMp}wibKUhVT_`uyBhDJ(%jt zUYx+&o__MyTV!^_PnMf|Ui`wxx0bXyy~*B3TfL#^2=>S^CJbE6`+FUexqc(a;6b7v z3ULx2*a16sB({Y;%_P4#Cto@+btA$4wx2zfXAz0)6YwqK*whX@FeC^2sMj53-GSy!8H z<+$gkD|s`Bm>NfR7;jsI0b%izJtaL)T16oFjYAOY?Lq;_-oII^cd~B2RW{vgU8;}* z=_?R&?s>%|WwU9=Fm)1ohaM^P&U>~S5%MeCyROLbjs%YQ?tHF?v6aN0o&h*K~FB( zlnBw2ZQSC1&=qC~_5&xW1vF%A`>MVPBnL5Xh^4GHw2iq7FFn#!ES&Wy)gwj!91>D~ zvSF`-!}OJ6NDMi@L*vM&t<}FG6}jIh z?ss4BkHlGi+ELua(u3iIL4hKGi%~`cPgIA)h?@d!nXIyLiT=(|K2O|y+;~xtHYLNE zMo;0`x;|wUVryzX!=%BQeH7Vha9CVbzlP?!W{^)V&&eS>E%Z!U?HIOpvrT~`U;-4G z367;aDabCrXQ?RF9~_svTg4}Ws+>fNjr=UfyF4y!%4%tVdPBed0o2- zK@XkNutC`37q?lKnZ${z**2*Qiu^44?!aKPy(tb7I)j0BMiL~6Y!K>Bm)zh2uX>u-F&%DiAPHe1# zF=O#W8Oc^Qiu|VgMD7_MTmHFoW7z|Pt;R`QK}9bN$)b<(XYCNf2@z;*Z=8jkyRCJIUwh z@mzl6G&Xji=-GNC)G!|9iN<7_kBBAm!`GaLxr{yGFw~KYWJ2N^$PX#rGv!U>#7phb z7Q<-8&UHVBRR;(kHS&H4x<;?T*)*HU^1Xrw7?W z0~cTPlwD1nYY&l3%2|$zC7p_>GyK`ixfsZOynf}So(rG;+kwN_v1+pBcBqb`HjGf`N>8c7;}|Kj#S8@!@F7pt7}uJ(VXoqlB?^ad3%O z+KMNyTM6sP;{u0gNoCb8r^@)+f{_ZLla1|YSUhp-{HS<=yC{BkJ38U7Q(vCzY zk5+a=mM~{?4ME5elF@ExPddQK4V$dgYeg?rspVEMY3_SMoFotpzcV|`M6c4+zR{#> z&XVa9)s<2=H|_<)>^+w{gSuD;7hv^cqzlm-Lk@P{!Dl)O5T0Se(tw!Ge>svfEcG8f zX)do7)N0L7u&@Pz2Vc#PKB*W}fBRZOfWNWJL)tEf+H&+mtO5`BZCg0@FuZxMGAr;| zT2*)!()^)ViX8QY0hqkjkpEkzKL|t0DV!pjO9WrdR+ot(yNCP-96gV>VNJu0-o?o7wa)kJLN-_sOAvaWM+lx^I`sR3g` z#vQe@gm5kf39NQqJ=LREfSqjuGo99qOwwT(SUf6UqFV)l^GrQ7OwZ{#O)FHCr_H)E z%&0zPWO%fq!L33tu7f9?4V(`z2u}koRTse6>0jjSBfgEri430JGF=IUM!i;?*vA`gs^-=-nc63tB~m3_2wuLshJsGew0n&61zbBCN?Xap%05E3Vv-&q9;Dy|CsotSWTNTS zFYafZ5}+h75t7eFNBadq$cjI{(#@~8ZGac-tWHlcs+Nl+jsp1}g+X5-0!Qh$!zPL~ z9+r$(mlb-3xhUDZvsVc7ZFjB``7XOd2V5`n;q`&v=XoOY9s2io6zVH$@`gYA{^ZdD z0FeBLcN8pa{$7W-@)TLSWdVesi`TG(1YzpH!RT1!)lU5I>IIBS#=f6n@izXwKXD}B z5kK14WED_UVy5}fL0U#m(oOc$lifTlAq;qNTw4+}Qpdiv*EDYzW0i{G%RW`D+KvOy zO)m79KH0P|Jb4T^x7AcypIo;ZI;n3Y*JLzFjP2Cu&ZCykyPVWEeu|n$cA#tVkM_sk zyq$>C?0Y#qH*2*Wh1IVevz)ost|6YCoENUx9*D7=VXvU!7nnLwmN;yzrYCxTeG7PV zw4sWBlK#44+xDo=Z{MzIf@j(3vIBxnKjaNile$5d~f%4Eiq#rfG|+o8s>L(NK=DI!ZCptC`&cEM7vc&vrKHm z7NDjzS`Hd`Za4U{U%U)6UX&rArcn4s{P?%-__s>4+T^s?`qri+1q>a!Fp(YS^lL*yY;5Q60 z5!;pUVFiQWff1l@XBhyi1x(?(GI&6qSb%PfKre^#Q=pm=o=OxB*P!p9?9rJ3O1L35#EiVoFk@>o8()V z;H&e+Z|#MQfSW`=Qm(3<0FcuPrbald&pB*utq>VX(w{uP>si&mIlcdzAnbKS|E>Oy zH5;qbcVYjMync0Mf0ev`6k6Ep>i$P{f0s4%V+g zzpoRTVv1W2U;qFF)c?3n+)PZY{#GZ%zD2>PX#teZtCw$KLGF_xG8$`h_PKQe*}(ZT zuIO|HQYzcFpB*AFYB$!p8%6ft*i+muYnEP%{e5*fsLT+&T$zIG%)-0v`14 zmA8#6yEspI`WFFxGz-cszN9A9^tS$$%- zVvwc_zdu6~!ihLNSfuQCRx=zTE4n!$X>epUr_K!aV-m{Fq)DDl`RrOlx5EODyG~RA{IsQNCB>_>?W$ErLd10m}l;mgghgrIi$3VtE9=s z_$z{v5E3+Vk{OxGLFj4rRz@~(CZ1IGg*Trz&QMyj4l~^alaw{Eu^Xq;xwdj0B=zVTHr9J5D7?3SqRGUNpctnVj<7{qyo-JKysEzV-X3` z$ReDuW@;$O&ta2l=pau+B?kqtJW#qsS%@*3P!?G9D?cPDqSFJg{;06%ImThgk5<$q zq$K6cw@FgiVp?A2G@&eX)K+)^b1H&7^xx)=h^~VZTZ+S(d_rS9pRhmVX(QdljfJ3Pw`7aAD^9&_j|1C zOgo$pSJ)>Pn)L1MtCsa#tLN+hGkBkiiSvnX|F*2DNA!4<(EtF#xd8uD>pM3KTVp#n zr@z^QX@{e}bK^oU=6E@Htyvg&ZH3wEfL4zrnj_DM9A-6mHk8&7QA=tBO=dCW z!#f{D$TUT;rn=uuuQ>%FKJ!c7O@3~!&&QYCE5f)F7a_%NM+v^y)yD=;**4EFB4V5? z9a*|5(qh7RF-z}i_}`x0udjA{;9uMrlIcPwJDyeoR+ZlBGqDQ`Gkth0Ue9{&bvn-0 zUkxNN5Tie?h=~S=?kBj9`T5!T($l_iay@-@_MGN;d%ZdO!k_ug0w?_|C#S_LZ}jeG zo!%O7wf74D`y(WLyyz=o%T|POaAr(5R~DtmSI@VPOkKOvjjLC>x1ZoXj}e16?hhfn zf)HL=2CJ7&`iLP#+2HHpJ5TVAL?B~Li--J{nLZycW1cUgV_Jg39JX}k&fup#T`k{M zK0X@o-!)ftH$t$3fT)7czFD94(*v!*MpP+?)Ot7ph9AdN^06&jB0@??Wx3f#91g{n z1O|&tBNN*uB7xuJ%#z#(ku9U;Rc$vGh`fx-j3verDWGJ4o~6q~PwHY?SR{TgOPfDn zijtNAn}A6J7-9D#NbTh%ZtxutZ!DA)nv`fUVVS1&DAdM1>b|CBKWT+H9U3YQt%p^< ze3oo!^AzBvbH}(I4ovA1qHX>xZ1oz$@)$YVjEPBNRxf7H?Y#TZh^zj+b1M^+-Bg{C zd}%cpgrE;_t%*TsV=7Sb2qpOkb2A?K=oQjkLF`2#GvBqP)j%=t2(> zB_0y!evOjK@z+0qYLh&|Xz*uSS(v1GF|fSN=5d6ZqK|-TlC~X~d6=CGa#W0|FH1w0 zl@h(Wu1HMmMmw#NcL4F8O*bPTcr5HTXbjqZ9uUM+9ZX>UN*(x#Fh!HdAv0)i2xjWH zp+o{#8_3TxO}Pu&*TsD}ANWEii-YlFoub)4p1~N+*cgpnWl@4@IK$!UM`M5r#tqMa z;3|`?q@I*KROATh&&C3=ktA(ACsYgkACJ7^vCk~3wU3<#-=WdjYQ@97A zQA}}l7XqL8(ydp0ph$A(z~_i1j{H=4u`4LT4dqlZ?8V2H%~K(bsr3^e*-2ZrsS6^4 zd`Y_ic<#X-Cu>Ca9gjb z@19%1C4~}Se|6jv4sFdXEWHX*`P|*M9Z@w!IbF&+J}^Hy74?i}qOTlJvt)iEo|OB}%?6|3A{ zurjO%P1pm-b28sw8vk0#oC^hM2Vn#P>2Ogdw~6HHY;Oac#>LV4c#5pbi*I;$5o^@> zOCpYE>b!i2Gn|5=ltuq_;X)TiB6f6z`jKWIh>$l(iuwES zHeua}a$8q2n2moWBTJ2oZ?U>*LZ7`}8(Q-7j|G?QmN^MzhrFI^fGQF`2JlrQ){$iD=Q5Ks*{9xjc}27dAZKaHW|AF46OdoslLDtx>A6B( zqdm!vzW1OZJ#UYG3AwI@W8)N*CEe;QUZ2mQ;Abq+47_uXAE@dCv^F@`zDk_Ys$9C@ z2eQ&L!;`2M>RvrjXFvu+Ow=h~Uxc9{B!c{DrK~w)`6f9idAx1C!rkd5_+xdCXu);` z%ma9XM7C=5#0q*BmV;u!<~Uwh_wC*QAITHCBWLrM{Zxki!+gt6ik)}vi?RWa`xiBy zaUpa|qIWZe$Xd#w=D3Ur_$0;=(!h7u&^fH}Jj=HxJM#(l~V z3sAGM)e{o~;%%#lYsx#nDowx|_AOhQV2KC@gQm(_k#(dtgp{-ERJ#YWvmK*ow!Zkyz*}^cwXl1_ptM)qO5q-7suYrA%eT-Xc!J56}FEs9fbnS)Ek)*U1 zxmo>;(pJ{&KeJ1UC%4$*h4_Ptg9hNrw~s> zJcj399le+I89Puyc_vrBt|wB>>T@Cq8yO7V8B` z>rjyp!?CUDdHX@_tk|TFzw-ElO3HU>xl{PSdet5WmR1*sD`D?Nuk<{JNY6{?Y9ih| z)hkW|x;_}~6ccBqDq^f*SimrKiP~mku6<|6Z{l;-vVly;KNdt!m8pS{Mq2md%4`rQ zijtJj^bV2}y=@qVkJ64;r@Ds5tA&BB3mn;wXj*;6h_DU;XPKx*fL~$j6~@f5z+>WW zAcQl_074_2C<|yEsoP6(m3-NM!immL!I74j=Q#eLfssZS3D94>Yq-n-_9WMd?@uV+ zVJ_VfAXm8YcPz7u9`yfOI}QVV&4eB$?kxKgJorn0XJSN{cFj+jy65KGpd>oG-kJ)60*pd5IsEE)RC3nO$a{LHGNu3TQ z5e*~>ml&f6B_R`uV_XO0&I$>dcsk*hHZH+~#f#F)Ix#04+Z_$yS`;r?DeD|w#B%Rw z&#$6u_kw)Yts$Hyo8izz?JGAZQdBqQ9GHn<#;o0$#q08A746l{)#Bakjr?11?;lV0 z9pdb_Hp>nJ@e)+14`xN8&_{E@-pW`ss`{>yLz_kk|Hv&S)cXQBs#2%rqrsyac3k|_y5LQg!dyS zz{2Uj2C}S1wc zB^t06$0BYh^g6~AyZHy7*~pW?n?E7hr5M@b%W==CP3{@4<(^-|SZErBUPjJt5Jecfeb zZ7t$!M^$A0=EOLs>6O|tI)DZ;3Z0SQcU6&tSg~RGDTS6S8vMuR+UQ5&sY=DhpvDn) z0*!a0RL;Y2A#TTldfDx-&~p4ca}V2>Hit#t z0az;e<8NTFr|<&cJVV^80!kY0Gy8ixEj2wVy^Ddr^KKuvr8GpQh8c$l&q_ z6wl@r;0=t~aSp!uH2GVbgo;dbX0h}$?i_uUQP<`?6F6!xECcIsZ=F&}^6l(< zTK<}POT7zM7Syn`?y6GUokZc_`1x%Hs@Ywur+oOgC)4Cce(>Vm|I$ySfq{Xk zVw7E|F6%h#c|AKpJUM8^SoqE<3$O^}+@GzOjTaFfxTHMc%5kdHhFS$h)5mCYyZQk3j+$>1P_hqVwesSBU(=uLQBKF{UehBvhJ&o6# zjD)FkxT`a$aQjXja>l7G37%*HD;4`Ug{|mtUC-Xor(f5}Aq~_kXt}T#8Gxlj;^<^a zU)0*0PBXw~%d3#G5CuWrRn__~8uj?L8%ZC-sys5uLgUt*&)WkMvzEF=GqO&usoe|s z9-)HbMSDfvO7>?fUx%}JUBG*RMSHACy~GCrjgMEH82etn0uqS>T9a<#UUbdQqcbV+ ztc9NC@sSZlT{$af%mpRA^eFvnG*HrlB){oXE|&{6ahiuFkqY8q-ktnXSd;kQj#d0abgTfsg};- zs0n62LHvv|`^jz%-|V&1f>bwRnS;VZ;V(h-G}MeKrUs)DmK6W?ucR!(14Tp2$M|Ue z(4g8?CHJdEeO!*;`$zA_W$SpG<-@!BmU{jC&h8?LVj=dovCe7@8syUp6^gt~dMUJ~ zmdQ)ahRZy}}k zI7&J4w>|6`n9z=g>f{dnq(;Sh<5w4caM~=(^NCx`47d-0MrHW4PjS+|W7t{pN8I!; zHIUB}j-jQo-jjp!pe`!`CIQLiu3@iJZXCd=pMh`Fm_9_;hAf=R-D|QsBs!7@i@~zT zcf=~Ih0rmApy?PP$(Az-<`%By?XbnbRiILlTGBJ*lEdjkA0O<~o5~1E!W8@4@{#~5 zta09&=?>%6sZw+;H&=lFT6MO;HsJJ+=C<4&D9Hfffqnu8Q?FHOGV*ry_?ohgbjSa0 zy%lA~qv1$SXV#=cXViVoB+UVKV!-&NU#iIjLw$nmE-UeYjMqqpYd_|CKS4)KWUZZ1 z5n5eJu|WrKTqX^-bTHyz|w+f9EmzDc6kX@%Ha<2&t5*~Txqo-K-{)WtSRRq z;<%n>f%I`5ECvlm>en#B$(}Fh%%xcx8A3r@a%HY7AtS=zv9zq-;2D@~dwx3{ph#)S z=HMbU`RB9yn}#a+E{>Ws)#um;e&CEWlwHwSBT48PdAAT1H)oMAM~}}^WrsPeX0aC5UNj%!A(m%?NIQmC4KAqD&az+;=M|xOis`Yv_gn!e2j* zZl1-2;Lr0mfAC%cuL=s`qZ5=0JfB+zL5?d&LZ(Imp?MACr8Ozx=1un27K)F)e^YEM&(c z0$Wgh<)d_b!iK~ct-;3(Xc3Kj>8$c-Tk2@a#0lPOr%wSTOGN67dXQ_CzU}zAP#(0%ulgSsL!Kd)c>~k`4J%RyU1_$ z=nU=LOdS7Pr0zeNhWa!O0PrO1D2A+nOGNy6{l_25Z>GyW3I8)xIx`Dr3p3l#QUBMV z{}2-WHxbc45Bd+w?{o0T44)$0n)Cnw_`g}k{e=IIWdm0O3u^;IYZDneBLiy_r~euL z-+=5h#$yD14!!2zhJW_G0OHS(e{;;=unfLBnjr-W0N?}-0D$=0@I4{_Y*|K9SX53) z^zV8_(YO8_>C>|qpFTkQli9QH@bG^&Yj0p=WngCVH=OaWwEM&3pFa4%Kj{B$`}0in zGwmD@{%qUH#opf96c4XiB; zoc>`*!xG&dhChS1FAnf|=<{a~;b#@Z|K!bYv-l%(Y>f>Z|8%l=GFR0RW);jcdp8*IaW0M*|~g z6Gt%vYiq;L4Ebk^#U{{<;RiMV0A~8Xdv=odubFnnCb9%w=$kuI5?+^h10C&Kr)bwve>*&8GT3DG_dnmaWIvf1MBq`@ZCt~~z+wkWk zsei*IRsSW<#>BwM#qqyxVE@>o<09d{*PmH-Jv;R>B^XDZuy8o9% zJ4a&+TLbHVM*2nED`4=sg=ND1dzuKG{w2xY;B##||Nm_BhdDP8A20v_b8mkM>M>uC5&&Sk7XX0lx7n=&|0V7J?s5MtLw@hU^5>BG z(EcUsuR5~)J!k$dk^g6;63c%;{-t34-=qGnBmHM;9_Rl~{gbNn-^2Z068dMHgymo3 zelHOHd!*ls>i$f!xA{xbzm?eiJ<{)WK7S^OJNz~2|E>D@D;ntMLjeE);pcA#EC9e; J@aKX9_&+tcox%VB literal 0 HcmV?d00001 diff --git a/icfp-2016/benchmark/gregor/base/cldr/file.rkt b/icfp-2016/benchmark/gregor/base/cldr/file.rkt new file mode 100644 index 0000000..e702ce5 --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/cldr/file.rkt @@ -0,0 +1,80 @@ +#lang racket/base + +(require racket/dict + racket/match + racket/port + racket/runtime-path + file/unzip + json) + +(provide cldr-ref + cldr-ref* + cldr-json) + +(define (cldr-ref json key [fail (λ () + (raise (exn:fail:contract + (format "cldr-ref: no value found for key\n\tkey : ~s" key) + (current-continuation-marks))))]) + (define (return/fail) (if (procedure? fail) (fail) fail)) + + (cond [(list? key) + (let loop ([json json] [key key]) + (match key + [(cons k key) + (match (dict-ref json (symbolize-key k) #f) + [#f (return/fail)] + [j (loop j key)])] + [(list) json]))] + [else + (dict-ref json (symbolize-key key) fail)])) + +(define (cldr-ref* #:fail fail json . keys) + (or + (for*/first ([key (in-list keys)] + [res (in-value (cldr-ref json key #f))] + #:when res) + res) + (if (procedure? fail) + (fail) + fail))) + +(define (cldr-json zip-path pkg path prefix #:cache? [cache? #t]) + (define ref (if cache? hash-ref! hash-ref)) + + (ref JSON-CACHE + path + (λ () + (cldr-ref + (load-json zip-path (build-path pkg path)) + prefix)))) + +(define (symbolize-key k) + (cond [(symbol? k) k] + [(string? k) (string->symbol k)] + [(integer? k) (string->symbol (number->string k))])) + +(define (load-json zip-path data-path) + (call-with-input-file* zip-path + (λ (in) + (define zip-path (path->zip-path data-path)) + (define dir (read-zip-directory in)) + + (unless (zip-directory-contains? dir zip-path) + (error + (format "CLDR file not found: ~a" zip-path))) + + (define-values (pipe-in pipe-out) (make-pipe)) + (define reader (make-extracting-entry-reader pipe-out zip-path)) + (unzip-entry in dir zip-path reader) + (read-json pipe-in)))) + +(define (make-extracting-entry-reader out zip-path) + (λ (name dir? in) + (when dir? + (error + (format "CLDR path names a directory, not a file: ~a" zip-path))) + + (copy-port in out))) + + +(define JSON-CACHE (make-hash)) \ No newline at end of file diff --git a/icfp-2016/benchmark/gregor/base/cldr/info.rkt b/icfp-2016/benchmark/gregor/base/cldr/info.rkt new file mode 100644 index 0000000..c0666ea --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/cldr/info.rkt @@ -0,0 +1,3 @@ +#lang info + +(define scribblings '(("scribblings/cldr-core.scrbl" ()))) diff --git a/icfp-2016/benchmark/gregor/base/cldr/likely-subtags.rkt b/icfp-2016/benchmark/gregor/base/cldr/likely-subtags.rkt new file mode 100644 index 0000000..3158339 --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/cldr/likely-subtags.rkt @@ -0,0 +1,102 @@ +#lang racket/base + +(require racket/contract/base + racket/match + racket/string + racket/set + memoize) + +(require "core.rkt") + +(struct cldr-locale + (lang script region) + #:transparent) + +(provide (struct-out cldr-locale)) + +(provide/contract + [locale->available-cldr-locale (-> string? (-> string? boolean?) string?)] + + [parse-locale (-> string? cldr-locale?)] + [locale->cldr-locale (-> string? cldr-locale?)] + [locale->cldr-language (-> string? string?)] + [locale->cldr-region (-> string? string?)] + [locale->cldr-script (-> string? string?)]) + + +(define/memo* (locale->available-cldr-locale locale available?) + (define full (locale->cldr-locale locale)) + + (for/first ([str (in-list (locale->possible-strings full))] + #:when (available? str)) + str)) + +(define (locale->cldr-language str) (cldr-locale-lang (locale->cldr-locale str))) +(define (locale->cldr-region str) (cldr-locale-region (locale->cldr-locale str))) +(define (locale->cldr-script str) (cldr-locale-script (locale->cldr-locale str))) + + +(define (locale->cldr-locale str) + (hash-ref cldr-locale-cache + str + (λ () + (define full (resolve-locale (parse-locale str))) + (hash-set! cldr-locale-cache str full) + full))) + +(define locale-path-cache (make-hash)) +(define cldr-locale-cache (make-hash)) + +(define (locale->possible-strings l) + (match l + [(cldr-locale lang script region) + (list (format "~a-~a-~a" lang script region) + (format "~a-~a" lang region) + lang + "root")])) + +(define (cldr-database-locale src-locale) + (define full (locale->cldr-locale src-locale)) + (for/first ([str (in-list (locale->possible-strings full))] + #:when (set-member? (modern-locales) str)) + str)) + +(define (parse-locale str) + (match (string-trim str) + [(regexp #px"^([^-_.]+)(?:[-_])([^-_.]+)(?:[-_])([^-_.]+)" (list _ lang script region)) + (build-locale lang script region)] + [(regexp #px"^([^-_.]+)(?:[-_])([^-_.]+)" (list _ lang region)) + (build-locale lang #f region)] + [(regexp #px"^[a-zA-Z]+" (list lang)) + (build-locale lang #f #f)] + [_ + (build-locale "und" #f #f)])) + +(define (build-locale lang script region) + (cldr-locale (and lang (string-downcase lang)) + (and script (string-titlecase script)) + (and region (string-upcase region)))) + +(define (resolve-locale l) + (define (lookup src) (cldr-ref (likely-subtags) src #f)) + + (match l + [(cldr-locale lang script region) + (define likely + (parse-locale + (or (and lang script region + (format "~a-~a-~a" lang script region)) + (and lang region + (lookup (format "~a-~a" lang region))) + (and lang script + (lookup (format "~a-~a" lang script))) + (and lang + (lookup (format "~a" lang))) + (and script + (lookup (format "und-~a" script))) + (lookup "und")))) + (match likely + [(cldr-locale def-lang def-script def-region) + (cldr-locale (or (and (not (equal? lang "und")) lang) def-lang) + (or script def-script) + (or region def-region))])])) diff --git a/icfp-2016/benchmark/gregor/base/cldr/scribblings/cldr-core.scrbl b/icfp-2016/benchmark/gregor/base/cldr/scribblings/cldr-core.scrbl new file mode 100644 index 0000000..b2a6031 --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/cldr/scribblings/cldr-core.scrbl @@ -0,0 +1,207 @@ +#lang scribble/manual + +@(require scribble/eval + (for-label racket/base + racket/runtime-path + cldr/core + cldr/likely-subtags + json)) +@(define the-eval (make-base-eval)) +@(the-eval '(require cldr/core + cldr/likely-subtags)) + +@title{CLDR Core} +@author[@author+email["Jon Zeppieri" "zeppieri@gmail.com"]] + +@margin-note{ +@deftech{CLDR} is the @link["http://cldr.unicode.org/"]{Common Locale Data Repository}, a +database of localization information published by the Unicode Consortium. +} + +The CLDR Core library is a Racket interface to the +@link["https://github.com/unicode-cldr/cldr-core"]{cldr-core} JSON distribution published by +the Unicode Consortium. + +This package provides functions for: +@itemize[ + @item{enumerating the set of locales supported by CLDR and testing whether a given locale is supported;} + @item{accessing CLDR JSON data; and } + @item{canonicalizing locale strings and mapping them to the set of supported CLDR locales.} +] + +@defmodule[cldr/core] + + +@section{Locale Support} + +@defproc[(all-locales) (listof string?)]{Returns the list of locales supported by CLDR} + +@defproc[(modern-locales) (listof string?)]{Returns the list of modern locales supported by CLDR.} + +@defproc[(locale? [loc string?]) boolean?]{ +Returns @racket[#t] if @racket[loc] is in @racket[(all-locales)], @racket[#f] otherwise. + +@examples[#:eval the-eval +(locale? "fr") +(locale? "yi") +]} + +@defproc[(modern-locale? [loc string?]) boolean?]{ +Returns @racket[#t] if @racket[loc] is in @racket[(moderns-locales)], @racket[#f] otherwise. + +@examples[#:eval the-eval +(modern-locale? "fr") +(modern-locale? "yi") +]} + +@defproc[(available-locales) jsexpr?]{ +Returns the raw data from the @tt{availableLocales.json} data file. +} + + +@section{Accessing CLDR JSON Data} + +@defproc[(cldr-ref [data jsexpr?] + [key cldr-key/c] + [fail any/c (λ () + (raise (exn:fail:contract ....)))]) + any/c]{ +Looks up the mapping of @racket[key] in @racket[data]. If there is no such mapping, +then @racket[fail] determines the result: + +@itemize[ + @item{If @racket[fail] is a procedure, it is called + (through a tail call) with no arguments to produce the result.} + @item{Otherwise, @racket[fail] is returned as the result.} +]} + +@defproc[(cldr-ref* [data jsexpr?] + [#:fail fail any/c (λ () + (raise (exn:fail:contract ....)))] + [key cldr-key/c] + ...) + any/c]{ +Like @racket[cldr-ref], except that any number of keys may be provided. The keys are tried in order, +and the value of the first key to be found is returned. If none of the given keys are mapped in +@racket[data], then @racket[fail] is used to determine the result, just as in @racket[cldr-ref]. +} + +@defproc[(cldr-json [path-to-zipfile path?] + [package-name string?] + [path-within-zipfile path?] + [common-prefix cldr-key/c]) + jsexpr?]{ +A low-level procedure for accessing raw CLDR data from @tt{.zip} files. +This function is useful for implementing packages within the @tech{cldr} +collection but is generally @emph{not} useful for users of those packages. + +In order to keep download sizes reasonable (since the CLDR data set is very large), +packages in the @tt{cldr} collection keep their data in a @tt{.zip} file named +for the package in question. For example, the @racket[cldr-core] package contains a +data file named @tt{cldr-core.zip}. This file is a compressed archive of the +@link["https://github.com/unicode-cldr/cldr-core"]{official distribution}. + +The @racket[cldr-json] procedure takes: + +@itemize[ + @item{the path to this zipfile (typically defined within the package using + @racket[define-runtime-path]);} + @item{the name of the package (which doubles as the name of the zipfile, + without the @tt{.zip} extension);} + @item{the path within the zipfile to the desired @tt{.json} file; and} + @item{a key used to prune the returned JSON data.} +]} + +@defproc[(raise-locale-not-found [locale string?] + [package-name string?]) + any/c]{ +Raises @racket[exn:cldr:locale-not-found], indicating that @racket[locale] is not available +in the CLDR data set for the package named by @racket[package-name]. + +This function is useful for authors of packages within the @tech{cldr} collection. +} + +@defstruct*[(exn:cldr exn:fail) () #:transparent]{ +A struct type that serves as the base type for all CLDR errors. +} + +@defstruct*[(exn:cldr:locale-not-found exn:cldr) ([locale string?] [pkg string?]) #:transparent]{ +Raised by functions that are given locale strings that cannot be mapped to CLDR locales. +} + +@defthing[cldr-key/c flat-contract?]{ +A contract for lookup keys used by @racket[cldr-ref] and @racket[cldr-ref*]. The contract is defined as: + +@racketblock[ +(or/c symbol? string? integer? + (listof (or/c symbol? string? integer?))) +]} + +@defthing[cldr-main/c chaperone-contract?]{ +A contract for functions that return raw data from the @tt{main} section of the CLDR dataset. +Data in the @tt{main} section is per-locale. The contract is defined as: + +@racketblock[ +(-> string? jsexpr?) +] + +The string argument is a locale name. +} + +@defthing[cldr/supplemental-c chaperone-contract?]{ +A contract for functions that return raw data from the @tt{supplemental} section of the CLDR dataset. +Data in the @tt{supplemental} section is @emph{not} distributed in a per-locale manner. This contract +is defined as: + +@racketblock[ +(-> jsexpr?) +]} + + +@section{Canonicalizing Locale Strings} + +@defmodule[cldr/likely-subtags] + +This module provides a high-level interface to the data in @tt{likelySubtags.json}, described +in the +@link["http://www.unicode.org/reports/tr35/tr35-39/tr35.html#Likely_Subtags"]{CLDR specification}. + +@defproc[(locale->available-cldr-locale [locale string?] + [available? (-> string? boolean?)]) + string?]{ +Returns the best available CLDR locale string corresponding to the given CLDR string. +Availability is determined by the given @racket[available?] predicate. + +@examples[#:eval the-eval +(locale->available-cldr-locale "gd" locale?) +(locale->available-cldr-locale "gd" modern-locale?) +]} + +@defproc[(locale->cldr-locale [locale string?]) + cldr-locale?]{ +Returns the @racket[cldr-locale] that best matches the given @racket[locale] string. + +@examples[#:eval the-eval +(locale->cldr-locale "en") +(locale->cldr-locale "ar") +(locale->cldr-locale "zh") +]} + +@defproc[(locale->cldr-language [locale string?]) string?]{ +Returns the CLDR language code that best matches the given locale string. +Equivalent to @racket[(cldr-locale-lang (locale->cldr-locale locale))]. +} + +@defproc[(locale->cldr-region [locale string?]) string?]{ +Returns the CLDR region code that best matches the given locale string. +Equivalent to @racket[(cldr-locale-region (locale->cldr-locale locale))]. +} + +@defproc[(locale->cldr-script [locale string?]) string?]{ +Returns the CLDR script code that best matches the given locale string. +Equivalent to @racket[(cldr-locale-script (locale->cldr-locale locale))]. +} + + +@defstruct*[cldr-locale ([lang string?] [script string?] [region string?]) #:transparent] + diff --git a/icfp-2016/benchmark/gregor/base/types.rkt b/icfp-2016/benchmark/gregor/base/types.rkt new file mode 100644 index 0000000..ca714d0 --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/types.rkt @@ -0,0 +1,4 @@ +#lang typed/racket/base + +(provide Month) +(define-type Month (U 1 2 3 4 5 6 7 8 9 10 11 12)) diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/info.rkt b/icfp-2016/benchmark/gregor/base/tzinfo/info.rkt new file mode 100644 index 0000000..eee1640 --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/tzinfo/info.rkt @@ -0,0 +1,5 @@ +#lang info + +(define name "TZInfo") +(define version "0.2") +(define scribblings '(("scribblings/tzinfo.scrbl" ()))) diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/main.rkt b/icfp-2016/benchmark/gregor/base/tzinfo/main.rkt new file mode 100644 index 0000000..e09f35d --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/tzinfo/main.rkt @@ -0,0 +1,79 @@ +#lang racket/base + +(require racket/contract/base + syntax/modresolve) + +(require "private/generics.rkt" + "private/structs.rkt" + "zoneinfo.rkt") + +;; Load the zoneinfo-data package, if it's installed +;; (as it should be on Windows, for example). +(define ZONEINFO-DATA #f) + ;; (and (file-exists? (resolve-module-path 'tzinfo/zoneinfo-data #f)) + ;; (dynamic-require 'tzinfo/zoneinfo-data 'ZONEINFO-DATA))) + +(provide (struct-out tzoffset) + (struct-out tzgap) + (struct-out tzoverlap) + (struct-out exn:fail:tzinfo) + (struct-out exn:fail:tzinfo:zone-not-found)) + +(define istring/c (and/c string? immutable?)) + +(provide/contract + [current-tzinfo-source (parameter/c (or/c tzinfo-source? false/c))] + [set-default-tzinfo-source-constructor! (-> (-> tzinfo-source?) void?)] + [utc-seconds->tzoffset (-> string? real? tzoffset?)] + [local-seconds->tzoffset (-> string? real? (or/c tzoffset? tzgap? tzoverlap?))] + [all-tzids (-> (listof istring/c))] + [tzid-exists? (-> string? boolean?)] + [tzid->country-codes (-> string? (listof istring/c))] + [country-code->tzids (-> string? (listof istring/c))] + [system-tzid (-> (or/c istring/c false/c))]) + +(define current-tzinfo-source + (make-parameter #f)) + +(define (utc-seconds->tzoffset tzid seconds) + (seconds->tzoffset/utc (ensure-current-tzinfo-source) tzid seconds)) + +(define (local-seconds->tzoffset tzid seconds) + (seconds->tzoffset/local (ensure-current-tzinfo-source) tzid seconds)) + +(define (all-tzids) + (tzinfo->all-tzids (ensure-current-tzinfo-source))) + +(define (tzid-exists? tzid) + (tzinfo-has-tzid? (ensure-current-tzinfo-source) tzid)) + +(define (tzid->country-codes tzid) + (tzinfo-tzid->country-codes (ensure-current-tzinfo-source) tzid)) + +(define (country-code->tzids cc) + (tzinfo-country-code->tzids (ensure-current-tzinfo-source) cc)) + +(define (ensure-current-tzinfo-source) + (or (current-tzinfo-source) + (let ([src (make-default-tzinfo-source)]) + (current-tzinfo-source src) + src))) + +(define (make-default-tzinfo-source) + (default-tzinfo-source-constructor)) + +(define (set-default-tzinfo-source-constructor! fn) + (set! default-tzinfo-source-constructor fn)) + +(define default-tzinfo-source-constructor (λ () (make-zoneinfo-source))) + +(define (system-tzid) + (unless memoized-system-tzid + (set! memoized-system-tzid + (or (detect-system-tzid (ensure-current-tzinfo-source)) + default-system-tzid))) + + memoized-system-tzid) + +(define memoized-system-tzid #f) +(define default-system-tzid "Etc/UTC") diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/private/generics.rkt b/icfp-2016/benchmark/gregor/base/tzinfo/private/generics.rkt new file mode 100644 index 0000000..eee41d2 --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/tzinfo/private/generics.rkt @@ -0,0 +1,15 @@ +#lang racket/base + +(require racket/generic) + +(provide (all-defined-out)) + +(define-generics tzinfo-source + (tzinfo->all-tzids tzinfo-source) + (tzinfo-has-tzid? tzinfo-source tzid) + (tzinfo-tzid->country-codes tzinfo-source tzid) + (tzinfo-country-code->tzids tzinfo-source cc) + (seconds->tzoffset/utc tzinfo-source tzid seconds) + (seconds->tzoffset/local tzinfo-source tzid seconds) + (detect-system-tzid tzinfo-source)) + diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/private/os/env.rkt b/icfp-2016/benchmark/gregor/base/tzinfo/private/os/env.rkt new file mode 100644 index 0000000..ab643cb --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/tzinfo/private/os/env.rkt @@ -0,0 +1,6 @@ +#lang racket/base + +(provide tzid-from-env) + +(define (tzid-from-env) + (getenv "TZ")) diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/private/os/unix.rkt b/icfp-2016/benchmark/gregor/base/tzinfo/private/os/unix.rkt new file mode 100644 index 0000000..e2ad2e7 --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/tzinfo/private/os/unix.rkt @@ -0,0 +1,70 @@ +#lang racket/base + +(require racket/file + racket/match + racket/path + racket/string + "env.rkt") + +(provide detect-tzid/unix) + +(define (detect-tzid/unix zoneinfo-dir default-zoneinfo-dir all-tzids) + (or (tzid-from-env) + (and zoneinfo-dir + (tzid-from-/etc/localtime zoneinfo-dir default-zoneinfo-dir all-tzids)) + (tzid-from-/etc/timezone) + (tzid-from-/etc/TIMEZONE) + (tzid-from-/etc/sysconfig/clock) + (tzid-from-/etc/default/init))) + + +(define (tzid-from-/etc/localtime zoneinfo-dir default-zoneinfo-dir all-tzids) + (define /etc/localtime "/etc/localtime") + (define base-path (resolve-path zoneinfo-dir)) + + (define (find-matching-zone) + (define size (file-size /etc/localtime)) + (define content (file->bytes /etc/localtime)) + + (for*/first ([tzid (in-list all-tzids)] + [f (in-value (build-path base-path tzid))] + #:when (and (= (file-size f) size) + (equal? (file->bytes f) content))) + tzid)) + + (and (file-exists? /etc/localtime) + default-zoneinfo-dir + (let ([rel (find-relative-path default-zoneinfo-dir (resolve-path /etc/localtime))]) + (match (explode-path rel) + [(cons 'up _) (find-matching-zone)] + [_ (path->string rel)])))) + +(define (tzid-from-/etc/timezone) + (define /etc/timezone "/etc/timezone") + + (and (file-exists? /etc/timezone) + (string-trim (file->string /etc/timezone)))) + +(define (tzid-from-/etc/TIMEZONE) + (define /etc/TIMEZONE "/etc/TIMEZONE") + + (tzid-from-var /etc/TIMEZONE "TZ")) + +(define (tzid-from-/etc/sysconfig/clock) + (define /etc/sysconfig/clock "/etc/sysconfig/clock") + + (tzid-from-var /etc/sysconfig/clock "(?:TIMEZONE|ZONE)")) + +(define (tzid-from-/etc/default/init) + (define /etc/default/init "/etc/default/init") + + (tzid-from-var /etc/default/init "TZ")) + +(define (tzid-from-var file var) + (define re (pregexp (string-append "^\\s*" var "\\s*=\\s*(\\S+)"))) + + (and (file-exists? file) + (for*/last ([s (in-list (file->lines file))] + [m (in-value (regexp-match re s))] + #:when m) + (cadr m)))) diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/private/os/windows-registry.rkt b/icfp-2016/benchmark/gregor/base/tzinfo/private/os/windows-registry.rkt new file mode 100644 index 0000000..fbb7ce0 --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/tzinfo/private/os/windows-registry.rkt @@ -0,0 +1,81 @@ +#lang racket/base + +(require ffi/unsafe + ffi/unsafe/define + ffi/winapi) + +(provide subresources) + +(define _HKEY (_cpointer/null 'HKEY)) +(define _LONG _long) +(define _DWORD _int32) +(define _REGSAM _DWORD) +(define _BOOL (make-ctype _int (lambda (v) (if v 1 0)) (lambda (v) (not (zero? v))))) + +(define KEY_QUERY_VALUE #x1) +(define KEY_ENUMERATE_SUB_KEYS #x8) + +(define ERROR_SUCCESS 0) + +(define (const-hkey v) + (cast (bitwise-ior v (arithmetic-shift -1 32)) _intptr _HKEY)) + +(define HKEY_CLASSES_ROOT (const-hkey #x80000000)) +(define HKEY_CURRENT_USER (const-hkey #x80000001)) +(define HKEY_LOCAL_MACHINE (const-hkey #x80000002)) +(define HKEY_USERS (const-hkey #x80000003)) +(define HKEY_CURRENT_CONFIG (const-hkey #x80000005)) + +(define advapi-dll (and (eq? (system-type) 'windows) + (ffi-lib "Advapi32.dll"))) + +(define-ffi-definer define-advapi advapi-dll + #:default-make-fail make-not-available) + +(define-advapi RegOpenKeyExW + (_fun #:abi winapi + _HKEY _string/utf-16 _DWORD _REGSAM (hkey : (_ptr o _HKEY)) + -> (r : _LONG) + -> (and (= r ERROR_SUCCESS) hkey))) + +(define-advapi RegCloseKey (_fun #:abi winapi _HKEY -> _LONG)) + +(define-advapi RegEnumKeyExW + (_fun #:abi winapi + _HKEY + _DWORD + (name : (_bytes o 256)) + (name-len : (_ptr io _DWORD)) + (_pointer = #f) + (_pointer = #f) + (_pointer = #f) + (_pointer = #f) + -> (r : _LONG) + -> (and (= r ERROR_SUCCESS) + (let*-values + ([(cnv) (bytes-open-converter "platform-UTF-16" "platform-UTF-8")] + [(bs n _) (bytes-convert cnv name 0 (* 2 name-len))] + [(str) (bytes->string/utf-8 bs)]) + (bytes-close-converter cnv) + str)))) + +(define (section->hkey section) + (case section + [("HKEY_CLASSES_ROOT") HKEY_CLASSES_ROOT] + [("HKEY_CURRENT_CONFIG") HKEY_CURRENT_CONFIG] + [("HKEY_CURRENT_USER") HKEY_CURRENT_USER] + [("HKEY_LOCAL_MACHINE") HKEY_LOCAL_MACHINE] + [("HKEY_USERS") HKEY_USERS] + [else (error "bad section")])) + + +(define (subresources section entry) + (define hkey (section->hkey section)) + (define sub-hkey (RegOpenKeyExW hkey entry 0 KEY_ENUMERATE_SUB_KEYS)) + (define result + (for*/list ([i (in-naturals)] + [key (in-value (RegEnumKeyExW sub-hkey i 256))] + #:break (not key)) + key)) + (RegCloseKey sub-hkey) + result) diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/private/os/windows.rkt b/icfp-2016/benchmark/gregor/base/tzinfo/private/os/windows.rkt new file mode 100644 index 0000000..3e880b6 --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/tzinfo/private/os/windows.rkt @@ -0,0 +1,49 @@ +#lang racket/base + +(require file/resource + "../../../cldr/core.rkt" + "env.rkt" + "windows-registry.rkt") + +(provide detect-tzid/windows) + +(define (detect-tzid/windows) + (or (tzid-from-env) + (tzid-from-registry/vista) + (tzid-from-registry/nt) + (tzid-from-registry/95))) + +(define (tzid-from-registry/vista) + (windows->tzid + (get-resource KEY (string-append TZINFO-KEY "\\TimeZoneKeyName")))) + +(define (tzid-from-registry/nt) + (windows->tzid + (tzid-from-registry-list "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones"))) + +(define (tzid-from-registry/95) + (windows->tzid + (tzid-from-registry-list "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Time Zones"))) + +(define (windows->tzid tz) + (and tz + (for*/first ([mz (in-list (windows-zones))] + [win (in-value (cldr-ref mz '(mapZone _other)))] + #:when (equal? tz win)) + (cldr-ref mz '(mapZone _type))))) + +(define (tzid-from-registry-list prefix) + (define standard (standard-name)) + (define tzs (subresources KEY prefix)) + + (for*/first ([tz (in-list tzs)] + [std (in-value (get-resource KEY (format "~a\\~a\\Std" prefix tz)))] + #:when (equal? standard std)) + tz)) + +(define (standard-name) + (get-resource KEY (string-append TZINFO-KEY "\\StandardName"))) + + +(define KEY "HKEY_LOCAL_MACHINE") +(define TZINFO-KEY "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation") diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/private/structs.rkt b/icfp-2016/benchmark/gregor/base/tzinfo/private/structs.rkt new file mode 100644 index 0000000..5ce8f66 --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/tzinfo/private/structs.rkt @@ -0,0 +1,47 @@ +#lang racket/base + +(provide (all-defined-out)) + +(struct tzoffset + (utc-seconds + dst? + abbreviation) + #:transparent) + +(struct tzgap + (starts-at + offset-before + offset-after) + #:transparent) + +(struct tzoverlap + (offset-before + offset-after) + #:transparent) + +(struct interval + (from + to + offset) + #:transparent) + +(struct zone + (id + intervals + offsets) + #:transparent) + +(struct tabzone + (id + country-codes + coordinates + comments) + #:transparent) + +(struct coordinates + (latitude + longitude) + #:transparent) + +(struct exn:fail:tzinfo exn:fail () #:transparent) +(struct exn:fail:tzinfo:zone-not-found exn:fail:tzinfo () #:transparent) diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/private/tabfile-parser.rkt b/icfp-2016/benchmark/gregor/base/tzinfo/private/tabfile-parser.rkt new file mode 100644 index 0000000..2c09249 --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/tzinfo/private/tabfile-parser.rkt @@ -0,0 +1,59 @@ +#lang racket/base + +(require racket/contract/base + racket/match + racket/string) +(require "structs.rkt") + +(provide/contract + [parse-tabfile (-> path-string? (hash/c string? tabzone?))]) + +(define (parse-tabfile dir) + (define path (tabfile-path dir)) + (call-with-input-file* path read-tabfile)) + +(define (read-tabfile in) + (define re #px"^([^#\t]+)[\t]([^\t]+)[\t]([^\t]+)(?:[\t](.*))?") + (for*/hash ([line (in-lines in)] + [parts (in-value (regexp-match re line))] + #:when parts) + (match parts + [(list _ codes coords tzid comments) + (values tzid + (tabzone (string->immutable-string tzid) + (map string->immutable-string + (string-split codes ",")) + (parse-coordinates coords) + (and comments + (string->immutable-string comments))))]))) + +(define (parse-coordinates str) + (match str + [(regexp #px"([-+])(.{2,3})(.{2})(.{2})?([-+])(.{2,3})(.{2})(.{2})?" + (list _ + lat-sgn lat-deg lat-min lat-sec + lon-sgn lon-deg lon-min lon-sec)) + (coordinates + (->degrees lat-sgn lat-deg lat-min lat-sec) + (->degrees lon-sgn lon-deg lon-min lon-sec))])) + +(define (->degrees sgn d m s) + (define absolute + (+ (string->number d) + (/ (string->number m) 60) + (/ (or (and s (string->number s)) 0) 3600))) + + (case sgn + [("+") absolute] + [else (- absolute)])) + +(define (tabfile-path dir) + (define paths + '(("zone1970.tab") + ("zone.tab") + ("tab" "zone_sun.tab"))) + + (for*/first ([suffix (in-list paths)] + [p (in-value (apply build-path dir suffix))] + #:when (file-exists? p)) + p)) diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/private/tzfile-parser.rkt b/icfp-2016/benchmark/gregor/base/tzinfo/private/tzfile-parser.rkt new file mode 100644 index 0000000..4970c53 --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/tzinfo/private/tzfile-parser.rkt @@ -0,0 +1,132 @@ +#lang racket/base + +(require racket/contract/base + racket/match + racket/vector) +(require "structs.rkt") + +(provide/contract + [parse-tzfile (-> path-string? string? (vector/c (vectorof interval?) (vectorof tzoffset?)))]) + +(struct header + (magic version gmtcnt stdcnt leapcnt txcnt offcnt chrcnt) + #:transparent) + +(struct offset + (utc-seconds + dst? + abbreviation-index) + #:transparent) + +(define (parse-tzfile dir tzid) + (define path (build-path dir tzid)) + (unless (file-exists? path) + (raise (exn:fail:tzinfo:zone-not-found + (format "Cannot find zoneinfo file for [~a]" tzid) + (current-continuation-marks)))) + (call-with-input-file* path parse-tzfile-contents)) + +(define (skip-32bit-section in header32) + (match header32 + [(header _ _ g s l t o c) + (skip-bytes in (+ (* 5 t) (* 6 o) (* 8 l) g s c))])) + +(define (parse-transition-times in header word-size) + (for/list ([i (in-range (header-txcnt header))]) + (integer-bytes->integer (read-bytes word-size in) #t #t))) + +(define (parse-transition-offsets in header) + (for/list ([i (in-range (header-txcnt header))]) + (read-byte in))) + +(define (parse-offsets in header) + (for/vector ([i (in-range (header-offcnt header))]) + (offset (integer-bytes->integer (read-bytes 4 in) #t #t) + (= (read-byte in) 1) + (read-byte in)))) + +(define (build-tzoffsets offsets abbreviation-bytes) + (vector-map (λ (o) + (match o + [(offset t d? i) + (tzoffset t + d? + (string->immutable-string + (bytes->string/utf-8 + (car (regexp-match #px#"[^\0]+" abbreviation-bytes i)))))])) + offsets)) + +(define (build-intervals txtimes offset-indices tzoffsets) + (define base-intervals + (reverse + (let loop ([res '()] [xs txtimes] [ys offset-indices]) + (match* (xs ys) + [('() '()) + res] + [((list t) (list i)) + (cons (interval t +inf.0 (vector-ref tzoffsets i)) + res)] + [((list-rest t1 t2 xs) (cons i ys)) + (loop + (cons (interval t1 t2 (vector-ref tzoffsets i)) + res) + (cons t2 xs) + ys)])))) + + (match base-intervals + ['() + ;; no intervals: create a single, infinite interval + (list (interval -inf.0 +inf.0 (vector-ref tzoffsets 0)))] + [(cons (interval _ t (and off (tzoffset _ #f _))) xs) + ;; our first interval is in standard time: extend it to -inf.0 + (cons (interval -inf.0 t off) xs)] + [(cons (and x (interval t _ _)) xs) + ;; our first interval is in DST: prepend a starting interval + (list* (interval -inf.0 t (first-standard-offset base-intervals)) + x + xs)])) + +(define (first-standard-offset intervals) + (for*/first ([int (in-list intervals)] + [off (in-value (interval-offset int))] + #:unless (tzoffset-dst? off)) + off)) + + + +(define (parse-tzfile-contents in) + (define header32 (parse-header in)) + (match-define (vector header word-size) + (match (header-version header32) + [(or #"2" #"3") + (skip-32bit-section in header32) + (vector (parse-header in) 8)] + [_ + (vector header32 4)])) + + (define transition-times (parse-transition-times in header word-size)) + (define transition-offsets (parse-transition-offsets in header)) + (define offsets (parse-offsets in header)) + (define abbreviation-bytes (read-bytes (header-chrcnt header) in)) + (define tzoffsets (build-tzoffsets offsets abbreviation-bytes)) + (define intervals (build-intervals transition-times transition-offsets tzoffsets)) + + + (vector (list->vector intervals) + tzoffsets)) + + +(define (parse-header in) + (define bs (read-bytes 44 in)) + (header (subbytes bs 0 4) + (subbytes bs 4 5) + (integer-bytes->integer (subbytes bs 20 24) #f #t) + (integer-bytes->integer (subbytes bs 24 28) #f #t) + (integer-bytes->integer (subbytes bs 28 32) #f #t) + (integer-bytes->integer (subbytes bs 32 36) #f #t) + (integer-bytes->integer (subbytes bs 36 40) #f #t) + (integer-bytes->integer (subbytes bs 40 44) #f #t))) + + +(define (skip-bytes in n) + (file-position in (+ n (file-position in)))) diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/private/zoneinfo-search.rkt b/icfp-2016/benchmark/gregor/base/tzinfo/private/zoneinfo-search.rkt new file mode 100644 index 0000000..8ba3245 --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/tzinfo/private/zoneinfo-search.rkt @@ -0,0 +1,65 @@ +#lang racket/base + +(require racket/contract/base + racket/match) +(require "structs.rkt") + +(provide/contract + [find-utc-offset (-> (vectorof interval?) real? tzoffset?)] + [find-local-offset (-> (vectorof interval?) real? (or/c tzoffset? tzgap? tzoverlap?))]) + +(define (find-utc-offset intervals seconds) + (match (binary-search intervals seconds (λ (x) 0) 0 (vector-length intervals) #f #f) + [`#s(present ,idx) + (interval-offset (vector-ref intervals idx))])) + +(define (find-local-offset intervals seconds) + (define (in-interval? n) + (and (>= n 0) + (< n (vector-length intervals)) + (eq? '= (interval-cmp (vector-ref intervals n) seconds tzoffset-utc-seconds)))) + + (define (offset-at n) + (interval-offset (vector-ref intervals n))) + + (match (binary-search intervals seconds tzoffset-utc-seconds 0 (vector-length intervals) #f #f) + [`#s(present ,idx) + ;; could be an overlap + (cond [(in-interval? (sub1 idx)) + (tzoverlap (offset-at (sub1 idx)) + (offset-at idx))] + [(in-interval? (add1 idx)) + (tzoverlap (offset-at idx) + (offset-at (add1 idx)))] + [else + (offset-at idx)])] + [`#s(absent ,idx) + ;; gap + (match (vector-ref intervals idx) + [(interval t _ o) + (tzgap t (offset-at (sub1 idx)) o)])])) + + +(define (binary-search intervals t offset->delta start end last best) + (define i (quotient (+ end start) 2)) + + (cond [(or (= start end) + (eq? i last)) + `#s(absent ,best)] + [else + (case (interval-cmp (vector-ref intervals i) t offset->delta) + [(=) `#s(present ,i)] + [(<) (binary-search intervals t offset->delta start i i i)] + [(>) (binary-search intervals t offset->delta i end i (add1 i))])])) + +(define (interval-cmp int t offset->delta) + (match int + [(interval t1 t2 off) + (define delta (offset->delta off)) + (define lo (+ t1 delta)) + (define hi (+ t2 delta)) + + (cond [(< t lo) '<] + [(>= t hi) '>] + [else '=])])) + \ No newline at end of file diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/private/zoneinfo.rkt b/icfp-2016/benchmark/gregor/base/tzinfo/private/zoneinfo.rkt new file mode 100644 index 0000000..ee20c62 --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/tzinfo/private/zoneinfo.rkt @@ -0,0 +1,127 @@ +#lang racket/base + +(require racket/contract/base + racket/path + racket/match + racket/set + racket/string) +(require "generics.rkt" + "structs.rkt" + "os/unix.rkt" + "os/windows.rkt" + "tzfile-parser.rkt" + "tabfile-parser.rkt" + "zoneinfo-search.rkt") + +(provide (struct-out zoneinfo) + current-zoneinfo-search-path + make-zoneinfo-source) + +(define (zoneinfo-seconds->tzoffset/utc zi tzid s) + (define zone (zoneinfo-zone zi tzid)) + (find-utc-offset (zone-intervals zone) s)) + +(define (zoneinfo-seconds->tzoffset/local zi tzid s) + (define zone (zoneinfo-zone zi tzid)) + (find-local-offset (zone-intervals zone) s)) + +(struct zoneinfo + (dir + tzids + zones + tabzone-index) + #:transparent + #:methods gen:tzinfo-source + [(define seconds->tzoffset/utc zoneinfo-seconds->tzoffset/utc) + (define seconds->tzoffset/local zoneinfo-seconds->tzoffset/local) + + (define (tzinfo->all-tzids zi) + (sort (set->list (zoneinfo-tzids zi)) + stringcountry-codes zi tzid) + (define tab (hash-ref (zoneinfo-tabzone-index zi) tzid #f)) + (if tab (tabzone-country-codes tab) '())) + + (define (tzinfo-country-code->tzids zi cc) + (for/list ([tab (in-hash-values (zoneinfo-tabzone-index zi))] + #:when (member cc (tabzone-country-codes tab))) + (tabzone-id tab))) + + (define (detect-system-tzid zi) + (define candidate + (case (system-type) + [(unix macosx) + (detect-tzid/unix (zoneinfo-dir zi) + (find-zoneinfo-directory default-zoneinfo-search-path) + (tzinfo->all-tzids zi))] + [(windows) + (detect-tzid/windows)] + [else + #f])) + + (and (tzinfo-has-tzid? zi candidate) + (string->immutable-string candidate)))]) + + +(define (make-zoneinfo-source) + (define dir (find-zoneinfo-directory)) + (zoneinfo dir + (read-tzids dir) + (make-hash) + (parse-tabfile dir))) + +(define (zoneinfo-zone zinfo tzid) + (hash-ref! (zoneinfo-zones zinfo) + tzid + (λ () (build-zone zinfo tzid)))) + +(define (build-zone zinfo tzid) + (match (parse-tzfile (zoneinfo-dir zinfo) tzid) + [(vector intervals offsets) + (zone tzid intervals offsets)])) + +(define default-zoneinfo-search-path + (list "/usr/share/zoneinfo" + "/usr/share/lib/zoneinfo" + "/etc/zoneinfo")) + +(define current-zoneinfo-search-path + (make-parameter default-zoneinfo-search-path)) + +(define (find-zoneinfo-directory [path-list (current-zoneinfo-search-path)]) + (for/first ([path (in-list path-list)] + #:when (valid-zoneinfo-directory? path)) + path)) + +(define (valid-zoneinfo-directory? path) + (and (directory-exists? path) + (ormap file-exists? + (list (build-path path "zone1970.tab") + (build-path path "zone.tab") + (build-path path "tab" "zone_sun.tab"))))) + +(define (read-tzids dir) + (define (use-path? p) + (use-relative-path? (find-relative-path dir p))) + + (define (use-relative-path? rel) + (define rel-str (path->string rel)) + + (and (not (regexp-match #rx"\\." rel-str)) + (andmap (λ (f) (not (equal? rel-str f))) EXCLUDED-ZONEINFO-PATHS))) + + (for*/set ([p (in-directory dir use-path?)] + [r (in-value (find-relative-path dir p))] + #:when (and (not (directory-exists? p)) + (use-relative-path? r))) + (string->immutable-string + (string-join + (map path->string (explode-path r)) + "/")))) + +(define EXCLUDED-ZONEINFO-PATHS + '("+VERSION" "localtime" "posix" "posixrules" "right" "src" "Factory")) diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/scribblings/tzinfo.scrbl b/icfp-2016/benchmark/gregor/base/tzinfo/scribblings/tzinfo.scrbl new file mode 100644 index 0000000..1a6bd06 --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/tzinfo/scribblings/tzinfo.scrbl @@ -0,0 +1,229 @@ +#lang scribble/manual + +@(require scribble/eval + (for-label racket/base + racket/contract + tzinfo)) + +@(define the-eval (make-base-eval)) +@(the-eval '(require tzinfo)) + +@title{TZInfo} +@author{@(author+email "Jon Zeppieri" "zeppieri@gmail.com")} + +@defmodule[tzinfo] + +@section{Introduction} + +The @tt{tzinfo} library provides an interface for querying the IANA time zone database +(also known as the Olson database). + +UNIX systems usually come with a compiled version of the IANA database (typically in +@tt{/usr/share/zoneinfo}). @tt{tzinfo} will use the system's database if available. +However, if the @tt{tzdata} package is installed, that will be used instead. Since +Windows systems do not come with a zoneinfo database, Windows users must install +@tt{tzdata} to use @tt{tzinfo}. + +@section{Querying the Database} + +@defproc[(all-tzids) (listof string?)]{ +Returns a list containing all of the time zone IDs in the database. +} + +@defproc[(tzid-exists? [tzid string?]) boolean?]{ +Returns @racket[#t] if the given ID is in the database, @racket[#f] otherwise. + +@examples[#:eval the-eval +(tzid-exists? "Europe/London") +(tzid-exists? "Fillory/Whitespire") +] +} + +@defproc[(utc-seconds->tzoffset [tzid string?] + [seconds real?]) + tzoffset?]{ +For a given time zone ID and number of seconds since the UNIX epoch (1970-01-01 00:00:00 UTC), +returns a @racket[tzoffset?] describing the offset from UTC in effect at that moment of time +in the given time zone. Raises @racket[exn:fail:tzinfo:zone-not-found] if the given time zone +ID is not in the database. + +@examples[#:eval the-eval +(utc-seconds->tzoffset "America/New_York" 0) +(utc-seconds->tzoffset "Fillory/Whitespire" 0) +] +} + +@defproc[(local-seconds->tzoffset [tzid string?] + [seconds real?]) + (or/c tzoffset? tzgap? tzoverlap?)]{ +For a given time zone ID and number of seconds since 1970-01-01 00:00:00 +@italic{in the given time zone}, returns one of: + +@itemize[ +@item{ +a @tt{tzoffset} struct, describing the offset from UTC in effect at the given time in the given time zone; +} +@item{ +a @tt{tzgap} struct if the given local time falls into a gap between different offsets (as, for example, +when an hour is skipped at the start of daylight saving time in most parts of the United States); or +} +@item{ +a @tt{tzoverlap} struct if the given local time falls in a period when two different offsets might be +in effect (as, for example, at the end of daylight saving time, when an hour is repeated). +} +] + +Raises @racket[exn:fail:tzinfo:zone-not-found] if the given time zone ID is not in the database. + +@examples[#:eval the-eval +(local-seconds->tzoffset "America/New_York" 1409606993) +(local-seconds->tzoffset "America/New_York" 1394330400) +(local-seconds->tzoffset "America/New_York" 1414890000) +] +} + +@defproc[(tzid->country-codes [tzid string?]) (listof string?)]{ +Returns a list of ISO 3166 alpha-2 country codes in which the given time zone is used. + +@examples[#:eval the-eval +(tzid->country-codes "Europe/Moscow") +(tzid->country-codes "Antarctica/Troll") +(tzid->country-codes "Africa/Kinshasa") +] +} + +@defproc[(country-code->tzids [cc string?]) (listof string?)]{ +Returns a list of time zone IDs that are used in the country identified by the given +ISO 3166 alpha-2 country code. + +@examples[#:eval the-eval +(country-code->tzids "US") +(country-code->tzids "IT") +] +} + +@defproc[(system-tzid) (or/c string? #f)]{ +Returns the ID of the current system time zone, if it can be determined, @racket[#f] otherwise. +} + +@defstruct*[exn:fail:tzinfo:zone-not-found ()]{ +An exception that is raised by query functions when the given time zone ID does not +exist in the tzinfo database. +} + +@section{Offsets, Gaps, and Overlaps} + +@defstruct*[tzoffset ([utc-seconds exact-integer?] + [dst? boolean?] + [abbreviation string?]) + #:transparent]{ +A structure type representing a time zone-specific offset from UTC. +@tt{utc-seconds} contains the different from UTC +in seconds. @tt{dst?} is true just in case the offset represents an offset in effect during +daylight saving time. @tt{abbreviation} is, e.g., "EST" for "Eastern Standard Time," "BST" for +"British Summer Time," etc. +} + +@defstruct*[tzgap ([starts-at exact-integer?] + [offset-before tzoffset?] + [offset-after tzoffset?]) + #:transparent]{ +A structure type representing a time zone-specific gap between two offsets from UTC. Gaps occur +at the start of daylight saving time. +@tt{starts-at} is the start of the gap, represented as a number of seconds since the UNIX epoch. +@tt{offset-before} is the @tt{tzoffset} in effect before the gap. +@tt{offset-after} is the @tt{tzoffset} in effect after the gap. +} + +@defstruct*[tzoverlap ([offset-before tzoffset?] + [offset-after tzoffset?]) + #:transparent]{ +A structure type representing a time-zone specific overlap of two different offsets. Overlaps +occur at the end of daylight saving time. +@tt{offset-before} is the earlier offset. E.g., when going from daylight saving time to standard time, +@tt{offset-before} is the daylight saving time offset. +@tt{offset-after} is the later offset. +} + +@section{Data Sources} + +@tt{tzinfo} allows for a pluggable data sources. At present, the only supported source +is based on @tt{zoneinfo} files, which are a compiled form of the IANA database, widely- +used on UNIX systems. + +@defparam[current-tzinfo-source tzinfo-source tzinfo-source? #:value #f]{ +A parameter containing the current @tt{tzinfo} data source. +} + +@defproc[(set-default-tzinfo-source-constructor! [ctor (-> tzinfo-source?)]) void?]{ +Sets the constructor function that will be applied to build the default tzinfo source. +To use a custom source, you must call this function before using any of the querying functions. +} + +@section{Data Source Generics} + +@defmodule[tzinfo/source] + +@defthing[gen:tzinfo-source any/c]{ +A generic interface for defining custom tzinfo data sources. It defines the following +methods: + +@itemize[ +@item{@racket[tzinfo->all-tzids]} +@item{@racket[tzinfo-has-tzid?]} +@item{@racket[tzinfo-tzid->country-codes]} +@item{@racket[tzinfo-country-code->tzids]} +@item{@racket[seconds->tzoffset/utc]} +@item{@racket[seconds->tzoffset/local]} +@item{@racket[detect-system-tzid]} +] +} + +@defproc[(tzinfo-source? [v any/c]) boolean?]{ +Returns @racket[#t] if @racket[v] is a tzinfo source, @racket[#f] otherwise. +} + +@defproc[(tzinfo->all-tzids [src tzinfo-source?]) (listof string?)]{ +Returns the full list of time zone IDs contained in the given tzinfo source. +} + +@defproc[(tzinfo-has-tzid? [src tzinfo-source?] + [tzid string?]) + boolean?]{ +@racket[#t] if the tzinfo source contains the given time zone ID, @racket[#f] otherwise. +} + +@defproc[(tzinfo-tzid->country-codes [src tzinfo-source?] + [tzid string?]) + (listof string?)]{ +Returns the list of ISO 3166 alpha-2 country codes in which the given time zone is used, accoring +to the tzinfo source data. +} + +@defproc[(tzinfo-country-code->tzids [src tzinfo-source?] + [cc string?]) + (listof string?)]{ +Returns the list of time zone IDs that are used in the given country (identified by an +ISO 3166 alpha-2 country code), according to the tzinfo data source. +} + +@defproc[(seconds->tzoffset/utc [src tzinfo-source?] + [tzid string?] + [seconds real?]) + tzoffset?]{ +Returns the @tt{tzoffset} in use at the given UTC time in the given time zone, according to +the tzinfo source. +} + +@defproc[(seconds->tzoffset/local [src tzinfo-source?] + [tzid string?] + [seconds real?]) + (or/c tzoffset? tzgap? tzoverlap?)]{ +Returns a @tt{tzoffset}, @tt{tzgap}, or @tt{tzoveralap}, depending on what offset is in effect +at the given local time in the given time zone, according to the tzinfo source. +} + +@defproc[(detect-system-tzid) (or/c string? #f)]{ +Returns the time zone ID currently in use by the operating system, if it can be detected, +@racket[#f] otherwise. +} diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/source.rkt b/icfp-2016/benchmark/gregor/base/tzinfo/source.rkt new file mode 100644 index 0000000..d274ddd --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/tzinfo/source.rkt @@ -0,0 +1,17 @@ +#lang racket/base + +(require racket/contract/base + "private/generics.rkt" + "private/structs.rkt") + +(provide/contract + [tzinfo-source? (-> any/c boolean?)] + [tzinfo->all-tzids (-> tzinfo-source? (listof string?))] + [tzinfo-has-tzid? (-> tzinfo-source? string? boolean?)] + [tzinfo-tzid->country-codes (-> tzinfo-source? string? (listof string?))] + [tzinfo-country-code->tzids (-> tzinfo-source? string? (listof string?))] + [seconds->tzoffset/utc (-> tzinfo-source? string? real? tzoffset?)] + [seconds->tzoffset/local (-> tzinfo-source? string? real? (or/c tzoffset? tzgap? tzoverlap?))] + [detect-system-tzid (-> tzinfo-source? (or/c string? #f))]) + +(provide gen:tzinfo-source) diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/+VERSION b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/+VERSION new file mode 100644 index 0000000..4f5f072 --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/+VERSION @@ -0,0 +1 @@ +2014c diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/Factory b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/Factory new file mode 100644 index 0000000000000000000000000000000000000000..4c409e1e51a2b37cf10e6d2fd92d8ce9101aa685 GIT binary patch literal 101 zcmWHE%1mRx1dKo-5QYH|+YrL>$xlwqQ7FmGO;xDM&r4OvEiEolNJ>>GPA$>ZElvfB UW+p4-Cgzm_RTU(rrvh~W0C;i|+yDRo literal 0 HcmV?d00001 diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Alaska b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Alaska new file mode 100644 index 0000000000000000000000000000000000000000..e186dfdc529dd11098c3a5ba89f15d6f90ebbfef GIT binary patch literal 861 zcmchLYeNd##k3SE$_gfOKdx=~raZT2zfW6#6$J3o%PM7Nv!JMQ+EV~$wu zb9h8wW0GxX@n^$OSsMHpQsVT@oxE@<3%Hg{UUVW7oGdclxhjKP%F=DF`4Qx%2)Bus zxs&+RHk*g{Bzbg>@SY#~Y1Yd=o7b}mkk~qHv%C9X&gF-^cWWoiZM?$ItG0rVu8H?8 zt^z-mfuEmJ2>ww8d_bt40zDG=Ag6o^it+Uh`j|$+W8o+r3Zn)0#2C`$Mhn{~keO3p zQEeZFYJy>L#Tyou_zS|mMU6hE=t%>M>A6EohEHN_TRSbi zR*7*n#|h5n;W8~kyfGe^D~~}!p)V%N${{KKD<+GxKrZ!R^6^MWnfk(3Jn)2-BTrZ= zMbN5S-E8$~cUp7q9OLzqq^P@rX}SHBUfzlsaaSob;~-{!dIieZ7N#8T1(oCgQ(fzT zb?-`9_W8TC{;>sf4qc=T*Gn+Bw4U;sQ!zhPO9kc-ER?E9t>IApGln#YW2kw(7K%ay zR&+lail<+(k`6D}Jle}j>)ykbo({IPd=R#^HL&eDZ>g-|BJPMCpq<)!ESC`NQfhJ6 zyECMfsZjgKL^^Q{>N+)4F)qP9%|_Te7|r&XH$o+OF})@k4A%FoDk%{5>j#<9ZwgGg zUCbo-lUY81=F#tD2_Urej8OHrGkBowHXVFw!b3F|=xnhT8 Q+eMLWH;xn8=g6P?8&O#tqyPW_ literal 0 HcmV?d00001 diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Aleutian b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Aleutian new file mode 100644 index 0000000000000000000000000000000000000000..d1a6a5069cd27dbdc6db9d7b8add69e64bd0e4a6 GIT binary patch literal 858 zcmchLTS${}7{KPKpJ8##h@~}}7>hK@ zi=pZ$;86UBNRS<6C-*a)AoS| zj5J*%){%!%#g8Dm8ZbtC6=JgjF-}o8{W|N?ELt#0dba9KQo7KTle>pok ztcGJNUs%pv1stClWw|ZOaKb#m@(eSO-*cT69R5Z6%l&vVVwwtzJJ29EQ<1h7ixzsR zSecE*Bh6GIjmMHc1C`GC;F-=QIBQX}GGif}Lj^0>B|$~|GOJW6p{jg_ReQ;xCY@M~ z7)(a>G#cMasm|Msb>?}hU+Ts4J+JA)L^C#+`sm`I0Zn=B)Yx?ZC3c*>!@ue%UGpC+ zibXufiDGqu#9?)vRzI$*?rvMoLlm1TB%4;3D!-6)M2@7YvY&hM?GvU1WeVOz9PuE;% zl#==Nqg3GciwFh=Mg~SEAY@?t|9|xYMuz|Y=T2Z?0kb)LT|yXqgMm0a1Y|Z4005Kq BBcK2P literal 0 HcmV?d00001 diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Central b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Central new file mode 100644 index 0000000000000000000000000000000000000000..7dfbd0a3a3901f3b24439fe8b5a802406b2b4964 GIT binary patch literal 1279 zcmd5+Z8R1J6uv|#FIHK?XxVxvjA|mWG@N&@%}05C8xwkIm0P}2#_h~lJ8QPAur*Sc zJ`9^1t;Is4Jy-Fu$rJoh=z{c-l=tHkJej6N`Cs?psVlK?`lH8O;L=HjVZB`B)eGP0W?}LAIw)3D@Y$u` z!dcldJ~y5M=j#)=q$?D@&-Lfh3MVK_-o)i6Lg<3j4=a+k&<`RztPC=tDxo1(+pAK| zLIu_u+@sn-Io7GFKwWDS{&Z&$E|$u;zNHNsG8(xtpc^ig*<(}cXVC1C$}Qo0;Iico zZgu;Ve%5}Q+bnib+hhc`3*4!_M}${CQBbGJ1a^jMa97+oTz4Gd8{Rjdd*xOB&AJ+T zpp<)cbD&rLCI7Cdq`t-&zA4M1TW7vNS$!h?ad;ofa|5YAN`eE)4s=_*0q+DG(_LSC z9u(QbJsTq)5*opu%Yld00EQn8@W|i*{MFsUqpdA)zo8$;O6A0P&G;ari5{jD;&^lc zO@yT5-yUi7Xmb=kwv437*FNSa+O9OEF6F67DNGNEd8S7U|FoI0qQ(qnivlTtJPI)3AuY!o~7T((El`L1P?g)gEQ- zGe`zvit8uL~9@fRE<9d-Fys>Qr?QGX7hfRIw*}im!9O^#jH#20k`5R=%=tkO-dIaC{I7Lq3(dcZMN-oY@ z(Pg|EL>9YQ)RhBbfd`8#4ub3GT7Kt57QNf;j&4bb4~`AqJYArffz1GqX>}$MvO+1RA`LStF9EKri4)?=CpJ0Hhyqi47;w)^6q#u*i+ii z(LMsejAq_zJqG)t3pqx&17bbWIaV=B@wNpRFS|zj_0n*EeK{pgM&g0oOgh-(ib=_F z^kI!TCI|acO12h)((_ySnal!}XNKpm{+|-Fv$bVPFgtthB&f`5P=D%ZK4l#zX9+lY UNx)?ePQG*Sl*~W1xdZ0uU+6&Q>Hq)$ literal 0 HcmV?d00001 diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/East-Indiana b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/East-Indiana new file mode 100644 index 0000000000000000000000000000000000000000..d5dcfb53f714aa0503866b53ae7afed6aa684f38 GIT binary patch literal 606 zcmWHE%1mRx1Z+Sd5C(xHAO^7|<}K4{n7`|1!GbovhJ~|k7n}-LYB+Vnz2J1mzlKZ7 zUkWZIa(=j6`kCR1!|M-ML$5MiQ#kwKy6JX?8w~3|+!US3aPz^$54ZkpZMc1)_`{uh z(;M!toKSFYUuDDn&Z2?`^P(FbW`-0zs}gi;Bu>8J#V4^3uhV_`pTKtiaX9Il=YwiVyC(@ekZDcYW~Wb$sBtIp>4dTjdAdb2ZBt6{kMS)Cn8uP2Xro^cRQfC-SVpiQB=kf=$nVbuVWz7R!k+Sfh>$z>AmYf! z50U>?JcwFy`9t)*t_LwKTR+6^%Xtu&GW|pRJiiACzFP_s+p`mrbf*<0r~4+P@KzM0 zy6Y#TzKtqKR~Jl3KWkHv$@V!RbFExK*0ZY#+0(2(JC!H1&!=?{uU4}B={uY6GQ?|wm<#k7R7dj|_DBq|ar_AM@`{1KHwo91g?*Aq=iSwkuE!2pB;Ghy(!D4ek#B literal 0 HcmV?d00001 diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Eastern b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Eastern new file mode 100644 index 0000000000000000000000000000000000000000..7590b6ef9bf8317fc41e10bef43ddc76e856d769 GIT binary patch literal 1267 zcmcJPYfuyf5XTQBKpq0w848j?g`jvQBF_>Nx(+%)9`cZ2HSp$uV)JoAAy%LSGsQGA zQ0bhZyd)8M24TlTLWagvP7!<@3n3|pF5rV8kHD{e;zR$P-_Cz__P-xDBvQUh@L%c8 zj^>!t$SiZ-Tv=>`$A1}t9}f$#;D?KFB5nXrrr)E&_%m4KQUb-nom?W!f>P(xT&gXi zvc=zUnI@Bdnm|6Sl2f@lh|ehfsiJy4pG|Y3%41uxO6CXEsm@p{)2CH6d80vyXy~o_xUIXU_uk)`Jmr2#uz)d+-)LeL!Tat3AHRAxE4^U8BYz+S< z3a55yDqb-2pbn>K?3fILPE&8}>~V+RzhdmNdxTvuP3nDveAW9lT?=jJ?iEdR-KCU! z1O?P9%;sK7ryJT5yxAN_w=`LJ`_z}9Q6*qsRxFTGiv99;VIWO}e@a%uV6+9^30p%$ zVkiE~)tv6yoAJFR<20;4#=}pp(#VjS?|0YHXnQR`Xi~$&iZ0~iwJ?@bgX0JDVInCH zAH}4=HiTfyM#rMS?%5Eho_vJoE!V>*N;y(h@DS%!-mGRW*y zI-7sLi!8F@_{Eg>Xt7+(FGV<#P~yN#+)e0Z2V=Ihb%3RYqr6Pl7?zD2p;iAVSYNr1 z%UdpiP30f>NNX$2HX(K$PZ>YmZpMn=%=%+dT!&VhOJgx&TDq(N{WGbda%_?ghBg;AlTXh zLqaHAc?du2@q*Me86K#& zfwX7|9{f%K0-gDl?t*y+=6C-8+@6`a(5xevnQ1sH(0lF;pLY{qpAdm>@GN1o1cuDL IGMzd81%8hW?*IS* literal 0 HcmV?d00001 diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Hawaii b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Hawaii new file mode 100644 index 0000000000000000000000000000000000000000..7537ac54c62ab6e547b0b7d8c1ece44e34c36501 GIT binary patch literal 101 zcmWHE%1mRx1k6Ao5C#EOAO^8HcC$Kr>{cv{INfP`;!>ig#ns+o4@L$?2B!c2b0QcR b{{OGaU}X9Kzc_(`!6P_?!NVm4s0#!DEyNW0 literal 0 HcmV?d00001 diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Indiana-Starke b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Indiana-Starke new file mode 100644 index 0000000000000000000000000000000000000000..1145946b45aa9f548eee360e159a862ce7b01b86 GIT binary patch literal 869 zcmb7+Z7dW37{{MOc|GZcP@ST>6_!3IZES6ro$^x7AyO)FN*-@lSJKng$cLtAURond zmNi4oTU!XVwq|uHQOHYV>fA#ph>> zlvKD->Ej=GC(Dw`Zhgd;SGDxUX$IfKnDV>OchJ4Dli#~HKo3-NuXQo>4&LAo+B*8! zn#z3xh16ep9S53~^eHC=2TLMpNG`?UOfMRd?848{4m29($zy(=@MX7%$HgKTpSIx% zV}J?OEPovvhHu>+tbX1BlPyE2sU9RQZO5tHHkvt-jX!7O;Mcf>=XxaY`-L-W8=XOS zU&v4-1VOfj4bE!7Fxdi)V$5k-@FXtZt0rT&*JylAOr};3(X{F=nDI?CAIv9<-WnFR zrjun;9na9`Fo-3OE`Yy!C-1vmNc+13F(5-pf%R?}6ctIq1*`CY zrxzVepTUsz4kQijM(Lb@WbTb98x=vg=q-mo1BlSp^P%!#h#V;5s4E?CxcNLspQwN% zB~g4dpp9a(m3YjxoQ}su;t63E#rk<+tU8|J#10tO=}&TF0m`dfC}C^_PZdbu^eY`F zDxBd=^$;h?gn+s2ob0ZFl%#u{YOR8_plnXls!8Edj*5X-bj~&l&o$SQayA~%m*mrh z9)HZpOs9*DE|?h|Mwf~#5d6&T;pwm6L14awkWPuj* Y1S@YJDR_tI9j14%6nynrFTr2@0gVMd#sB~S literal 0 HcmV?d00001 diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Michigan b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/US/Michigan new file mode 100644 index 0000000000000000000000000000000000000000..8b11517f1ba4d1c3fcd595acfd9ea68ecfd9d429 GIT binary patch literal 811 zcmd6l|1Z>W9LGN-MH|=oYrIb z9qS&rXS54jxF@F=PI~;nNzl?OK{uP`I!GIE1GS&R$TWNw&HP5d?2HpGv+V*4t`jZT zNwB0kw0eDstcT>de6W^muAX4F?FD4lkk3|B?xK|n5wlP8A_p;_tqQTC)qG3l=*|Zx za}9Ggwgl(z7U=R`1FjQaaLw>Ixb;56wH>{%PRX(L$D6@j_JMg6_Rt2wDD#XtOB)@o zFrHT#@fIH<-$F+Gnak+)If%T~^|)zD3O*_YZtf2R-|ATOYj%V!ayj!a{RIIcG25E- z4g@@J7U-{rATw(g?DB?!=f1HJ?R^Rzn_yvYRV3{BirelTqwP)4amV>w3NPuyh}s(1 znb3lfc{vc}tHkK2NQhqOW+I<#5=}KSv2_HA`-@qO#)D!nG+^AzaFA3LVf-C;NXV36 zVyg-47W!h+p*cu)wL_`wF-Wxwm?F3aDIaZEs@oW)j?S~R#coRPnqnC{Ep038$%D=lfGGKUdXo={2Ui?gTpz{q%siSg3^;&i$`Pma^+u3zL#bh^P?oViZ-XvoOw ek8S_hK29R#B9o(R%QG1=qB5^X04jZH~{sSzU*GZz& zGPc47vbt4));(8fY`2bWI_kl;A(QRy>cIX+5#sqw7?*Pb#~)V11Z@&dj8T9?&>D2~ z^MFYnv(d>tkS1GMqqDh$oWIRtmlswf)?4zF#*gG$@qwr6TF6b9g42$dk$a>Or|)<_`0uJQWE zaTJo4%^U74r_eYphvmD`#-+g=E|^n64J_v+1a#JTFKiqT1v9bW3?if)Sm^`NTj4`QL$EJ zPug2@-tp!u?aYtHU9EPoTkyj@Wj&A_<$@`>de|!)!hOlrkm}Hd`$O|#zhQs{-%1iX zpYb85JUUcY&xiX2I#Q_PqwOk6%gE&P8aZXetNGYDF@f3dF(36u{uckkH5zXgnSs$* bz+f@rmLuCHBtQuv5yM0e6Q(phk(r5KN5fXLdl{_0=gd-=S)yx*T{iB2o{R^IN( zgGU$KcsiI)#PN|j3Gp@sA3e}XH%kM#VdRJ0hV(IT-&uf7CDruMd6%251dnXB{J82g z*(??Or1Vd+n+o}wqL^lSN@$$7E<1NwK{_0I^k<*Vsz<+)vBh zeT~rFwFSSlX`!bn6aTv&2hQ_Kbe&XyV4oa?JN&?_$QOI%jV14N8TU@|p*}OkESm6| zM7w6Q7;cfc`V#uQJxjiJGy6TL2Y+ih|8T(!{i@C&>@SD@rGx{D^I@QF9sa0U43c;i z4w^az2FoKbU_>$v5eHzPS2zWBgz?a4gGt&jh=VSFreQT*Jp5=gp?)0xwD}^9Q2XP^ z?1wNa{0)wt`wxtf+(ntf1Tv?CN9T zSvSWV+yygo9`Q_L70pVp@a&8~C^nRNPV8Em^S%+4!8<|Ocn;(J*Fb#jUYzS#2=flr z^8EYRv|vL8FZ_ExB`hoC#62ODG)=>c^gzkdXjU!mAXQHgtHbY+`ehWR40{JDSEZZ8G95FdTw>No zT1jtv#YF*?RAi~=;w~foW-{~dO;~T;d>Nx(+%)9`cZ2HSp$uV)JoAAy%LSGsQGA zQ0bhZyd)8M24TlTLWagvP7!<@3n3|pF5rV8kHD{e;zR$P-_Cz__P-xDBvQUh@L%c8 zj^>!t$SiZ-Tv=>`$A1}t9}f$#;D?KFB5nXrrr)E&_%m4KQUb-nom?W!f>P(xT&gXi zvc=zUnI@Bdnm|6Sl2f@lh|ehfsiJy4pG|Y3%41uxO6CXEsm@p{)2CH6d80vyXy~o_xUIXU_uk)`Jmr2#uz)d+-)LeL!Tat3AHRAxE4^U8BYz+S< z3a55yDqb-2pbn>K?3fILPE&8}>~V+RzhdmNdxTvuP3nDveAW9lT?=jJ?iEdR-KCU! z1O?P9%;sK7ryJT5yxAN_w=`LJ`_z}9Q6*qsRxFTGiv99;VIWO}e@a%uV6+9^30p%$ zVkiE~)tv6yoAJFR<20;4#=}pp(#VjS?|0YHXnQR`Xi~$&iZ0~iwJ?@bgX0JDVInCH zAH}4=HiTfyM#rMS?%5Eho_vJoE!V>*N;y(h@DS%!-mGRW*y zI-7sLi!8F@_{Eg>Xt7+(FGV<#P~yN#+)e0Z2V=Ihb%3RYqr6Pl7?zD2p;iAVSYNr1 z%UdpiP30f>NNX$2HX(K$PZ>YmZpMn=%=%+dT!&VhOJgx&TDq(N{WGbda%_?ghBg;AlTXh zLqaHAc?du2@q*Me86K#& zfwX7|9{f%K0-gDl?t*y+=6C-8+@6`a(5xevnQ1sH(0lF;pLY{qpAdm>@GN1o1cuDL IGMzd81%8hW?*IS* literal 0 HcmV?d00001 diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/zone.tab b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/zone.tab new file mode 100644 index 0000000..923d6ac --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/32-bit/zone.tab @@ -0,0 +1,452 @@ +# TZ zone descriptions +# +# This file is in the public domain, so clarified as of +# 2009-05-17 by Arthur David Olson. +# +# From Paul Eggert (2013-08-14): +# +# This file contains a table where each row stands for an area that is +# the intersection of a region identified by a country code and of a +# zone where civil clocks have agreed since 1970. The columns of the +# table are as follows: +# +# 1. ISO 3166 2-character country code. See the file 'iso3166.tab'. +# 2. Latitude and longitude of the area's principal location +# in ISO 6709 sign-degrees-minutes-seconds format, +# either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS, +# first latitude (+ is north), then longitude (+ is east). +# 3. Zone name used in value of TZ environment variable. +# Please see the 'Theory' file for how zone names are chosen. +# If multiple zones overlap a country, each has a row in the +# table, with column 1 being duplicated. +# 4. Comments; present if and only if the country has multiple rows. +# +# Columns are separated by a single tab. +# The table is sorted first by country, then an order within the country that +# (1) makes some geographical sense, and +# (2) puts the most populous areas first, where that does not contradict (1). +# +# Lines beginning with '#' are comments. +# +# This table is intended as an aid for users, to help them select time +# zone data appropriate for their practical needs. It is not intended +# to take or endorse any position on legal or territorial claims. +# +#country- +#code coordinates TZ comments +AD +4230+00131 Europe/Andorra +AE +2518+05518 Asia/Dubai +AF +3431+06912 Asia/Kabul +AG +1703-06148 America/Antigua +AI +1812-06304 America/Anguilla +AL +4120+01950 Europe/Tirane +AM +4011+04430 Asia/Yerevan +AO -0848+01314 Africa/Luanda +AQ -7750+16636 Antarctica/McMurdo McMurdo, South Pole, Scott (New Zealand time) +AQ -6734-06808 Antarctica/Rothera Rothera Station, Adelaide Island +AQ -6448-06406 Antarctica/Palmer Palmer Station, Anvers Island +AQ -6736+06253 Antarctica/Mawson Mawson Station, Holme Bay +AQ -6835+07758 Antarctica/Davis Davis Station, Vestfold Hills +AQ -6617+11031 Antarctica/Casey Casey Station, Bailey Peninsula +AQ -7824+10654 Antarctica/Vostok Vostok Station, Lake Vostok +AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville Station, Terre Adelie +AQ -690022+0393524 Antarctica/Syowa Syowa Station, E Ongul I +AQ -720041+0023206 Antarctica/Troll Troll Station, Queen Maud Land +AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF) +AR -3124-06411 America/Argentina/Cordoba most locations (CB, CC, CN, ER, FM, MN, SE, SF) +AR -2447-06525 America/Argentina/Salta (SA, LP, NQ, RN) +AR -2411-06518 America/Argentina/Jujuy Jujuy (JY) +AR -2649-06513 America/Argentina/Tucuman Tucuman (TM) +AR -2828-06547 America/Argentina/Catamarca Catamarca (CT), Chubut (CH) +AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR) +AR -3132-06831 America/Argentina/San_Juan San Juan (SJ) +AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ) +AR -3319-06621 America/Argentina/San_Luis San Luis (SL) +AR -5138-06913 America/Argentina/Rio_Gallegos Santa Cruz (SC) +AR -5448-06818 America/Argentina/Ushuaia Tierra del Fuego (TF) +AS -1416-17042 Pacific/Pago_Pago +AT +4813+01620 Europe/Vienna +AU -3133+15905 Australia/Lord_Howe Lord Howe Island +AU -5430+15857 Antarctica/Macquarie Macquarie Island +AU -4253+14719 Australia/Hobart Tasmania - most locations +AU -3956+14352 Australia/Currie Tasmania - King Island +AU -3749+14458 Australia/Melbourne Victoria +AU -3352+15113 Australia/Sydney New South Wales - most locations +AU -3157+14127 Australia/Broken_Hill New South Wales - Yancowinna +AU -2728+15302 Australia/Brisbane Queensland - most locations +AU -2016+14900 Australia/Lindeman Queensland - Holiday Islands +AU -3455+13835 Australia/Adelaide South Australia +AU -1228+13050 Australia/Darwin Northern Territory +AU -3157+11551 Australia/Perth Western Australia - most locations +AU -3143+12852 Australia/Eucla Western Australia - Eucla area +AW +1230-06958 America/Aruba +AX +6006+01957 Europe/Mariehamn +AZ +4023+04951 Asia/Baku +BA +4352+01825 Europe/Sarajevo +BB +1306-05937 America/Barbados +BD +2343+09025 Asia/Dhaka +BE +5050+00420 Europe/Brussels +BF +1222-00131 Africa/Ouagadougou +BG +4241+02319 Europe/Sofia +BH +2623+05035 Asia/Bahrain +BI -0323+02922 Africa/Bujumbura +BJ +0629+00237 Africa/Porto-Novo +BL +1753-06251 America/St_Barthelemy +BM +3217-06446 Atlantic/Bermuda +BN +0456+11455 Asia/Brunei +BO -1630-06809 America/La_Paz +BQ +120903-0681636 America/Kralendijk +BR -0351-03225 America/Noronha Atlantic islands +BR -0127-04829 America/Belem Amapa, E Para +BR -0343-03830 America/Fortaleza NE Brazil (MA, PI, CE, RN, PB) +BR -0803-03454 America/Recife Pernambuco +BR -0712-04812 America/Araguaina Tocantins +BR -0940-03543 America/Maceio Alagoas, Sergipe +BR -1259-03831 America/Bahia Bahia +BR -2332-04637 America/Sao_Paulo S & SE Brazil (GO, DF, MG, ES, RJ, SP, PR, SC, RS) +BR -2027-05437 America/Campo_Grande Mato Grosso do Sul +BR -1535-05605 America/Cuiaba Mato Grosso +BR -0226-05452 America/Santarem W Para +BR -0846-06354 America/Porto_Velho Rondonia +BR +0249-06040 America/Boa_Vista Roraima +BR -0308-06001 America/Manaus E Amazonas +BR -0640-06952 America/Eirunepe W Amazonas +BR -0958-06748 America/Rio_Branco Acre +BS +2505-07721 America/Nassau +BT +2728+08939 Asia/Thimphu +BW -2439+02555 Africa/Gaborone +BY +5354+02734 Europe/Minsk +BZ +1730-08812 America/Belize +CA +4734-05243 America/St_Johns Newfoundland Time, including SE Labrador +CA +4439-06336 America/Halifax Atlantic Time - Nova Scotia (most places), PEI +CA +4612-05957 America/Glace_Bay Atlantic Time - Nova Scotia - places that did not observe DST 1966-1971 +CA +4606-06447 America/Moncton Atlantic Time - New Brunswick +CA +5320-06025 America/Goose_Bay Atlantic Time - Labrador - most locations +CA +5125-05707 America/Blanc-Sablon Atlantic Standard Time - Quebec - Lower North Shore +CA +4339-07923 America/Toronto Eastern Time - Ontario & Quebec - most locations +CA +4901-08816 America/Nipigon Eastern Time - Ontario & Quebec - places that did not observe DST 1967-1973 +CA +4823-08915 America/Thunder_Bay Eastern Time - Thunder Bay, Ontario +CA +6344-06828 America/Iqaluit Eastern Time - east Nunavut - most locations +CA +6608-06544 America/Pangnirtung Eastern Time - Pangnirtung, Nunavut +CA +744144-0944945 America/Resolute Central Standard Time - Resolute, Nunavut +CA +484531-0913718 America/Atikokan Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut +CA +624900-0920459 America/Rankin_Inlet Central Time - central Nunavut +CA +4953-09709 America/Winnipeg Central Time - Manitoba & west Ontario +CA +4843-09434 America/Rainy_River Central Time - Rainy River & Fort Frances, Ontario +CA +5024-10439 America/Regina Central Standard Time - Saskatchewan - most locations +CA +5017-10750 America/Swift_Current Central Standard Time - Saskatchewan - midwest +CA +5333-11328 America/Edmonton Mountain Time - Alberta, east British Columbia & west Saskatchewan +CA +690650-1050310 America/Cambridge_Bay Mountain Time - west Nunavut +CA +6227-11421 America/Yellowknife Mountain Time - central Northwest Territories +CA +682059-1334300 America/Inuvik Mountain Time - west Northwest Territories +CA +4906-11631 America/Creston Mountain Standard Time - Creston, British Columbia +CA +5946-12014 America/Dawson_Creek Mountain Standard Time - Dawson Creek & Fort Saint John, British Columbia +CA +4916-12307 America/Vancouver Pacific Time - west British Columbia +CA +6043-13503 America/Whitehorse Pacific Time - south Yukon +CA +6404-13925 America/Dawson Pacific Time - north Yukon +CC -1210+09655 Indian/Cocos +CD -0418+01518 Africa/Kinshasa west Dem. Rep. of Congo +CD -1140+02728 Africa/Lubumbashi east Dem. Rep. of Congo +CF +0422+01835 Africa/Bangui +CG -0416+01517 Africa/Brazzaville +CH +4723+00832 Europe/Zurich +CI +0519-00402 Africa/Abidjan +CK -2114-15946 Pacific/Rarotonga +CL -3327-07040 America/Santiago most locations +CL -2709-10926 Pacific/Easter Easter Island & Sala y Gomez +CM +0403+00942 Africa/Douala +CN +3114+12128 Asia/Shanghai east China - Beijing, Guangdong, Shanghai, etc. +CN +4545+12641 Asia/Harbin Heilongjiang (except Mohe), Jilin +CN +2934+10635 Asia/Chongqing central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc. +CN +4348+08735 Asia/Urumqi most of Tibet & Xinjiang +CN +3929+07559 Asia/Kashgar west Tibet & Xinjiang +CO +0436-07405 America/Bogota +CR +0956-08405 America/Costa_Rica +CU +2308-08222 America/Havana +CV +1455-02331 Atlantic/Cape_Verde +CW +1211-06900 America/Curacao +CX -1025+10543 Indian/Christmas +CY +3510+03322 Asia/Nicosia +CZ +5005+01426 Europe/Prague +DE +5230+01322 Europe/Berlin most locations +DE +4742+00841 Europe/Busingen Busingen +DJ +1136+04309 Africa/Djibouti +DK +5540+01235 Europe/Copenhagen +DM +1518-06124 America/Dominica +DO +1828-06954 America/Santo_Domingo +DZ +3647+00303 Africa/Algiers +EC -0210-07950 America/Guayaquil mainland +EC -0054-08936 Pacific/Galapagos Galapagos Islands +EE +5925+02445 Europe/Tallinn +EG +3003+03115 Africa/Cairo +EH +2709-01312 Africa/El_Aaiun +ER +1520+03853 Africa/Asmara +ES +4024-00341 Europe/Madrid mainland +ES +3553-00519 Africa/Ceuta Ceuta & Melilla +ES +2806-01524 Atlantic/Canary Canary Islands +ET +0902+03842 Africa/Addis_Ababa +FI +6010+02458 Europe/Helsinki +FJ -1808+17825 Pacific/Fiji +FK -5142-05751 Atlantic/Stanley +FM +0725+15147 Pacific/Chuuk Chuuk (Truk) and Yap +FM +0658+15813 Pacific/Pohnpei Pohnpei (Ponape) +FM +0519+16259 Pacific/Kosrae Kosrae +FO +6201-00646 Atlantic/Faroe +FR +4852+00220 Europe/Paris +GA +0023+00927 Africa/Libreville +GB +513030-0000731 Europe/London +GD +1203-06145 America/Grenada +GE +4143+04449 Asia/Tbilisi +GF +0456-05220 America/Cayenne +GG +4927-00232 Europe/Guernsey +GH +0533-00013 Africa/Accra +GI +3608-00521 Europe/Gibraltar +GL +6411-05144 America/Godthab most locations +GL +7646-01840 America/Danmarkshavn east coast, north of Scoresbysund +GL +7029-02158 America/Scoresbysund Scoresbysund / Ittoqqortoormiit +GL +7634-06847 America/Thule Thule / Pituffik +GM +1328-01639 Africa/Banjul +GN +0931-01343 Africa/Conakry +GP +1614-06132 America/Guadeloupe +GQ +0345+00847 Africa/Malabo +GR +3758+02343 Europe/Athens +GS -5416-03632 Atlantic/South_Georgia +GT +1438-09031 America/Guatemala +GU +1328+14445 Pacific/Guam +GW +1151-01535 Africa/Bissau +GY +0648-05810 America/Guyana +HK +2217+11409 Asia/Hong_Kong +HN +1406-08713 America/Tegucigalpa +HR +4548+01558 Europe/Zagreb +HT +1832-07220 America/Port-au-Prince +HU +4730+01905 Europe/Budapest +ID -0610+10648 Asia/Jakarta Java & Sumatra +ID -0002+10920 Asia/Pontianak west & central Borneo +ID -0507+11924 Asia/Makassar east & south Borneo, Sulawesi (Celebes), Bali, Nusa Tengarra, west Timor +ID -0232+14042 Asia/Jayapura west New Guinea (Irian Jaya) & Malukus (Moluccas) +IE +5320-00615 Europe/Dublin +IL +314650+0351326 Asia/Jerusalem +IM +5409-00428 Europe/Isle_of_Man +IN +2232+08822 Asia/Kolkata +IO -0720+07225 Indian/Chagos +IQ +3321+04425 Asia/Baghdad +IR +3540+05126 Asia/Tehran +IS +6409-02151 Atlantic/Reykjavik +IT +4154+01229 Europe/Rome +JE +4912-00207 Europe/Jersey +JM +175805-0764736 America/Jamaica +JO +3157+03556 Asia/Amman +JP +353916+1394441 Asia/Tokyo +KE -0117+03649 Africa/Nairobi +KG +4254+07436 Asia/Bishkek +KH +1133+10455 Asia/Phnom_Penh +KI +0125+17300 Pacific/Tarawa Gilbert Islands +KI -0308-17105 Pacific/Enderbury Phoenix Islands +KI +0152-15720 Pacific/Kiritimati Line Islands +KM -1141+04316 Indian/Comoro +KN +1718-06243 America/St_Kitts +KP +3901+12545 Asia/Pyongyang +KR +3733+12658 Asia/Seoul +KW +2920+04759 Asia/Kuwait +KY +1918-08123 America/Cayman +KZ +4315+07657 Asia/Almaty most locations +KZ +4448+06528 Asia/Qyzylorda Qyzylorda (Kyzylorda, Kzyl-Orda) +KZ +5017+05710 Asia/Aqtobe Aqtobe (Aktobe) +KZ +4431+05016 Asia/Aqtau Atyrau (Atirau, Gur'yev), Mangghystau (Mankistau) +KZ +5113+05121 Asia/Oral West Kazakhstan +LA +1758+10236 Asia/Vientiane +LB +3353+03530 Asia/Beirut +LC +1401-06100 America/St_Lucia +LI +4709+00931 Europe/Vaduz +LK +0656+07951 Asia/Colombo +LR +0618-01047 Africa/Monrovia +LS -2928+02730 Africa/Maseru +LT +5441+02519 Europe/Vilnius +LU +4936+00609 Europe/Luxembourg +LV +5657+02406 Europe/Riga +LY +3254+01311 Africa/Tripoli +MA +3339-00735 Africa/Casablanca +MC +4342+00723 Europe/Monaco +MD +4700+02850 Europe/Chisinau +ME +4226+01916 Europe/Podgorica +MF +1804-06305 America/Marigot +MG -1855+04731 Indian/Antananarivo +MH +0709+17112 Pacific/Majuro most locations +MH +0905+16720 Pacific/Kwajalein Kwajalein +MK +4159+02126 Europe/Skopje +ML +1239-00800 Africa/Bamako +MM +1647+09610 Asia/Rangoon +MN +4755+10653 Asia/Ulaanbaatar most locations +MN +4801+09139 Asia/Hovd Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan +MN +4804+11430 Asia/Choibalsan Dornod, Sukhbaatar +MO +2214+11335 Asia/Macau +MP +1512+14545 Pacific/Saipan +MQ +1436-06105 America/Martinique +MR +1806-01557 Africa/Nouakchott +MS +1643-06213 America/Montserrat +MT +3554+01431 Europe/Malta +MU -2010+05730 Indian/Mauritius +MV +0410+07330 Indian/Maldives +MW -1547+03500 Africa/Blantyre +MX +1924-09909 America/Mexico_City Central Time - most locations +MX +2105-08646 America/Cancun Central Time - Quintana Roo +MX +2058-08937 America/Merida Central Time - Campeche, Yucatan +MX +2540-10019 America/Monterrey Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border +MX +2550-09730 America/Matamoros US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border +MX +2313-10625 America/Mazatlan Mountain Time - S Baja, Nayarit, Sinaloa +MX +2838-10605 America/Chihuahua Mexican Mountain Time - Chihuahua away from US border +MX +2934-10425 America/Ojinaga US Mountain Time - Chihuahua near US border +MX +2904-11058 America/Hermosillo Mountain Standard Time - Sonora +MX +3232-11701 America/Tijuana US Pacific Time - Baja California near US border +MX +3018-11452 America/Santa_Isabel Mexican Pacific Time - Baja California away from US border +MX +2048-10515 America/Bahia_Banderas Mexican Central Time - Bahia de Banderas +MY +0310+10142 Asia/Kuala_Lumpur peninsular Malaysia +MY +0133+11020 Asia/Kuching Sabah & Sarawak +MZ -2558+03235 Africa/Maputo +NA -2234+01706 Africa/Windhoek +NC -2216+16627 Pacific/Noumea +NE +1331+00207 Africa/Niamey +NF -2903+16758 Pacific/Norfolk +NG +0627+00324 Africa/Lagos +NI +1209-08617 America/Managua +NL +5222+00454 Europe/Amsterdam +NO +5955+01045 Europe/Oslo +NP +2743+08519 Asia/Kathmandu +NR -0031+16655 Pacific/Nauru +NU -1901-16955 Pacific/Niue +NZ -3652+17446 Pacific/Auckland most locations +NZ -4357-17633 Pacific/Chatham Chatham Islands +OM +2336+05835 Asia/Muscat +PA +0858-07932 America/Panama +PE -1203-07703 America/Lima +PF -1732-14934 Pacific/Tahiti Society Islands +PF -0900-13930 Pacific/Marquesas Marquesas Islands +PF -2308-13457 Pacific/Gambier Gambier Islands +PG -0930+14710 Pacific/Port_Moresby +PH +1435+12100 Asia/Manila +PK +2452+06703 Asia/Karachi +PL +5215+02100 Europe/Warsaw +PM +4703-05620 America/Miquelon +PN -2504-13005 Pacific/Pitcairn +PR +182806-0660622 America/Puerto_Rico +PS +3130+03428 Asia/Gaza Gaza Strip +PS +313200+0350542 Asia/Hebron West Bank +PT +3843-00908 Europe/Lisbon mainland +PT +3238-01654 Atlantic/Madeira Madeira Islands +PT +3744-02540 Atlantic/Azores Azores +PW +0720+13429 Pacific/Palau +PY -2516-05740 America/Asuncion +QA +2517+05132 Asia/Qatar +RE -2052+05528 Indian/Reunion +RO +4426+02606 Europe/Bucharest +RS +4450+02030 Europe/Belgrade +RU +5443+02030 Europe/Kaliningrad Moscow-01 - Kaliningrad +RU +5545+03735 Europe/Moscow Moscow+00 - west Russia +RU +4844+04425 Europe/Volgograd Moscow+00 - Caspian Sea +RU +5312+05009 Europe/Samara Moscow+00 - Samara, Udmurtia +RU +4457+03406 Europe/Simferopol Moscow+00 - Crimea +RU +5651+06036 Asia/Yekaterinburg Moscow+02 - Urals +RU +5500+07324 Asia/Omsk Moscow+03 - west Siberia +RU +5502+08255 Asia/Novosibirsk Moscow+03 - Novosibirsk +RU +5345+08707 Asia/Novokuznetsk Moscow+03 - Novokuznetsk +RU +5601+09250 Asia/Krasnoyarsk Moscow+04 - Yenisei River +RU +5216+10420 Asia/Irkutsk Moscow+05 - Lake Baikal +RU +6200+12940 Asia/Yakutsk Moscow+06 - Lena River +RU +623923+1353314 Asia/Khandyga Moscow+06 - Tomponsky, Ust-Maysky +RU +4310+13156 Asia/Vladivostok Moscow+07 - Amur River +RU +4658+14242 Asia/Sakhalin Moscow+07 - Sakhalin Island +RU +643337+1431336 Asia/Ust-Nera Moscow+07 - Oymyakonsky +RU +5934+15048 Asia/Magadan Moscow+08 - Magadan +RU +5301+15839 Asia/Kamchatka Moscow+08 - Kamchatka +RU +6445+17729 Asia/Anadyr Moscow+08 - Bering Sea +RW -0157+03004 Africa/Kigali +SA +2438+04643 Asia/Riyadh +SB -0932+16012 Pacific/Guadalcanal +SC -0440+05528 Indian/Mahe +SD +1536+03232 Africa/Khartoum +SE +5920+01803 Europe/Stockholm +SG +0117+10351 Asia/Singapore +SH -1555-00542 Atlantic/St_Helena +SI +4603+01431 Europe/Ljubljana +SJ +7800+01600 Arctic/Longyearbyen +SK +4809+01707 Europe/Bratislava +SL +0830-01315 Africa/Freetown +SM +4355+01228 Europe/San_Marino +SN +1440-01726 Africa/Dakar +SO +0204+04522 Africa/Mogadishu +SR +0550-05510 America/Paramaribo +SS +0451+03136 Africa/Juba +ST +0020+00644 Africa/Sao_Tome +SV +1342-08912 America/El_Salvador +SX +180305-0630250 America/Lower_Princes +SY +3330+03618 Asia/Damascus +SZ -2618+03106 Africa/Mbabane +TC +2128-07108 America/Grand_Turk +TD +1207+01503 Africa/Ndjamena +TF -492110+0701303 Indian/Kerguelen +TG +0608+00113 Africa/Lome +TH +1345+10031 Asia/Bangkok +TJ +3835+06848 Asia/Dushanbe +TK -0922-17114 Pacific/Fakaofo +TL -0833+12535 Asia/Dili +TM +3757+05823 Asia/Ashgabat +TN +3648+01011 Africa/Tunis +TO -2110-17510 Pacific/Tongatapu +TR +4101+02858 Europe/Istanbul +TT +1039-06131 America/Port_of_Spain +TV -0831+17913 Pacific/Funafuti +TW +2503+12130 Asia/Taipei +TZ -0648+03917 Africa/Dar_es_Salaam +UA +5026+03031 Europe/Kiev most locations +UA +4837+02218 Europe/Uzhgorod Ruthenia +UA +4750+03510 Europe/Zaporozhye Zaporozh'ye, E Lugansk / Zaporizhia, E Luhansk +UG +0019+03225 Africa/Kampala +UM +1645-16931 Pacific/Johnston Johnston Atoll +UM +2813-17722 Pacific/Midway Midway Islands +UM +1917+16637 Pacific/Wake Wake Island +US +404251-0740023 America/New_York Eastern Time +US +421953-0830245 America/Detroit Eastern Time - Michigan - most locations +US +381515-0854534 America/Kentucky/Louisville Eastern Time - Kentucky - Louisville area +US +364947-0845057 America/Kentucky/Monticello Eastern Time - Kentucky - Wayne County +US +394606-0860929 America/Indiana/Indianapolis Eastern Time - Indiana - most locations +US +384038-0873143 America/Indiana/Vincennes Eastern Time - Indiana - Daviess, Dubois, Knox & Martin Counties +US +410305-0863611 America/Indiana/Winamac Eastern Time - Indiana - Pulaski County +US +382232-0862041 America/Indiana/Marengo Eastern Time - Indiana - Crawford County +US +382931-0871643 America/Indiana/Petersburg Eastern Time - Indiana - Pike County +US +384452-0850402 America/Indiana/Vevay Eastern Time - Indiana - Switzerland County +US +415100-0873900 America/Chicago Central Time +US +375711-0864541 America/Indiana/Tell_City Central Time - Indiana - Perry County +US +411745-0863730 America/Indiana/Knox Central Time - Indiana - Starke County +US +450628-0873651 America/Menominee Central Time - Michigan - Dickinson, Gogebic, Iron & Menominee Counties +US +470659-1011757 America/North_Dakota/Center Central Time - North Dakota - Oliver County +US +465042-1012439 America/North_Dakota/New_Salem Central Time - North Dakota - Morton County (except Mandan area) +US +471551-1014640 America/North_Dakota/Beulah Central Time - North Dakota - Mercer County +US +394421-1045903 America/Denver Mountain Time +US +433649-1161209 America/Boise Mountain Time - south Idaho & east Oregon +US +332654-1120424 America/Phoenix Mountain Standard Time - Arizona (except Navajo) +US +340308-1181434 America/Los_Angeles Pacific Time +US +611305-1495401 America/Anchorage Alaska Time +US +581807-1342511 America/Juneau Alaska Time - Alaska panhandle +US +571035-1351807 America/Sitka Alaska Time - southeast Alaska panhandle +US +593249-1394338 America/Yakutat Alaska Time - Alaska panhandle neck +US +643004-1652423 America/Nome Alaska Time - west Alaska +US +515248-1763929 America/Adak Aleutian Islands +US +550737-1313435 America/Metlakatla Metlakatla Time - Annette Island +US +211825-1575130 Pacific/Honolulu Hawaii +UY -3453-05611 America/Montevideo +UZ +3940+06648 Asia/Samarkand west Uzbekistan +UZ +4120+06918 Asia/Tashkent east Uzbekistan +VA +415408+0122711 Europe/Vatican +VC +1309-06114 America/St_Vincent +VE +1030-06656 America/Caracas +VG +1827-06437 America/Tortola +VI +1821-06456 America/St_Thomas +VN +1045+10640 Asia/Ho_Chi_Minh +VU -1740+16825 Pacific/Efate +WF -1318-17610 Pacific/Wallis +WS -1350-17144 Pacific/Apia +YE +1245+04512 Asia/Aden +YT -1247+04514 Indian/Mayotte +ZA -2615+02800 Africa/Johannesburg +ZM -1525+02817 Africa/Lusaka +ZW -1750+03103 Africa/Harare diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/Factory b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/Factory new file mode 100644 index 0000000000000000000000000000000000000000..6e6c452ee1f2bbd4941da75c6935b9f9180538b9 GIT binary patch literal 264 zcmWHE%1kq2zyORu5fFv}5Ze&K@ySn4%uy)G%uQ9O%Fjzx$So}{QAkQvC{8WW)h$j1 oie@G&u+M{XsK zHixs(agMDvX=l2Xu0^-3wTU@~TMuKAx;2xfYdy`PxSj8*trs<4a{l}OKL^GO-u%A4 z+NNi+od28%^BZ2y5%Y3S*=Ih(hjId=i+*kytuK(jkCv#Zvs=8uH&;uiuh{E)d5H|^ zO!CfXEz+U&g@KvXi8?GlA>hso*X~z01tOv+bj0A8*Ym?geb<%YK;&09WK>`#51hE6L`R-{uxnT?^v{=zwtXiSXa6Y^)?5&YvERs~ zlv5&UYEmbA4vXaRuXV~qi%1>%K&M@PMWy$j&>3g8tEGEi((<(`mD#9dR$G=@RsPhHy;|nR&lb7Ym&m-yU&KS7dgQ}nUx<}DQ9ttDIq~R`aJ}mIap7&A z(D?`6RRxt7bz#FXRkZYNU0k$F75{WqmZbNIlFR31S=3HZc4k1XxmhR5U;j|A{k&6E z>^`X zwF8mz$?@}|?!Ybi)X;#~*f1hD^>>TS72oUn?vv{2^hn3-qY8v$GZP%mJvq#(Hb0aC@`Hsisb{#32{VQZk&n?lKGgrRQJR;g+CuMu( zY0(~x(;c~&RLA&lx^s?JokL@K$L(IVv;Td)>&tevd+!^1&so3PyRl2Z*q5tZAv0W| zGw<|-g}bNm2?pCb9mjk(JE6f~SBop$exvMfX4!ijUnf2o?AhlM_MWh|!sis`^FG0+ z%ID;l*6=CvIUBf?n@fJVxtZhQ!}y&=dXWWN&5DsFBWp$$jjS43 zHnMJH;mFF7r6X%c7LTkRSw6CUqyR_-kP=u;4XmaJNEMJWAay_rfm8x11yT#77)Ujc zav=3U3W8L`YD$9C#A=FyR0SyuQWvB!NM(@HAhkh?gH#784^khbKuCp<5+OCRnj#@p zLdt~H2`Lm(DWp_Lt&n0N)k4aJ)C(yXQZcJ38B#N=DH>8Wt0@~&H>7Y#<&e@LwL^-B zR1Ya1Qa_}CNCmB?gh&morie%tt)`4f9g#vJl|)L3)DkHsQca|sNIj8)A{9kSiqzC< zii%X#YRZb#)oKchR2C^MQd^|BNOh6&BK1WIj8qsYF;ZizDKb)Jt0^;5XR9eRQfZ{r zNUf1#Bh^OAjnvyQ`3?=48Fr_~9T7f_kK=r7A~_8e|2O0R+&uI>kJ6`AEX&BskZBc} KnHiZG((@OSrEiM> literal 0 HcmV?d00001 diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Aleutian b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Aleutian new file mode 100644 index 0000000000000000000000000000000000000000..b0a5dd60dc21f5afc16a0dec9ecd566e452edc91 GIT binary patch literal 2379 zcmciCZA{fw0LSsm8d3;=Iwk>ZM~@ZF3*4e|L1VW+uzq$ z*ZN$h>tDxXe&OW|nwPuxRr5JJP~@Ln{#*NGqa$xlKCNz@>~I1f`K0S;wG(tGR|a?I zI3XPybZBFhKddTShZkh|-5GJ({n~cFCwfkMMz1=N*DvY?-%tA&PT!DGdfdP0i)ne+ z@hKj6`d-eUELMI`3i%wXTyfon# zM=$;{OC?Tb>Lp*rss}!c(Mj*!P)oZ?sk!etBjUUWM-#SStWxqyE<9r zcz4R&tWfo^+b8o9mx;V9xiWt~L_BgPUOxKmWwAzO>&M2=h{p%x^xAih3%O%X7wkW+ z3M((_Cz?J~MXSHm#YF?E_}6Q)B<%xHa^buzi#jCA#>Qm%Y@2v$_-noHn**w%=Y(GW z`SYrB^N@Cql&h*WyY+^yR8^f=t9><#ly5#?*W_GRHJ5AT#-u2*@pPWtbnBX^dp|)w zGjm>S-ajv&ofs4KO*3-K$eW^};-+pqctUMWyQH_Z45_B53Ef<>TQ$!f(=Faw)pBm1 zZguCY*3l;2c4e`8;Yh!H(Vr)_cWsj|sRXg3rdYNgo);atUb%C}jOdK>$X%6M>B|A*`)gF59_^0pHxA?Awi*Gw|l}P z+;{K^1nRcBT!BEd;|dJ~Ivau_?02F4CEDI&_`2c)f&TWOCH9`YuEOV9Uv1u6^Ey6P zp}7|p`CJ91=2BWkYBIU|!sW{pf6 znKv?VWah}!k+~z2M`n*qADKUr03-uelLD*B0g?nH3rHG}JRpfcGJ&K5$pw-OBpXON zkbEEsv6_q^DY2TIAW1>8f}{n>3z8TlGe~NX+#tz8vV)`t$q$ksBtuAwtR_cDl8`JR zX+rXZBnrtCk}4!uNV1S@A?ZT$g(S>sGKQqgYI24o&1$lSqz%a%k~k!DNa~Q>A<09s zhole5ACf?;$sm$KtH~jfM61anl13ztNFtF;BB?}ji6j%rCX!AhpGZQHj3Ozunw%m@ zwVJFVX|^2SkNXjVd1Qo4W~PKCY%?)FLS>C z>6#0TQZm1OlnVTQ5y8O32!zZ)$jJ2n|Fm}u4FCVHUckum|Nq;uKkB@H%gRct^ z2Lo|<2+(i{2qEkw9-vCFlYT(;{0D+K7M=|t8stO}4RR)k200Z(gPaSZK~4tIAZLSV apwmG#$oU`|;@ zhGvVQk_wrKh~{WcDN2$`xS>(#ZeX~vnF$&Y>LFfYH$oy#!8hx0#iLzBjZ z$lu1(zQe=(Y9C(vX!|X5jlW*@)it$zegnPY{iAB-z7$#Y;_oIa;-FqVy40*0P%0mL zFIH>4LT^kQta9e` z)L%w+Rhx#l(VP8Rsx9HQb?#j*mDl2|&Z{U_TWi;nt-A}=*QYCFTXvbrFWMv97Z#X; zp(V0oeYh&jcujW3W|*QelVw-nII}zERsBuFr_7!X6ZM|zv1+eZAHDZTq}ungOCM}= zMI9Vj*A!2`EQfmhVh#^HEG4b?n;$~A$PvjlrQS=WwEQjeqid5sS}@HVD_g9OfAXd( z%TLoky)spmXAaXRlH%0K^lti8R3~*hp_M)}DBM&;hRfN`zUG{tul(FpOr`y=RbD-5 zeyKPqzm^o4s@+9$e)|b^A-i0gWjocyg@yXk+|}xGa+ba_VuAWCcD}yaJxTo@I9^vj z@{+mMFj`-)lW4A2C(4a;QRe26DEVVgd*jM&FYdKoMwWPq$ASx{#*7P6b4qbJbv_Z6P|rjciZ}gd17Ii?*4%?J(3G_&y3gAld&sxuQAE0 zcVLE&=-p36T;3v)9VVH`;-wPh6>Fk$W=nKcuzC8!#rm0&J}PETn(nhXNW~5xru)9v zSoI6w&!M=yg;9Vj^T$|0%tdlaVY>643Q6$gi z&oT*P*2sv=;pVxRLOpUpni|z1OOH+*rp9>9*JC5Qsj*e#b)sJ@mAF4zCwY3Pq;>v! zLd7Zd{CiO{@jJJfl-gbkf&y-FfRhYPsE?EtfjHmio>+jhyfI-g^I;m^kUx+dc#0B*H$u2HB@?oZW49 zJpLl?-}hpb{j9SWt8e|1{p)UbLQU6lWKSZy64{r?&P4VmvOAIeiR@5hk0QGi*{6|SL5B0Ct_!^kd1_A#=Pk-h9_cQdk|9qo=r z_B67qk$sKqY-DdEyBpcx$PP#LII_!;eU9vOWUo8g-Hz;cN4w*ZJ&){qN4xKlosaB& zWcMTcA87#60i*?vwg*TPkS-u?K>C0*0_gwIHYq(>yX|d&12{u(msa%Aq`~cAkspH z9wJR-=pxcahCVvlMk1X=T8Z=$X(rN5q@4`?L>kJ_QKY2|Jw=+z&{ap@3|&Ur%+O~?+h~SPBduoWHPURP+eo{Sej^P> zI*zm)={eGLr0b5h?F@Z)w2f!zyrXSBL+_F1Bi%>ZkMtk80gyWYxdo7W0J#Z}yTH-j z2FQKjXm13DJHgT33JmuGax*a84an`la6ce71j8MH+!Dw=f!q|xU4h&d$bI2xZw%zl zaJ07ua&I`=n*+H!klTad{y=UJhC2kgMHuc84gWNN6N7u>!2hBeoH1+Jg)5+dF{xKZ`LIQ&PV}gSNf&+r; F{Ry|ZcJBZH literal 0 HcmV?d00001 diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/East-Indiana b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/East-Indiana new file mode 100644 index 0000000000000000000000000000000000000000..4a92c06593d33d3969756f482e5d3d4b773984ef GIT binary patch literal 1675 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 SRPU&s5#C%J%>V!A zFflLy$p{9P|NpBp7&-p`FHT@!@$n5|@CXKCmk^+S2nZo;D?3mn*w!CVJ^z8AxBx^rPJ#dc literal 0 HcmV?d00001 diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Indiana-Starke b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Indiana-Starke new file mode 100644 index 0000000000000000000000000000000000000000..cc785da97de0a5614613f9ba6e502d7dc5f525b5 GIT binary patch literal 2437 zcmd_rUrg0y9LMo52q6eaCWd5SS}_9&Y$$E8wFP5`#6Nk!KM+Q0h-E%1kf_n))+8^Q zrA@&a>LQnGhSpSU3r(rDnlm&BQVB4LS;(VtK}zTJydN*KKlgpv@4U_qC|931-bH24 zPm{k~i2a0z+hrf#$7uUfzb{Ge{`7aXXLF?9yX%7b=5?PwJ9$u@EeSQ}^Uq7$#M9>c zw4>54jiw{IPCB~YGC%kZ>kB8=nv0z~^`-r9s?O#r{o|H3s;jSGmp;5`X5Z>v#V+jV%yK@)MJLPs9kW=8MdCQ)_e=I$-!GN!7) z+*4K{V;82IXivI~dpy?MJ0(_PCe2XeM-EGD;CK~#BSzoXeM?Pfy{Yg2{E~`0bWz9e zJ+3BJj+O^D?NyWVugl~WpP2{K&dEc$yUoMVhb7^WO(wzDs;7i4FHdg6bM^e=6qC!1q#~3v?BU3+JF{tKE zh}YiyHsu`-&;@Bts^ChTEQtHgEcilXq3?)U)X*b^owcUuwHA4%dA%uKx=$9@7nx`C zPU@1HD)rpd2EC-TP%Vwvte53vs%8Dlb!kGpDm|U6%R&NF*?}azqW7|TVTVUvJmWVj zD--3V#%{B!AVSpEQ)YGAfUH^dzF8aHD&@0lOu4ULSEe_p%FZ)-UCd^+uKAFz8d|Q_ z*KgMw+H=*$>I(fzQj%7D}XDFjjpq!dUk zkYXU!KvxdlP!G-)grg!zNjPeP6a}dYQWm5xPFonHGEQ3>j@lr_L8^n42dNKIAdU(l zCE}RQI(-x4Uf=*jPjv69GM5>6C5ve0mNTiZTDUn(t#YC#9hsqsHoGHl%u9dQ8}uLl$E2dNMSiDiFS(=vDTtKMt`{2xIWL%`mewGuXVT2=W)C3?*6&g zGu#;6Q11QXk!auH@OauDUT1E%SI-AItM*sz^*(vZ$obqqxb5iv6`N<|TCtppSG-{^BC#z|{`(*m}qblp%FLJ}lvnu=W zXL93#!|JAX&)od@9+lJZgUQ`Epl|V?HZvAHt8dMC#pD%i)_D^jO1`f_=MTRu1wYT$ zGY5A_;ZRr=^+l!l=qy#zwNOg;WU8`A#FTIPQ&j|l=C-BZDSzHfGpl@1%}z=+mD9h` zl_S5IIpgo^xo6IqdEfTws)1kS_V>2yJ9d9AcRs&fSGOIJ`Q6*pUG;mVrfHq3Eoqm! z+8R|i)^7quYjt2~mkFlM*TJK$X2EE#UiiXJS@dPK3T(`qd#>(wm^}sVb4B z509v2S?LmP_*jL<$7H$xHMRW5$!10N8NK54C9`s(UpF2aGOLDn>DArG%zcBcdQHuY`qeSx3Rpiqui6)Mz=$qNHapVit(mU6* zp1q_WXwNba4h-qGh6y9PkLic}+H7jur#EMuGF$39^_Gc?(q7rC+J{d{M`nlW7(6JQ zmmAe1eLeE%g(|hRD*%BxWDi4zu3!V_ZfaQ7GpQac98ub z8*8Z^-75-67jU_J?c`*&(t;WRJ)ukzFF& zMD~en6xk`VRb;PDyIEwn$aazaA{$0_jBFX%GqP!9*T}Y!eIpx3cJ8!WNA~Wtn@4t! zY#-S_(g36bNDGi2AWcBJfV2VW1JVej6G$tNUN~(tkZvIDK>C3+1nCIU5~L?cQ;@D8 zZ9)2iGzRI6)3yfbjng&<>5kL32k8&eAf!V`i;x~6O+vbav88`R6X~bZHWcY7(o&?SNK=unB5lS0YhQgfzJ43s U!cawVd2wlBsI08Gthm(o7dPd97XSbN literal 0 HcmV?d00001 diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Mountain b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Mountain new file mode 100644 index 0000000000000000000000000000000000000000..7fc669171f88e8e1fb0c1483bb83e746e5f1c779 GIT binary patch literal 2453 zcmdtjeN5F=9LMnkqQH%ZQ;8vb8FWLuL3o9$5k`URY6U)Y(?UE3#rVT< zR*YFDf|Ayni4SWwHq3b&mt~`eO%k}b^FAy8>5u+w>&t$;e%!&IpEvGR z-Zfd`A2->2!ozi$hxe(9ANJ?zJ^i7o`=tck^V$z;Z>?YNYndW?3oq&3_WkO^wg^2m z=l6!8>R53#-KR(Ab%;NrJ^EUhPh1;)Mvi^&5##48Hesdb*xmIy=m9w`H%Z)*G*8CPE>zRQ9WpLBQN{f_SI2)D zt`dgA^o&zKs+or`>sx!ys9C-l^0w`V)a(@jIcM!h;`Zz>FGv zB*zAkG<-@YUv`T-2lnZda}6rB>qVV*v`nQp)#;2^7O2d+7MZninwsxiBNvp7s_euE ze9|x>fuGjy37}>mM5fY_lmETdpuf~XP;K(-=s*-%&&xJFiNiU4~kX2Bl3~q z1ER8JNIp8yCaP+V$<*7-ulRIbVydb;yRY*i1vPNW)$SRR#BI`sJimcRXmWr$uS*+Ep7FjN`USz?@imhhJ$eNKwBdbQc zY+hJ5XBG~uoMY+8+L6U0t4EfPtlw%1fKBc$bvVj{)Q6)$NQJDXL`aRS zrbtMYILd_72`Lm(DWp_Lt&n0N)k4aJ)C(yXQZb}tNX@LKXh_vK%7)a9qi{&&I7)}q zj-z-;^^o!*^+O7XRM2Wlh}6((iilLvYRZVzk)x1EC6Q7hwM2@ER1+yDQct9yNJXut zq)1Jzrl?3&t){FVrON6L@X jUtDkg|1SRy^Iu`1`R|b8nxB@HmXYGh%uLHn%W(V&DI1f# literal 0 HcmV?d00001 diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Pacific b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Pacific new file mode 100644 index 0000000000000000000000000000000000000000..1fa9149f9a9207a9b9838141088663ebe669f250 GIT binary patch literal 2845 zcmd_reN5F=9LMpCq6kW!Oq2-iq$YxjfTAdt`82>pRIVgu_>jOb4HZHyLt6A;%{b(I z=!w3PYq>IX%w|!9Zn;{s5}NZVB1>f|sc4Bx_jcar-~Qs*Kc?5=Y4;?3kvcQ zJpVY|>^EG_XZG^mx6D4O-cOZx>%xq@7$ZC1ykWlG6d{d+udixcGE^P&73$-Dc59yMJf5rn`Z`tl4y0)R2QkXCBU%T% z+)H&?*Hd?0JDf{vy-plap$(OC z$EP)__wJ9idZSX^xyk50>xO2QNRVh9q9r_s{rT4GlZ0qhhL5 zl&?*qL&{Wi^Y;>SVW}EkzfVRqm70-NTO_u2u^CnRl*DbBV&d~(*9k>K%;=P2Jtnie zNsP+UV-s4J>jks+A=v`pFufD$I)3t14R5>ajibn!-b>D6CBvXY5kN z{$MFdYA_|u7iC>|wOLnxMAmndo2RR43U!RgtnHbwvt`R2C^MQd^|BNOh6& zBK1WI?6eg|O6;^XMv9D787VVTXQa?brIAu2wML4KR2wNbQg5W-NX3zoJ8jL8q9avD z%8t|>DLhhnr1VJbk>VrON6L@XA6WpWT>)eXoOTV6MR3|xK$Zbn2V^0Tl|YsPSqo$_ zkkvqz16dDbL7a9)kR@^2H9;1|X;%eV7GzzJg+W#ZSsG+*ki|h(2U#9ueUJr0RtQ-l zr(Gjtk(_pwkY#e(bwU;jSt(?xkhMY<3t25>xsdfj77ST2WXYU%&5%WN+EqiA&1u&S xSvX|nkflS`4p}^8^^oQBxUKu&O<#yz#3Z|nBhp95Cd9^#NRN+?jgO5B`5OyZo4^17 literal 0 HcmV?d00001 diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Pacific-New b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Pacific-New new file mode 100644 index 0000000000000000000000000000000000000000..1fa9149f9a9207a9b9838141088663ebe669f250 GIT binary patch literal 2845 zcmd_reN5F=9LMpCq6kW!Oq2-iq$YxjfTAdt`82>pRIVgu_>jOb4HZHyLt6A;%{b(I z=!w3PYq>IX%w|!9Zn;{s5}NZVB1>f|sc4Bx_jcar-~Qs*Kc?5=Y4;?3kvcQ zJpVY|>^EG_XZG^mx6D4O-cOZx>%xq@7$ZC1ykWlG6d{d+udixcGE^P&73$-Dc59yMJf5rn`Z`tl4y0)R2QkXCBU%T% z+)H&?*Hd?0JDf{vy-plap$(OC z$EP)__wJ9idZSX^xyk50>xO2QNRVh9q9r_s{rT4GlZ0qhhL5 zl&?*qL&{Wi^Y;>SVW}EkzfVRqm70-NTO_u2u^CnRl*DbBV&d~(*9k>K%;=P2Jtnie zNsP+UV-s4J>jks+A=v`pFufD$I)3t14R5>ajibn!-b>D6CBvXY5kN z{$MFdYA_|u7iC>|wOLnxMAmndo2RR43U!RgtnHbwvt`R2C^MQd^|BNOh6& zBK1WI?6eg|O6;^XMv9D787VVTXQa?brIAu2wML4KR2wNbQg5W-NX3zoJ8jL8q9avD z%8t|>DLhhnr1VJbk>VrON6L@XA6WpWT>)eXoOTV6MR3|xK$Zbn2V^0Tl|YsPSqo$_ zkkvqz16dDbL7a9)kR@^2H9;1|X;%eV7GzzJg+W#ZSsG+*ki|h(2U#9ueUJr0RtQ-l zr(Gjtk(_pwkY#e(bwU;jSt(?xkhMY<3t25>xsdfj77ST2WXYU%&5%WN+EqiA&1u&S xSvX|nkflS`4p}^8^^oQBxUKu&O<#yz#3Z|nBhp95Cd9^#NRN+?jgO5B`5OyZo4^17 literal 0 HcmV?d00001 diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Samoa b/icfp-2016/benchmark/gregor/base/tzinfo/test/data/64-bit/US/Samoa new file mode 100644 index 0000000000000000000000000000000000000000..1d7649ff71d07a158d69ab0d46a60f89c28683a3 GIT binary patch literal 272 zcmWHE%1kq2zyPd35fBCe79a+(1sZ_FMAqLNzb=JtkkU3VU}Rzj%5AJ*VEF$({s)Lm z4PamalN?}@$HzB>!7n(3!3l_iffxZo2-^#Dg8tkJ=? z!Q9a_a=|1E(F`4%HgPS*S5s0GdzBW_I;Z#h-geP=(N%xve?Dg%818=GCn+U!T5r!k zp2qfnczG_{m+x&}v>!$5LS@CrKdJW?d1U3=U#eB{j*B;NN9u6QjyHo{+MdLuyyRuVz=}cJ;}*W9HM6Z*=*-GP8ThR$Z~? z9kVBEnckcCg83{lTklJoYCeyiq$|DiWPk7=eIPPb4%AOn2ZQ3|;PHX#i&u;s>iUZu zQa5zfoO9-I+$nt|xzZf%yjvfODK^JFEA@$x#pZ-wpuh92m+vdm^~vf2Ikn+sRb4(q zP8XypUF4NBnGdS7xzX}NLN|3TwUwNo7^Q3CBh8QfTj~p8!RBJyYx+`?tLD;ghxJc2 zRp#>19lEx%)LhwJrG73sBxXgay1Hb$T${gK)nygRFH`5LUlViWw;_+H-=kBczT30< zkKkCj-fXhIUO&m)xG-4%d3=!h>%bk_x3iP+ulH-ua-V6Ce?~WaR+~oRQvvEPX*^b| zCUK{wY0tf?>8tJKmX>SOEt{8_K(k0S*9)b^iB&qNB13L1%hSOd7MPZAP1CIk(#>si zAJVNe<4v2%-E~MpxM@4Eg}yz!xoOuWT(xgjYdSP+t~y)`l#XX=Ri|$+%N={ZR-s$I zk~>#!QJu3r=B}5PsxHZAP1orq`tF#0=AMyn=zBxfnXvA&beQim2@g!x;ni!U`=$Q6 zM|r+PR3)j%qD+a})=x#}j*^~B+o@g|8K(C$*HxeR1k-o?Nfi^;!}RN2uKG6(G6On( zrw7#hYzE%=L=UR`)(rl>NXM33k^6SNsPA9$jSP9`aUGYnRfguxR}UmElVNF(so~Mt zGGh2JHKMNA#79om@l}gWLeNm1ux+LpS=&{QdbdDEAB|Jqc{60pjxH*3idV)K2B>kd z(K3EcjhfJ@l_Vt}P)RrHf!UjW>RRSp0w|(nd~dpDQl|CBh`!bl)O^&X!%T? znzr0bEgGYhce^~6KSMnpStw6rcvV_Zj->ozrL!U%(GouMi>H9_XT=}`?E+~mJT0XO*zH~R_6OYt*7Fr~ zUy+SPb{5%MWN(qpMRph2USxlf4R+ccMz+{#_ZZn^WS5a`M)n!mXk@36tw#15*=%ID zk?ltI8`*HD-Em~gop#TWO-FX!X}2BOcVy#{okzAF*?VO3k==LN?ML<>X#mmzqyMS(m14ZNb8W^Aedx|s_=_=Azq_0S0ka;NP%(sZZoI?{He??~g3 z&LgcydXF?8=|0kar2ohb;IwxDatk=^J%HQ1axWk^19CSY zw*zuNAU6bZMZQ``|338(#cM5W=AomJ#vmkd1a=UnL`V#q{9xs9Rrirn)O@y~k SRPU&s5#Ctzoffset "US/Eastern" -999999999999999) + (tzoffset -17762 #f "LMT")) + + (check-equal? (utc-seconds->tzoffset "US/Eastern" IN-DST) + (tzoffset -14400 #t "EDT")) + + (check-equal? (local-seconds->tzoffset "US/Eastern" IN-DST) + (tzoffset -14400 #t "EDT")) + + (check-equal? (local-seconds->tzoffset "US/Eastern" GAP-START) + (tzgap (+ GAP-START 18000) + (tzoffset -18000 #f "EST") + (tzoffset -14400 #t "EDT"))) + + (check-equal? (local-seconds->tzoffset "US/Eastern" (sub1 GAP-START)) + (tzoffset -18000 #f "EST")) + + (check-equal? (local-seconds->tzoffset "US/Eastern" OVERLAP-START) + (tzoverlap (tzoffset -14400 #t "EDT") + (tzoffset -18000 #f "EST"))) + + (check-equal? (local-seconds->tzoffset "US/Eastern" (sub1 OVERLAP-START)) + (tzoffset -14400 #t "EDT")) + + (check-equal? (local-seconds->tzoffset "US/Eastern" (+ OVERLAP-START 3600)) + (tzoffset -18000 #f "EST")) + + (check-equal? (local-seconds->tzoffset "US/Eastern" (sub1 (+ OVERLAP-START 3600))) + (tzoverlap (tzoffset -14400 #t "EDT") + (tzoffset -18000 #f "EST")))) + +(parameterize* ([current-zoneinfo-search-path (list "/path/to/nowhere" + TEST32-DIR)] + [current-tzinfo-source (make-zoneinfo-source)]) + ;; LMT data for this zone is only available in the 64-bit files + (check-equal? (utc-seconds->tzoffset "US/Eastern" -999999999999999) + (tzoffset -18000 #f "EST")) + + (check-equal? (utc-seconds->tzoffset "UTC" 238635325) + (tzoffset 0 #f "UTC")) + + (check-exn exn:fail:tzinfo:zone-not-found? + (λ () + (utc-seconds->tzoffset "Fillory/Whitespire" 675765756)))) diff --git a/icfp-2016/benchmark/gregor/base/tzinfo/zoneinfo.rkt b/icfp-2016/benchmark/gregor/base/tzinfo/zoneinfo.rkt new file mode 100644 index 0000000..4c595ac --- /dev/null +++ b/icfp-2016/benchmark/gregor/base/tzinfo/zoneinfo.rkt @@ -0,0 +1,9 @@ +#lang racket/base + +(require racket/contract/base) +(require "private/generics.rkt" + "private/zoneinfo.rkt") + +(provide/contract + [current-zoneinfo-search-path (parameter/c (listof path-string?))] + [make-zoneinfo-source (-> tzinfo-source?)]) diff --git a/icfp-2016/benchmark/gregor/post/clock.rkt b/icfp-2016/benchmark/gregor/post/clock.rkt new file mode 100644 index 0000000..61c1539 --- /dev/null +++ b/icfp-2016/benchmark/gregor/post/clock.rkt @@ -0,0 +1,79 @@ +#lang typed/racket/base +(require trivial/no-colon) + +;; Front-end: +;; Working with current clock + +(provide;/contract + current-clock ;any/c] + current-posix-seconds ;any/c] + now/moment ;(->i () (#:tz [tz tz/c]) [res moment?])] + now ;(->i () (#:tz [tz tz/c]) [res datetime?])] + today ;(->i () (#:tz [tz tz/c]) [res date?])] + current-time ;(->i () (#:tz [tz tz/c]) [res time?])] + now/moment/utc ;(-> moment?)] + now/utc ;(-> datetime?)] + today/utc ;(-> date?)] + current-time/utc ;(-> time?)]) +) + +;; ----------------------------------------------------------------------------- + +(require + (only-in racket/math exact-round) + "../base/types.rkt" + "tzinfo-adapter.rkt" + "gregor-adapter.rkt" +) +(require "moment.rkt" +) +(require "datetime.rkt" +) + +;; ============================================================================= + +(: now/moment (->* () (#:tz (U tz #f)) Moment)) +(define (now/moment #:tz [tz (current-timezone)]) + (unless tz (error "current-timezone is #f")) + (posix->moment ((current-clock)) tz)) + +(: now/moment/utc (-> Moment)) +(define (now/moment/utc) + (now/moment #:tz "Etc/UTC")) + +(: now (->* () (#:tz (U tz #f)) DateTime)) +(define (now #:tz [tz (current-timezone)]) + (unless tz (error "now: current-timezone is #f")) + (moment->datetime/local (now/moment #:tz tz))) + +(: now/utc (-> DateTime)) +(define (now/utc) + (now #:tz "Etc/UTC")) + +(: today (->* () (#:tz (U tz #f)) Date)) +(define (today #:tz [tz (current-timezone)]) + (unless tz (error "today: current-timezone is #f")) + (datetime->date (now #:tz tz))) + +(: today/utc (-> Date)) +(define (today/utc) + (today #:tz "Etc/UTC")) + +(: current-time (->* () (#:tz (U tz #f)) Time)) +(define (current-time #:tz [tz (current-timezone)]) + (unless tz (error "current-time: current-timezone is #f")) + (datetime->time (now #:tz tz))) + +(: current-time/utc (-> Time)) +(define (current-time/utc) + (current-time #:tz "Etc/UTC")) + +(: current-posix-seconds (-> Natural)) +(define (current-posix-seconds) + (let ([r (exact-round (/ (inexact->exact (current-inexact-milliseconds)) 1000))]) + (unless (index? r) (error "current-posix-seconds")) + r)) + +(: current-clock (Parameterof (-> Exact-Rational))) +(define current-clock (make-parameter current-posix-seconds)) + diff --git a/icfp-2016/benchmark/gregor/post/core-adapter.rkt b/icfp-2016/benchmark/gregor/post/core-adapter.rkt new file mode 100644 index 0000000..35ae909 --- /dev/null +++ b/icfp-2016/benchmark/gregor/post/core-adapter.rkt @@ -0,0 +1,15 @@ +#lang typed/racket/base +(require trivial/no-colon) + +;; Adapter for gregor's `structs.rkt` file. + +(provide + (struct-out YMD) + (struct-out HMSN) + Month) + +(require + "../base/types.rkt") + +(require "core-structs.rkt" +) diff --git a/icfp-2016/benchmark/gregor/post/core-structs.rkt b/icfp-2016/benchmark/gregor/post/core-structs.rkt new file mode 100644 index 0000000..33e84b3 --- /dev/null +++ b/icfp-2016/benchmark/gregor/post/core-structs.rkt @@ -0,0 +1,23 @@ +#lang typed/racket/base +(require trivial/no-colon) + +;; Core: +;; Essential structs + +(provide + (struct-out YMD) + (struct-out HMSN) +) + +(require "../base/types.rkt") + +;; TODO precise types for year, day, hour, second? +;; (the others are not feasible) + +(struct YMD ([y : Natural] + [m : Month] + [d : Natural]) #:transparent) +(struct HMSN ([h : Integer] + [m : Integer] + [s : Integer] + [n : Integer]) #:transparent) diff --git a/icfp-2016/benchmark/gregor/post/date.rkt b/icfp-2016/benchmark/gregor/post/date.rkt new file mode 100644 index 0000000..2e0d958 --- /dev/null +++ b/icfp-2016/benchmark/gregor/post/date.rkt @@ -0,0 +1,129 @@ +#lang typed/racket/base +(require trivial/no-colon) + +;; Working with dates + +(provide;/contract + date ;(->i ([year exact-integer?]) + ; ([month (integer-in 1 12)] + ; [day (year month) (day-of-month/c year month)]) + ; [d date?])] + date->ymd ;(-> date? YMD?)] + date->jdn ;(-> date? exact-integer?)] + ymd->date ;(-> YMD? date?)] + jdn->date ;(-> exact-integer? date?)] + date->iso-week ;(-> date? (integer-in 1 53))] + date->iso-wyear ;(-> date? exact-integer?)] + date->iso8601 ;(-> date? string?)] + date=? ;(-> date? date? boolean?)] + date<=? ;(-> date? date? boolean?)] +) + +;; ----------------------------------------------------------------------------- + +(require + (only-in racket/math exact-round) + (only-in racket/format ~r) + "core-adapter.rkt" + "gregor-adapter.rkt" + racket/match) + +(require + "ymd.rkt" +) + +;; ============================================================================= + +(: date-equal-proc (-> Date Date Boolean)) +(define (date-equal-proc x y) + (= (Date-jdn x) (Date-jdn y))) + +(: date-hash-proc (-> Date (-> Integer Integer) Integer)) +(define (date-hash-proc x fn) + (fn (Date-jdn x))) + +(: date-write-proc (-> Date Output-Port Any Void)) +(define (date-write-proc d out mode) + (fprintf out "#" (date->iso8601 d))) + +;; #:methods gen:equal+hash +;; [(define equal-proc date-equal-proc) +;; (define hash-proc date-hash-proc) +;; (define hash2-proc date-hash-proc)] + +;; #:methods gen:custom-write +;; [(define write-proc date-write-proc)] + +;; #:property prop:serializable +;; (make-serialize-info (λ (d) (vector (date->jdn d))) +;; #'deserialize-info:Date +;; #f +;; (or (current-load-relative-directory) +;; (current-directory)))) + +(: date? (-> Any Boolean)) +(define date? Date?) + +(: date (->* (Natural) (Month Natural) Date)) +(define (date y [m 1] [d 1]) + (: ymd YMD) + (define ymd (YMD y m d)) + (Date ymd (ymd->jdn ymd))) + +(: date->ymd (-> Date YMD)) +(define date->ymd Date-ymd) +(: date->jdn (-> Date Integer)) +(define (date->jdn d) + (Date-jdn d)) + +(: ymd->date (-> YMD Date)) +(define (ymd->date ymd) + (match-define (YMD y m d) ymd) + (date y m d)) + +(: jdn->date (-> Exact-Rational Date)) +(define (jdn->date jdn) + (Date (jdn->ymd jdn) (exact-round jdn))) + +(: date->iso-week (-> Date Natural)) +(define (date->iso-week d) + (car (date->iso-week+wyear d))) + +(: date->iso-wyear (-> Date Natural)) +(define (date->iso-wyear d) + (cdr (date->iso-week+wyear d))) + +(: date->iso-week+wyear (-> Date (Pairof Natural Natural))) +(define (date->iso-week+wyear d) + (define ymd (date->ymd d)) + (define yday (ymd->yday ymd)) + (define iso-wday (jdn->iso-wday (date->jdn d))) + (match-define (YMD y _ _) ymd) + (define w (quotient (+ yday (- iso-wday ) 10) + 7)) + (cond [(zero? w) + (define y-1 + (let ([r (sub1 y)]) (unless (index? r) (error "date->iso-week+year")) r)) + (cons (iso-weeks-in-year y-1) y-1)] + [(and (= w 53) (> w (iso-weeks-in-year y))) + (cons 1 (add1 y))] + [(index? w) + (cons w y)] + [else (error "date->iso-week+year")])) + +(: date->iso8601 (-> Date String)) +(define (date->iso8601 d) + (: f (-> Integer Natural String)) + (define (f n len) (~r n #:min-width len #:pad-string "0")) + + (match (Date-ymd d) + [(YMD y m d) (format "~a-~a-~a" (f y 4) (f m 2) (f d 2))])) + +(: date=? (-> Date Date Boolean)) +(define (date=? d1 d2) + (= (date->jdn d1) (date->jdn d2))) + +(: date<=? (-> Date Date Boolean)) +(define (date<=? d1 d2) + (<= (date->jdn d1) (date->jdn d2))) + diff --git a/icfp-2016/benchmark/gregor/post/datetime.rkt b/icfp-2016/benchmark/gregor/post/datetime.rkt new file mode 100644 index 0000000..3517d0a --- /dev/null +++ b/icfp-2016/benchmark/gregor/post/datetime.rkt @@ -0,0 +1,166 @@ +#lang typed/racket/base +(require trivial/no-colon) + +;; Working with DateTime objects +;; (i.e. dates and times at the same time) + +(require + "core-adapter.rkt" + "gregor-adapter.rkt" + racket/match + (only-in racket/math exact-round exact-floor)) + +(require + "hmsn.rkt" +) +(require + "date.rkt" +) +(require "time.rkt" +) + +;; ----------------------------------------------------------------------------- + +(provide;/contract + datetime ;(->i ([year exact-integer?]) + ; ([month (integer-in 1 12)] + ; [day (year month) (day-of-month/c year month)] + ; [hour (integer-in 0 23)] + ; [minute (integer-in 0 59)] + ; [second (integer-in 0 59)] + ; [nanosecond (integer-in 0 (sub1 NS/SECOND))]) + ; [dt datetime?])] + datetime->date ;(-> datetime? date?)] + datetime->time ;(-> datetime? time?)] + datetime->jd ;(-> datetime? rational?)] + datetime->posix ;(-> datetime? rational?)] + date+time->datetime ;(-> date? time? datetime?)] + jd->datetime ;(-> real? datetime?)] + posix->datetime ;(-> real? datetime?)] + datetime->iso8601 ;(-> datetime? string?)] + datetime-add-nanoseconds ;(-> datetime? exact-integer? datetime?)] + datetime-add-seconds ;(-> datetime? exact-integer? datetime?)] + datetime=? ;(-> datetime? datetime? boolean?)] + datetime datetime? datetime? boolean?)] + datetime<=? ;(-> datetime? datetime? boolean?)] +) + +;; ============================================================================= + +(: datetime-equal-proc (-> DateTime DateTime Boolean)) +(define (datetime-equal-proc x y) + (= (datetime->jd x) + (datetime->jd y))) + +(: datetime-hash-proc (-> DateTime (-> Exact-Rational Integer) Integer)) +(define (datetime-hash-proc x fn) + (fn (datetime->jd x))) + +(: datetime-write-proc (-> DateTime Output-Port Any Void)) +(define (datetime-write-proc dt out mode) + (fprintf out "#" (datetime->iso8601 dt))) + +(: datetime? (-> Any Boolean)) +(define datetime? DateTime?) + +(: datetime->date (-> DateTime Date)) +(define datetime->date DateTime-date) +(: datetime->time (-> DateTime Time)) +(define datetime->time DateTime-time) +(: datetime->jd (-> DateTime Exact-Rational)) +(define (datetime->jd d) + (DateTime-jd d)) + +(: datetime->posix (-> DateTime Exact-Rational)) +(define (datetime->posix dt) + (jd->posix (datetime->jd dt))) + +(: posix->datetime (-> Exact-Rational DateTime)) +(define (posix->datetime posix) + (jd->datetime (posix->jd (inexact->exact posix)))) + +(: date+time->datetime (-> Date Time DateTime)) +(define (date+time->datetime d t) + (DateTime d t (date+time->jd d t))) + +(: jd->datetime (-> Exact-Rational DateTime)) +(define (jd->datetime jd) + (define ejd (inexact->exact jd)) + (define-values (d t) (jd->date+time ejd)) + (date+time->datetime d t)) + +(: datetime (->* (Natural) (Month Natural Natural Natural Natural Natural) DateTime)) +(define (datetime year [month 1] [day 1] [hour 0] [minute 0] [second 0] [nano 0]) + (date+time->datetime (date year month day) + (make-time hour minute second nano))) + +(: datetime->iso8601 (-> DateTime String)) +(define (datetime->iso8601 dt) + (format "~aT~a" + (date->iso8601 (datetime->date dt)) + (time->iso8601 (datetime->time dt)))) + +(: datetime=? (-> DateTime DateTime Boolean)) +(define (datetime=? dt1 dt2) + (= (datetime->jd dt1) (datetime->jd dt2))) + +(: datetime DateTime DateTime Boolean)) +(define (datetimejd dt1) (datetime->jd dt2))) + +(: datetime<=? (-> DateTime DateTime Boolean)) +(define (datetime<=? dt1 dt2) + (<= (datetime->jd dt1) (datetime->jd dt2))) + +(: date+time->jd (-> Date Time Exact-Rational)) +(define (date+time->jd d t) + (define jdn (date->jdn d)) + (define day-ns (time->ns t)) + + (+ (- jdn 1/2) + (/ day-ns NS/DAY))) + +(: jd->date+time (-> Exact-Rational (Values Date Time))) +(define (jd->date+time jd) + (define jdn (jd->jdn jd)) + (define d (jdn->date jdn)) + (define day-ns (jd->day-ns jd)) + (define t (day-ns->time day-ns)) + + (values d t)) + +(: jd->jdn (-> Exact-Rational Exact-Rational)) +(define (jd->jdn jd) + (define lo (exact-floor jd)) + + ;; math-class rounding: round up for >= 1/2 + (if (>= (- jd lo) 1/2) + (add1 lo) + lo)) + +(: jd->day-ns (-> Exact-Rational Natural)) +(define (jd->day-ns jd) + (define base (- jd 1/2)) + (define frac (- base (exact-floor base))) + (define r (exact-round (* frac NS/DAY))) + (unless (index? r) (error "jd->day-ns")) + r) + +(: jd->posix (-> Exact-Rational Exact-Rational)) +(define (jd->posix jd) + (* 86400 (- jd (+ 2440587 1/2)))) + +(: posix->jd (-> Exact-Rational Exact-Rational)) +(define (posix->jd posix) + (+ (/ posix 86400) (+ 2440587 1/2))) + +(: datetime-add-nanoseconds (-> DateTime Integer DateTime)) +(define (datetime-add-nanoseconds dt n) + (jd->datetime + (+ (datetime->jd dt) + (/ n NS/DAY)))) + +(: datetime-add-seconds (-> DateTime Integer DateTime)) +(define (datetime-add-seconds dt n) + (datetime-add-nanoseconds dt (* n NS/SECOND))) + diff --git a/icfp-2016/benchmark/gregor/post/difference.rkt b/icfp-2016/benchmark/gregor/post/difference.rkt new file mode 100644 index 0000000..54a86ae --- /dev/null +++ b/icfp-2016/benchmark/gregor/post/difference.rkt @@ -0,0 +1,76 @@ +#lang typed/racket/base +(require trivial/no-colon) + +;; Time deltas + +(provide;/contract + datetime-months-between ;(-> datetime? datetime? exact-integer?)] + datetime-days-between ;(-> datetime? datetime? exact-integer?)] + datetime-nanoseconds-between ;(-> datetime? datetime? exact-integer?)]) +) + +;; ----------------------------------------------------------------------------- + +(require + racket/match + "core-adapter.rkt" + "gregor-adapter.rkt" + (only-in racket/math exact-floor)) +(require + "ymd.rkt" + ) +(require "hmsn.rkt" +) +(require "date.rkt" +) +(require "datetime.rkt" +) + +;; ============================================================================= + +;; difference +(: datetime-months-between (-> DateTime DateTime Integer)) +(define (datetime-months-between dt1 dt2) + (cond [(datetimedate dt1)) + (: d2 Date) + (define d2 (datetime->date dt2)) + + (match* ((date->ymd d1) (date->ymd d2)) + [((YMD y1 m1 d1) (YMD y2 m2 d2)) + (: diff Integer) + (define diff + (+ (* (- y2 y1) 12) + m2 + (- m1))) + (: start-dom Natural) + (define start-dom + (let ([r (if (and (> d1 d2) + (= (days-in-month y2 m2) d2)) + d2 + d1)]) + (abs r))) + (: dt1a DateTime) + (define dt1a (date+time->datetime (date y1 m1 start-dom) (datetime->time dt1))) + + (define ts1 (- (datetime->jd dt1a) (datetime->jd (datetime y1 m1)))) + (define ts2 (- (datetime->jd dt2) (datetime->jd (datetime y2 m2)))) + (if (< ts2 ts1) + (sub1 diff) + diff)])])) + +(: datetime-days-between (-> DateTime DateTime Integer)) +(define (datetime-days-between dt1 dt2) + (exact-floor (- (datetime->jd dt2) (datetime->jd dt1)))) + +(: datetime-nanoseconds-between (-> DateTime DateTime Integer)) +(define (datetime-nanoseconds-between dt1 dt2) + (- (datetime->jdns dt2) + (datetime->jdns dt1))) + +(: datetime->jdns (-> DateTime Integer)) +(define (datetime->jdns dt) + (exact-floor (* (datetime->jd dt) NS/DAY))) diff --git a/icfp-2016/benchmark/gregor/post/gregor-adapter.rkt b/icfp-2016/benchmark/gregor/post/gregor-adapter.rkt new file mode 100644 index 0000000..4dcea61 --- /dev/null +++ b/icfp-2016/benchmark/gregor/post/gregor-adapter.rkt @@ -0,0 +1,24 @@ +#lang typed/racket/base +(require trivial/no-colon) + +(require + "core-adapter.rkt") + +(require "gregor-structs.rkt" +) + +(provide + Date Date? + Date-ymd + Date-jdn + Time Time? + Time-hmsn + Time-ns + DateTime DateTime? + DateTime-date + DateTime-time + DateTime-jd + Moment Moment? + Moment-datetime/local + Moment-utc-offset + Moment-zone) diff --git a/icfp-2016/benchmark/gregor/post/gregor-structs.rkt b/icfp-2016/benchmark/gregor/post/gregor-structs.rkt new file mode 100644 index 0000000..86c4143 --- /dev/null +++ b/icfp-2016/benchmark/gregor/post/gregor-structs.rkt @@ -0,0 +1,28 @@ +#lang typed/racket/base +(require trivial/no-colon) + +(require + "core-adapter.rkt") + +(provide + (struct-out Date) + (struct-out Time) + (struct-out DateTime) + (struct-out Moment)) + +;; Structs from the main gregor modules +;; `date.rkt`, `time.rkt`, `datetime.rkt`, `moment-base.rkt` + +(struct Date ([ymd : YMD] + [jdn : Integer])) + +(struct Time ([hmsn : HMSN] [ns : Natural])) + +(struct DateTime ([date : Date] + [time : Time] + [jd : Exact-Rational])) + +(struct Moment ([datetime/local : DateTime] + [utc-offset : Integer] + [zone : (U String #f)])) + diff --git a/icfp-2016/benchmark/gregor/post/hmsn.rkt b/icfp-2016/benchmark/gregor/post/hmsn.rkt new file mode 100644 index 0000000..7706ba0 --- /dev/null +++ b/icfp-2016/benchmark/gregor/post/hmsn.rkt @@ -0,0 +1,66 @@ +#lang typed/racket/base +(require trivial/no-colon) + +;; Core: +;; Hours, Minutes, Seconds, Nanoseconds +;; constants and conversions + +(provide + NS/MICRO + NS/MILLI + NS/SECOND + NS/MINUTE + NS/HOUR + NS/DAY + MILLI/DAY + hmsn->day-ns + day-ns->hmsn) + +(require + racket/match + "core-adapter.rkt") + +;; ============================================================================= + +(: NS/SECOND Natural) +(define: NS/SECOND 1000000000) +(: NS/MILLI Natural) +(define: NS/MILLI 1000000) +;; (define NS/MILLI (/ NS/SECOND 1000)) +(: NS/MICRO Natural) +(define: NS/MICRO 1000) +;; (define NS/MICRO (/ NS/MILLI 1000)) +(: NS/MINUTE Natural) +(define: NS/MINUTE (* NS/SECOND 60)) +(: NS/HOUR Natural) +(define: NS/HOUR (* NS/MINUTE 60)) +(: NS/DAY Natural) +(define: NS/DAY (* 86400 NS/SECOND)) +(: MILLI/DAY Natural) +(define: MILLI/DAY 86400000) +;; (define MILLI/DAY (/ NS/DAY NS/MILLI)) +(: DAYS/NS Exact-Rational) +(define: DAYS/NS (/ 1 NS/DAY)) + +;; (define day-ns/c (integer-in 0 (sub1 NS/DAY))) +;; Codomain of hmsn->day-ns should be a day-ns/c +(: hmsn->day-ns (-> HMSN Natural)) +(define (hmsn->day-ns hmsn) + (match-define (HMSN h m s n) hmsn) + (define r (+ (* NS/HOUR h) + (* NS/MINUTE m) + (* NS/SECOND s) + n)) + (unless (index? r) + (error "nope")) + r) + +(: day-ns->hmsn (-> Natural HMSN)) +(define (day-ns->hmsn ns) + (let* ([h (quotient ns NS/HOUR)] + [ns (- ns (* h NS/HOUR))] + [m (quotient ns NS/MINUTE)] + [ns (- ns (* m NS/MINUTE))] + [s (quotient ns NS/SECOND)] + [ns (- ns (* s NS/SECOND))]) + (HMSN h m s ns))) diff --git a/icfp-2016/benchmark/gregor/post/main.rkt b/icfp-2016/benchmark/gregor/post/main.rkt new file mode 100644 index 0000000..92709a8 --- /dev/null +++ b/icfp-2016/benchmark/gregor/post/main.rkt @@ -0,0 +1,143 @@ +#lang typed/racket/base +(require trivial/no-colon) + +(require + "../base/types.rkt" + "gregor-adapter.rkt" + "tzinfo-adapter.rkt" +) +(require "date.rkt" +) +(require "time.rkt" +) +(require "datetime.rkt" +) +(require "moment.rkt" +) +(require "clock.rkt" +) +(require "difference.rkt" +) + +;; ============================================================================= + +(: HISTORIC-DATES (-> (Listof DateTime))) +(define (HISTORIC-DATES) + (list + ;(datetime YEAR MONTH DAY HOUR MINUTE SECOND NANOSECOND) + (datetime 2001 9 11 8 46) ;; 9/11 part I + (datetime 2001 9 11 9 3) ;; 9/11 part II + (datetime 1944 6 6 6 6 6 6) ;; D-Day + (datetime 1984) + (datetime 1963 11 22 12 30) ;; Kennedy + (datetime 1865 4 14 10) ;; Lincoln + (datetime 1881 7 2) ;; Garfield + (datetime 1901 9 6) ;; McKinley + (datetime 1933 2 15) ;; Roosevelt + (datetime 1912 10 14) ;; Taft + (datetime 1928 11 19) ;; Hoover + (datetime 1950 11 1) ;; Truman + (datetime 1835 1 30) ;; Jackson + (datetime 1989 11 9) ;; Berlin Wall + (datetime 1969 7 20 20 18) ;; Lunar landing + (datetime 1977 8 16) ;; Elvis + (datetime 1980 12 8) ;; Lennon + (datetime 2013 6 18) ;; Kanye releases Yeezus + (datetime 1998 9 28) ;; Pokemon Red released + (datetime 1991 4 29) ;; Sarah bday + (datetime 1922 2 2) ;; Ulysses released + (datetime 12) + (datetime 1030) ;; Leif Erikson landing + (datetime 1898 4) ;; Spanish-American war begins + (datetime 1099 7 10) ;; El Cid dies +)) +(: RANDOM-DATES (-> (Listof DateTime))) +(define (RANDOM-DATES) + (list + (datetime 324 2 1 4 32 66 23) + (datetime 6 9 12 0 55 6 8) + (datetime 1111 12 30 8 48 11 44) + (datetime 32 5 8 12 2 41 39) (datetime 6 6 6 6 6 6 6) + (datetime 8 6 7 5 3 0 9) + (datetime 1251 3 18 6) + (datetime 1386 2 1 0) + (datetime 123 4 5 12 53) + (datetime 2002 11 42 32) + (datetime 777 7 77 77 77) + (datetime 1 2 3 4 5 6 7) + (datetime 9999 12 30 30 30 30 30) +)) + +;; -- tests + +(: test-clock (-> Void)) +(define (test-clock) + (parameterize ([current-clock (lambda () 1)]) + ;; -- today + (unless (date=? (today/utc) (date 1970)) (error "test1")) + (unless (date=? (today #:tz "America/Chicago") (date 1969 12 31)) (error "test2")) + ;; -- current-time + (unless (time=? (current-time/utc) (make-time 0 0 1)) (error "test 3")) + (unless (time=? (current-time #:tz "America/Chicago") (make-time 18 0 1)) (error "test4")) + ;; -- now + (unless (datetime=? (now/utc) (datetime 1970 1 1 0 0 1)) (error "test5")) + (unless (datetime=? (now #:tz "America/Chicago") (datetime 1969 12 31 18 0 1)) (error "test6")) + + ;; -- "moment" + (unless (moment=? (now/moment/utc) (moment 1970 1 1 0 0 1 #:tz UTC)) (error "test7")) + ;; 2015-04-25: Can't type check! Need help + ;; (unless (moment=? (now/moment #:tz "America/Chicago") + ;; (moment 1969 12 31 18 0 1 0 #:tz "America/Chicago")) (error "test8")) +)) + +(: test-iso (-> (Listof DateTime) Void)) +(define (test-iso dates) + (parameterize ([current-clock (lambda () 1463207954418177/1024000)]) + ;; -- test-case "today" + (let ([d (today)]) + (unless (string=? "2015-04-13" (date->iso8601 d)) (error "test9"))) + + ;; -- test-case "current-time" + (let ([t (current-time)]) + (unless (string=? "04:33:37.986500977" (time->iso8601 t)) (error "test10"))) + + ;; -- test-case "now" + (let ([n (now)]) + (unless (string=? "2015-04-13T04:33:37.986500977" (datetime->iso8601 n)) (error "test11"))) + + ;; -- test-case "now/moment" + (let ([n (now/moment)]) + (unless (string=? "2015-04-13T04:33:37.986500977-04:00[America/New_York]" (moment->iso8601/tzid n)) (error "test12"))) + ) + (for ([d1 dates]) + (datetime->iso8601 d1) + (time->iso8601 (datetime->time d1)) + (date->iso8601 (datetime->date d1))) +) + +(: test-difference (-> (Listof DateTime) Void)) +(define (test-difference dates) + (for* ([dt1 dates] + [dt2 dates]) + (datetime<=? dt1 dt2) + (datetime-months-between dt1 dt2) + (datetime-days-between dt1 dt2) + (datetime-nanoseconds-between dt1 dt2) + (moment=? + (posix->moment (datetime->posix dt1) UTC) + (posix->moment (datetime->posix dt2) UTC)) + )) + +(: main (-> Natural Boolean Void)) +(define (main N large?) + (define dates + (if large? + (append (HISTORIC-DATES) (RANDOM-DATES)) + (HISTORIC-DATES))) + (for ([i (in-range N)]) + (test-clock) + (test-iso dates) + (test-difference dates))) + +;(time (main 10 #f)) ;;134ms +(time (main 10 #t)) ;;347ms diff --git a/icfp-2016/benchmark/gregor/post/moment-base.rkt b/icfp-2016/benchmark/gregor/post/moment-base.rkt new file mode 100644 index 0000000..801ce8b --- /dev/null +++ b/icfp-2016/benchmark/gregor/post/moment-base.rkt @@ -0,0 +1,51 @@ +#lang typed/racket/base +(require trivial/no-colon) + +;; Support for moment.rkt +;; (Works together with offset-resolvers.rkt) + +(provide + moment->iso8601 + moment->iso8601/tzid + make-moment +) + +;; ----------------------------------------------------------------------------- + +(require + racket/match + "gregor-adapter.rkt" + (only-in racket/format ~r) +) +(require "datetime.rkt" +) + +;; ============================================================================= + +(: moment->iso8601/tzid (-> Moment String)) +(define (moment->iso8601/tzid m) + (: iso String) + (define iso (moment->iso8601 m)) + (match m + [(Moment _ _ z) #:when z (format "~a[~a]" iso z)] + [_ iso])) + +(: moment->iso8601 (-> Moment String)) +(define (moment->iso8601 m) + (match m + [(Moment d 0 _) + (string-append (datetime->iso8601 d) "Z")] + [(Moment d o _) + (define sign (if (< o 0) "-" "+")) + (define sec (abs o)) + (define hrs (quotient sec 3600)) + (define min (quotient (- sec (* hrs 3600)) 60)) + (format "~a~a~a:~a" + (datetime->iso8601 d) + sign + (~r hrs #:min-width 2 #:pad-string "0" #:sign #f) + (~r min #:min-width 2 #:pad-string "0" #:sign #f))])) + +(: make-moment (-> DateTime Integer (U String #f) Moment)) +(define (make-moment dt off z) + (Moment dt off (and z (string->immutable-string z)))) diff --git a/icfp-2016/benchmark/gregor/post/moment.rkt b/icfp-2016/benchmark/gregor/post/moment.rkt new file mode 100644 index 0000000..85fc6e4 --- /dev/null +++ b/icfp-2016/benchmark/gregor/post/moment.rkt @@ -0,0 +1,180 @@ +#lang typed/racket/base +(require trivial/no-colon) + +;; Moments in time + +;; Need the requires on top to stop syntax errors; opaques must +;; come lexically before their use +(require + "../base/types.rkt" + "gregor-adapter.rkt" + racket/match + (only-in racket/math exact-round) + "tzinfo-adapter.rkt" +) +(require "hmsn.rkt" +) +(require "datetime.rkt" +) +(require "moment-base.rkt" +) +(require "offset-resolvers.rkt" +) + +;; ----------------------------------------------------------------------------- + +(provide;/contract + current-timezone ;(parameter/c tz/c)] + moment ;(->i ([year exact-integer?]) + ; ([month (integer-in 1 12)] + ; [day (year month) (day-of-month/c year month)] + ; [hour (integer-in 0 23)] + ; [minute (integer-in 0 59)] + ; [second (integer-in 0 59)] + ; [nanosecond (integer-in 0 (sub1 NS/SECOND))] + ; #:tz [tz tz/c] + ; #:resolve-offset [resolve offset-resolver/c]) + ; [res moment?])] + datetime+tz->moment ;(-> datetime? tz/c offset-resolver/c moment?)] + moment->iso8601 ;(-> moment? string?)] + moment->iso8601/tzid ;(-> moment? string?)] + moment->datetime/local ;(-> moment? datetime?)] + moment->utc-offset ;(-> moment? exact-integer?)] + moment->timezone ;(-> moment? tz/c)] + moment->tzid ;(-> moment? (or/c string? #f))] + moment->jd ;(-> moment? rational?)] + moment->posix ;(-> moment? rational?)] + posix->moment ;(-> rational? tz/c moment?)] + moment-add-nanoseconds ;(-> moment? exact-integer? moment?)] + moment-in-utc ;(-> moment? moment?)] + timezone-adjust ;(-> moment? tz/c moment?)] + timezone-coerce ;(->i ([m moment?] + ; [z tz/c]) + ; (#:resolve-offset [r offset-resolver/c]) + ; [res moment?])] + moment=? ;(-> moment? moment? boolean?)] + moment moment? moment? boolean?)] + moment<=? ;(-> moment? moment? boolean?)] + UTC ;tz/c] +) + +;; ============================================================================= + +(: current-timezone (Parameterof (U tz #f))) +(define current-timezone (make-parameter (system-tzid))) + +(: moment (->* (Natural) (Month + Natural Natural Natural Natural Natural + #:tz (U tz #f) + #:resolve-offset (-> (U tzgap tzoverlap) + DateTime + (U String #f) + (U #f Moment) Moment) + ) + Moment)) +(define (moment year [month 1] [day 1] [hour 0] [minute 0] [second 0] [nano 0] + #:tz [tz (current-timezone)] + #:resolve-offset [resolve resolve-offset/raise]) + (when (eq? tz #f) (error "no timezone")) + (datetime+tz->moment (datetime year month day hour minute second nano) tz resolve)) + +(: datetime+tz->moment (-> DateTime + (U Integer String) + (-> (U tzgap tzoverlap) + DateTime + (U String #f) + (U Moment #f) Moment) + Moment)) +(define (datetime+tz->moment dt zone resolve) + (cond [(string? zone) + (define res (local-seconds->tzoffset zone (exact-round (datetime->posix dt)))) + (cond + [(tzoffset? res) + (make-moment dt (tzoffset-utc-seconds res) zone)] + [else (resolve res dt zone #f)])] + [(index? zone) + (make-moment dt zone #f)] + [else (error (format "datetime+tz->moment unknown zone ~a" zone))])) + +(define moment->datetime/local Moment-datetime/local) +(define moment->utc-offset Moment-utc-offset) +(define moment->tzid Moment-zone) + +(: moment->timezone (-> Moment tz)) +(define (moment->timezone m) + (or (moment->tzid m) + (moment->utc-offset m))) + +(: moment-in-utc (-> Moment Moment)) +(define (moment-in-utc m) + (if (equal? UTC (moment->timezone m)) + m + (timezone-adjust m UTC))) + +(: moment->jd (-> Moment Exact-Rational)) +(define (moment->jd m) + (datetime->jd + (moment->datetime/local + (moment-in-utc m)))) + +(: moment->posix (-> Moment Exact-Rational)) +(define (moment->posix m) + (datetime->posix + (moment->datetime/local + (moment-in-utc m)))) + +(: posix->moment (-> Exact-Rational tz Moment)) +(define (posix->moment p z) + (: off Integer) + (define off + (cond [(string? z) (tzoffset-utc-seconds (utc-seconds->tzoffset z p))] + [else 0])) + (define dt (posix->datetime (+ p off))) + (unless (string? z) (error "posix->moment: can't call make-moment with an integer")) + (make-moment dt off z)) + +(: moment-add-nanoseconds (-> Moment Natural Moment)) +(define (moment-add-nanoseconds m n) + (posix->moment (+ (moment->posix m) (* n (/ 1 NS/SECOND))) + (moment->timezone m))) + +(: timezone-adjust (-> Moment (U Natural String) Moment)) +(define (timezone-adjust m z) + (: dt DateTime) + (define dt (error 'foo));(Moment-datetime/local m)) + (: neg-sec Integer) + (define neg-sec (error 'foo));(Moment-utc-offset m)) + (: dt/utc DateTime) + (define dt/utc + (datetime-add-seconds dt (- neg-sec))) + (cond [(string? z) + (define posix (datetime->posix dt/utc)) + (match-define (tzoffset offset _ _) (utc-seconds->tzoffset z posix)) + (define local (datetime-add-seconds dt/utc offset)) + (make-moment local offset z)] + [else + (define local (datetime-add-seconds dt/utc z)) + (make-moment local z #f)])) + +(: timezone-coerce (->* [Moment (U Natural String)] + (#:resolve-offset (-> (U tzgap tzoverlap) DateTime (U String #f) (U #f Moment) Moment)) + Moment)) +(define (timezone-coerce m z #:resolve-offset [resolve resolve-offset/raise]) + (datetime+tz->moment (moment->datetime/local m) z resolve)) + +(: moment=? (-> Moment Moment Boolean)) +(define (moment=? m1 m2) + (= (moment->jd m1) (moment->jd m2))) + +(: moment Moment Moment Boolean)) +(define (momentjd m1) (moment->jd m2))) + +(: moment<=? (-> Moment Moment Boolean)) +(define (moment<=? m1 m2) + (<= (moment->jd m1) (moment->jd m2))) + +(: UTC String) +(define UTC "Etc/UTC") + + diff --git a/icfp-2016/benchmark/gregor/post/offset-resolvers.rkt b/icfp-2016/benchmark/gregor/post/offset-resolvers.rkt new file mode 100644 index 0000000..ba19330 --- /dev/null +++ b/icfp-2016/benchmark/gregor/post/offset-resolvers.rkt @@ -0,0 +1,141 @@ +#lang typed/racket/base +(require trivial/no-colon) + +;; Resolving offsets between moments + +(require + "tzinfo-adapter.rkt" + "core-adapter.rkt" + "gregor-adapter.rkt" + racket/match) +(require "hmsn.rkt" +) +(require "datetime.rkt" +) +(require "moment-base.rkt" +) + +;; ----------------------------------------------------------------------------- + +(provide + resolve-gap/pre + resolve-gap/post + resolve-gap/push + + resolve-overlap/pre + resolve-overlap/post + resolve-overlap/retain + + resolve-offset/pre + resolve-offset/post + resolve-offset/post-gap/pre-overlap + resolve-offset/retain + resolve-offset/push + resolve-offset/raise + + offset-resolver +) +;; ============================================================================= + +;; -- from exn.rkt + +(struct exn:gregor exn:fail ()) +(struct exn:gregor:invalid-offset exn:gregor ()) + +(: raise-invalid-offset (-> Any DateTime Any Any Moment)) +(define (raise-invalid-offset g/o target-dt target-tzid orig) + (raise + (exn:gregor:invalid-offset + (format "Illegal moment: local time ~a ~a in time zone ~a" + (datetime->iso8601 target-dt) + (if (tzgap? g/o) + "does not exist" + "is ambiguous") + target-tzid) + (current-continuation-marks)))) + +;; -- from `offset-resolvers.rkt` + +(: resolve-gap/pre (-> tzgap DateTime (U String #f) (U #f Moment) Moment)) +(define (resolve-gap/pre gap target-dt target-tzid orig) + ;(define tm (tzgap-starts-at gap)) + ;(define delta (tzoffset-utc-seconds (tzgap-offset-before gap))) + (match-define (tzgap tm (tzoffset delta _ _) _) gap) + (make-moment (posix->datetime (+ tm delta (- (/ 1 NS/SECOND)))) delta target-tzid)) + +(: resolve-gap/post (-> tzgap DateTime (U String #f) (U #f Moment) Moment)) +(define (resolve-gap/post gap target-dt target-tzid orig) + ;(match-define (tzgap _ _ (tzoffset delta _ _)) gap) + (define tm (tzgap-starts-at gap)) + (define delta (tzoffset-utc-seconds (tzgap-offset-before gap))) + (define sum (+ tm delta)) + (make-moment (posix->datetime sum) delta target-tzid)) + +(: resolve-gap/push (-> tzgap DateTime (U String #f) (U #f Moment) Moment)) +(define (resolve-gap/push gap target-dt target-tzid orig) + ;(match-define (tzgap tm (tzoffset delta1 _ _) (tzoffset delta2 _ _)) gap) + (define tm (tzgap-starts-at gap)) + (define delta1 (tzoffset-utc-seconds (tzgap-offset-before gap))) + (define delta2 (tzoffset-utc-seconds (tzgap-offset-after gap))) + (make-moment (posix->datetime (+ (datetime->posix target-dt) (- delta2 delta1))) delta2 target-tzid)) + +(: resolve-overlap/pre (-> tzoverlap DateTime (U String #f) (U #f Moment) Moment)) +(define (resolve-overlap/pre overlap target-dt target-tzid orig) + (match-define (tzoverlap (tzoffset delta _ _) _) overlap) + (make-moment target-dt delta target-tzid)) + +(: resolve-overlap/post (-> tzoverlap DateTime (U String #f) (U #f Moment) Moment)) +(define (resolve-overlap/post overlap target-dt target-tzid orig) + (match-define (tzoverlap _ (tzoffset delta _ _)) overlap) + (make-moment target-dt delta target-tzid)) + +(: resolve-overlap/retain (-> tzoverlap DateTime (U String #f) (U #f Moment) Moment)) +(define (resolve-overlap/retain overlap target-dt target-tzid orig) + ;(match-define (tzoverlap (tzoffset delta1 _ _) (tzoffset delta2 _ _)) overlap) + (define delta1 (tzoffset-utc-seconds (tzoverlap-offset-before overlap))) + (define delta2 (tzoffset-utc-seconds (tzoverlap-offset-after overlap))) + (make-moment target-dt + (or (and orig (= (Moment-utc-offset orig) delta1) delta1) + delta2) + target-tzid)) + +(: offset-resolver (-> (-> tzgap DateTime (U String #f) (U #f Moment) Moment) + (-> tzoverlap DateTime (U String #f) (U #f Moment) Moment) + (-> (U tzgap tzoverlap) DateTime (U String #f) (U #f Moment) Moment))) +(define (offset-resolver rg ro) + (λ ([g/o : (U tzgap tzoverlap)] + [target-dt : DateTime] + [target-tzid : (U String #f)] + [orig : (U #f Moment)]) + (cond [(tzgap? g/o) + (rg g/o target-dt target-tzid orig)] + [else + (ro g/o target-dt target-tzid orig)]))) + ;; (define fn (if (tzgap? g/o) rg ro)) + ;; (fn g/o target-dt target-tzid orig))) + +(: resolve-offset/pre (-> (U tzgap tzoverlap) DateTime (U String #f) (U #f Moment) Moment)) +(define resolve-offset/pre + (offset-resolver resolve-gap/pre resolve-overlap/pre)) + +(: resolve-offset/post (-> (U tzgap tzoverlap) DateTime (U String #f) (U #f Moment) Moment)) +(define resolve-offset/post + (offset-resolver resolve-gap/post resolve-overlap/post)) + +(: resolve-offset/post-gap/pre-overlap (-> (U tzgap tzoverlap) DateTime (U String #f) (U #f Moment) Moment)) +(define resolve-offset/post-gap/pre-overlap + (offset-resolver resolve-gap/post resolve-overlap/pre)) + +(: resolve-offset/retain (-> (U tzgap tzoverlap) DateTime (U String #f) (U #f Moment) Moment)) +(define resolve-offset/retain + (offset-resolver resolve-gap/post + resolve-overlap/retain)) + +(: resolve-offset/push (-> (U tzgap tzoverlap) DateTime (U String #f) (U #f Moment) Moment)) +(define resolve-offset/push + (offset-resolver resolve-gap/push + resolve-overlap/post)) + +(: resolve-offset/raise (-> (U tzgap tzoverlap) DateTime (U String #f) (U Moment #f) Moment)) +(define (resolve-offset/raise g/o target-dt target-tzid orig) + (raise-invalid-offset g/o target-dt target-tzid orig)) diff --git a/icfp-2016/benchmark/gregor/post/structs-adapter.rkt b/icfp-2016/benchmark/gregor/post/structs-adapter.rkt new file mode 100644 index 0000000..d2f4b4e --- /dev/null +++ b/icfp-2016/benchmark/gregor/post/structs-adapter.rkt @@ -0,0 +1,15 @@ +#lang typed/racket/base +(require trivial/no-colon) + +;; Adapter for gregor's `structs.rkt` file. + +(provide + (struct-out YMD) + (struct-out HMSN) + Month) + +(require + "../base/types.rkt") + +(require "structs.rkt" +) diff --git a/icfp-2016/benchmark/gregor/post/time.rkt b/icfp-2016/benchmark/gregor/post/time.rkt new file mode 100644 index 0000000..22618a5 --- /dev/null +++ b/icfp-2016/benchmark/gregor/post/time.rkt @@ -0,0 +1,89 @@ +#lang typed/racket/base +(require trivial/no-colon) + +;; Working with Time objects + +(provide;/contract + make-time ;(->i ([hour (integer-in 0 23)]) + ; ([minute (integer-in 0 59)] + ; [second (integer-in 0 59)] + ; [nanosecond (integer-in 0 (sub1 NS/SECOND))]) + ; [t time?])] + time->hmsn ; (-> time? HMSN?)] + time->ns ; (-> time? (integer-in 0 (sub1 NS/DAY)))] + day-ns->time ; (-> (integer-in 0 (sub1 NS/DAY)) time?)] + time->iso8601 ; (-> time? string?)] + time=? ; (-> time? time? boolean?)] + time time? time? boolean?)] + time<=? ; (-> time? time? boolean?)] +) + +;; ----------------------------------------------------------------------------- + +(require + (only-in racket/format ~r) + "core-adapter.rkt" + "gregor-adapter.rkt" + racket/match) +(require + "hmsn.rkt" +) + +;; ============================================================================= + +(: time-equal-proc (-> Time Time Boolean)) +(define (time-equal-proc x y) + (= (Time-ns x) (Time-ns y))) + +(: time-hash-proc (-> Time (-> Natural Integer) Integer)) +(define (time-hash-proc x fn) + (fn (Time-ns x))) + +(: time-write-proc (-> Time Output-Port Any Void)) +(define (time-write-proc t out mode) + (fprintf out "#